mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-07-03 12:32:06 +08:00
152 lines
3.9 KiB
C++
152 lines
3.9 KiB
C++
#include "libyuv.h"
|
|
|
|
#include "selfdrive/ui/qt/util.h"
|
|
|
|
#include "starpilot/ui/screenrecorder/screenrecorder.h"
|
|
|
|
constexpr int BITRATE = 8 * 1024 * 1024;
|
|
constexpr int MAX_DURATION = 1000 * 60 * 5;
|
|
constexpr int SCREEN_WIDTH = 2160;
|
|
constexpr int SCREEN_HEIGHT = 1080;
|
|
|
|
const QDir RECORDINGS_FOLDER("/data/media/screen_recordings");
|
|
|
|
ScreenRecorder::ScreenRecorder(QWidget *parent) : QPushButton(parent) {
|
|
setFixedSize(btn_size, btn_size);
|
|
|
|
rootWidget = topWidget(this);
|
|
|
|
QObject::connect(this, &QPushButton::clicked, this, &ScreenRecorder::toggleRecording);
|
|
QObject::connect(uiState(), &UIState::offroadTransition, this, &ScreenRecorder::stopRecording);
|
|
QObject::connect(uiState(), &UIState::uiUpdate, this, &ScreenRecorder::updateState);
|
|
}
|
|
|
|
void ScreenRecorder::updateState() {
|
|
if (!recording) {
|
|
return;
|
|
}
|
|
|
|
if (QDateTime::currentMSecsSinceEpoch() - startedTime > MAX_DURATION) {
|
|
stopRecording();
|
|
startRecording();
|
|
return;
|
|
}
|
|
|
|
if (captureBuffer.size() != QSize(SCREEN_WIDTH, SCREEN_HEIGHT)) {
|
|
captureBuffer = QImage(SCREEN_WIDTH, SCREEN_HEIGHT, QImage::Format_RGBA8888);
|
|
}
|
|
|
|
QPainter p(&captureBuffer);
|
|
rootWidget->render(&p);
|
|
p.end();
|
|
|
|
imageQueue.push(QImage(captureBuffer));
|
|
}
|
|
|
|
void ScreenRecorder::toggleRecording() {
|
|
recording ? stopRecording() : startRecording();
|
|
}
|
|
|
|
void ScreenRecorder::startRecording() {
|
|
encoder = std::make_unique<OmxEncoder>(
|
|
RECORDINGS_FOLDER.path().toStdString().c_str(),
|
|
SCREEN_WIDTH,
|
|
SCREEN_HEIGHT,
|
|
UI_FREQ,
|
|
BITRATE
|
|
);
|
|
encoder->encoder_open((QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss").toStdString() + ".mp4").c_str());
|
|
|
|
if (!encoder->is_open) {
|
|
encoder.reset();
|
|
return;
|
|
}
|
|
|
|
recording = true;
|
|
|
|
startedTime = QDateTime::currentMSecsSinceEpoch();
|
|
|
|
imageQueue.clear();
|
|
|
|
encodingThread = std::thread(&ScreenRecorder::encodeImage, this);
|
|
|
|
update();
|
|
}
|
|
|
|
void ScreenRecorder::stopRecording() {
|
|
if (!recording) {
|
|
return;
|
|
}
|
|
|
|
recording = false;
|
|
|
|
if (encodingThread.joinable()) {
|
|
encodingThread.join();
|
|
}
|
|
|
|
if (encoder) {
|
|
encoder->encoder_close();
|
|
encoder.reset();
|
|
}
|
|
|
|
update();
|
|
}
|
|
|
|
void ScreenRecorder::encodeImage() {
|
|
while (recording) {
|
|
QImage image;
|
|
if (imageQueue.pop_wait_for(image, std::chrono::milliseconds(1000))) {
|
|
uint64_t currentTimestamp = nanos_since_boot();
|
|
|
|
if (image.format() != QImage::Format_RGBA8888) {
|
|
image = image.convertToFormat(QImage::Format_RGBA8888);
|
|
}
|
|
|
|
const uint8_t *bits = image.constBits();
|
|
if (bits) {
|
|
encoder->encode_frame_rgba(bits, SCREEN_WIDTH, SCREEN_HEIGHT, currentTimestamp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ScreenRecorder::paintEvent(QPaintEvent *event) {
|
|
QPainter p(this);
|
|
p.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
|
|
|
|
if (recording) {
|
|
qint64 elapsed = QDateTime::currentMSecsSinceEpoch() - startedTime;
|
|
|
|
qreal phase = (elapsed % 2000) / 2000.0 * 2 * M_PI;
|
|
qreal alphaFactor = 0.5 + 0.5 * sin(phase);
|
|
|
|
QColor glowColor = redColor();
|
|
glowColor.setAlphaF(0.3 + 0.7 * alphaFactor);
|
|
|
|
int glowWidth = 8 + static_cast<int>(2 * alphaFactor);
|
|
|
|
p.setBrush(blackColor(166));
|
|
p.setFont(InterFont(25, QFont::Bold));
|
|
p.setPen(QPen(glowColor, glowWidth));
|
|
} else {
|
|
p.setBrush(blackColor(166));
|
|
p.setFont(InterFont(25, QFont::DemiBold));
|
|
p.setPen(QPen(redColor(), 8));
|
|
}
|
|
|
|
int centeringOffset = 10;
|
|
|
|
QRect buttonRect(centeringOffset, btn_size / 3, btn_size - centeringOffset * 2, btn_size / 3);
|
|
p.drawRoundedRect(buttonRect, 24, 24);
|
|
|
|
QRect textRect = buttonRect.adjusted(centeringOffset, 0, -centeringOffset, 0);
|
|
p.setPen(QPen(whiteColor(), 6));
|
|
p.drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, recording ? tr("RECORDING") : tr("RECORD"));
|
|
|
|
if (!recording) {
|
|
p.setBrush(redColor(166));
|
|
p.setPen(Qt::NoPen);
|
|
p.drawEllipse(QPoint(buttonRect.right() - btn_size / 10 - centeringOffset, buttonRect.center().y()), btn_size / 10, btn_size / 10);
|
|
}
|
|
}
|