parent
9395bd5399
commit
57ef078106
19 changed files with 194 additions and 71 deletions
@ -1,22 +1,25 @@ |
||||
Import('env', 'arch', 'common', 'messaging', 'visionipc', 'cereal') |
||||
Import('qt_env', 'ui_libs', 'qt_libs', 'qt_ui', 'asset_obj', 'arch', 'common', 'messaging', 'visionipc', 'cereal') |
||||
|
||||
replay_env = env.Clone() |
||||
replay_env = qt_env.Clone() |
||||
replay_env['CCFLAGS'] += ['-Wno-deprecated-declarations'] |
||||
|
||||
base_frameworks = [] |
||||
base_libs = [common, messaging, cereal, visionipc, 'm', 'ssl', 'crypto', 'pthread'] |
||||
base_frameworks = replay_env["FRAMEWORKS"] |
||||
base_libs = replay_env["LIBS"] |
||||
|
||||
if arch == "Darwin": |
||||
base_frameworks.append('OpenCL') |
||||
else: |
||||
base_libs.append('OpenCL') |
||||
|
||||
if arch == 'larch64': |
||||
base_libs.append('EGL') |
||||
|
||||
replay_lib_src = ["replay.cc", "consoleui.cc", "camera.cc", "filereader.cc", "logreader.cc", "framereader.cc", |
||||
"route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc"] |
||||
"route.cc", "util.cc", "seg_mgr.cc", "timeline.cc", "api.cc", "clip/recorder/widget.cc", "clip/recorder/ffmpeg.cc", "clip/application.cc"] |
||||
replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEWORKS=base_frameworks) |
||||
Export('replay_lib') |
||||
replay_libs = [replay_lib, 'avutil', 'avcodec', 'avformat', 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs |
||||
replay_env.Program("replay", ["main.cc"], LIBS=replay_libs, FRAMEWORKS=base_frameworks) |
||||
replay_libs = [replay_lib, cereal, 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs + qt_libs + ui_libs + qt_ui |
||||
replay_env.Program("replay", ["main.cc", asset_obj], LIBS=replay_libs, FRAMEWORKS=base_frameworks) |
||||
|
||||
if GetOption('extras'): |
||||
replay_env.Program('tests/test_replay', ['tests/test_replay.cc'], LIBS=replay_libs) |
||||
|
@ -0,0 +1,51 @@ |
||||
#include "tools/replay/clip/application.h" |
||||
|
||||
#include <QApplication> |
||||
#include <QTranslator> |
||||
#include <selfdrive/ui/qt/util.h> |
||||
#include <selfdrive/ui/qt/window.h> |
||||
|
||||
#include "recorder/widget.h" |
||||
|
||||
Application::Application() { |
||||
|
||||
} |
||||
|
||||
Application::~Application() { |
||||
|
||||
} |
||||
|
||||
int Application::exec(int argc, char *argv[]) { |
||||
initApp(argc, argv); |
||||
|
||||
QApplication a(argc, argv); |
||||
|
||||
QString outputFile = "/Users/trey/Desktop/out.mp4"; |
||||
|
||||
QTranslator translator; |
||||
QString translation_file = QString::fromStdString(Params().get("LanguageSetting")); |
||||
if (!translator.load(QString(":/%1").arg(translation_file)) && translation_file.length()) { |
||||
qCritical() << "Failed to load translation file:" << translation_file; |
||||
} |
||||
|
||||
a.installTranslator(&translator); |
||||
|
||||
OnroadWindow w; |
||||
|
||||
QThread recorderThread; |
||||
Recorder recorder; |
||||
recorder.moveToThread(&recorderThread); |
||||
QObject::connect(&recorderThread, &QThread::finished, &recorder, &QObject::deleteLater); |
||||
QObject::connect(&w, &OnroadWindow::drewOnroadFrame, &recorder, &Recorder::saveFrame, Qt::QueuedConnection); |
||||
recorderThread.start(); |
||||
|
||||
w.setAttribute(Qt::WA_DontShowOnScreen); |
||||
w.setAttribute(Qt::WA_Mapped); |
||||
w.setAttribute(Qt::WA_NoSystemBackground); |
||||
w.resize(DEVICE_SCREEN_SIZE); |
||||
setMainWindow(&w); |
||||
|
||||
return a.exec(); |
||||
} |
||||
|
||||
|
@ -0,0 +1,9 @@ |
||||
#pragma once |
||||
|
||||
|
||||
class Application { |
||||
public: |
||||
Application(); |
||||
~Application(); |
||||
int exec(int argc, char* argv[]); |
||||
}; |
@ -1,4 +1,4 @@ |
||||
#include "selfdrive/ui/qt/recorder/recorder.h" |
||||
#include "tools/replay/clip/recorder/ffmpeg.h" |
||||
|
||||
#include <QDebug> |
||||
|
@ -0,0 +1,46 @@ |
||||
#include "tools/replay/clip/recorder/widget.h" |
||||
|
||||
#include "tools/replay/clip/recorder/ffmpeg.h" |
||||
|
||||
Recorder::~Recorder() { |
||||
fprintf(stderr, "closing\n"); |
||||
QObject::~QObject(); |
||||
} |
||||
|
||||
void Recorder::saveFrame(QImage *frame) { |
||||
QMutexLocker locker(&mutex); |
||||
frameQueue.enqueue(frame); // Add frame to queue
|
||||
if (!isProcessing) { |
||||
isProcessing = true; |
||||
QMetaObject::invokeMethod(this, &Recorder::processQueue, Qt::QueuedConnection); |
||||
} |
||||
} |
||||
|
||||
void Recorder::processQueue() { |
||||
while (true) { |
||||
QImage *frame; |
||||
{ |
||||
QMutexLocker locker(&mutex); |
||||
if (frameQueue.isEmpty() || !keepRunning) { |
||||
isProcessing = false; |
||||
return; |
||||
} |
||||
frame = frameQueue.dequeue(); |
||||
} |
||||
// Save the frame (this runs in the worker thread)
|
||||
static int frameCount = 0; |
||||
if (frameCount == 0 && !encoder.startRecording()) { |
||||
fprintf(stderr, "failed to start record\n"); |
||||
} |
||||
fprintf(stderr, "processing frame %d: %p\n", frameCount++, &frame); |
||||
if (!encoder.writeFrame(frame->convertToFormat(QImage::Format_ARGB32_Premultiplied))) { |
||||
fprintf(stderr, "did not write\n"); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void Recorder::stop() { |
||||
QMutexLocker locker(&mutex); |
||||
keepRunning = false; |
||||
} |
||||
|
@ -0,0 +1,29 @@ |
||||
#pragma once |
||||
|
||||
#include <QImage> |
||||
#include <QObject> |
||||
#include <QQueue> |
||||
#include <selfdrive/ui/ui.h> |
||||
#include <selfdrive/ui/qt/qt_window.h> |
||||
|
||||
#include "ffmpeg.h" |
||||
|
||||
class Recorder : public QObject { |
||||
Q_OBJECT |
||||
|
||||
public: |
||||
Recorder(QObject *parent = nullptr) : QObject(parent) {} |
||||
~Recorder() override; |
||||
|
||||
public slots: |
||||
void saveFrame(QImage *frame); |
||||
void stop(); |
||||
|
||||
private: |
||||
FFmpegEncoder encoder = FFmpegEncoder("/Users/trey/Desktop/out.mp4", DEVICE_SCREEN_SIZE.width(), DEVICE_SCREEN_SIZE.height(), UI_FREQ); |
||||
QQueue<QImage *> frameQueue; |
||||
QMutex mutex; |
||||
bool isProcessing = false; |
||||
bool keepRunning = true; |
||||
void processQueue(); |
||||
}; |
Loading…
Reference in new issue