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'] |
replay_env['CCFLAGS'] += ['-Wno-deprecated-declarations'] |
||||||
|
|
||||||
base_frameworks = [] |
base_frameworks = replay_env["FRAMEWORKS"] |
||||||
base_libs = [common, messaging, cereal, visionipc, 'm', 'ssl', 'crypto', 'pthread'] |
base_libs = replay_env["LIBS"] |
||||||
|
|
||||||
if arch == "Darwin": |
if arch == "Darwin": |
||||||
base_frameworks.append('OpenCL') |
base_frameworks.append('OpenCL') |
||||||
else: |
else: |
||||||
base_libs.append('OpenCL') |
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", |
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) |
replay_lib = replay_env.Library("replay", replay_lib_src, LIBS=base_libs, FRAMEWORKS=base_frameworks) |
||||||
Export('replay_lib') |
Export('replay_lib') |
||||||
replay_libs = [replay_lib, 'avutil', 'avcodec', 'avformat', 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs |
replay_libs = [replay_lib, cereal, 'bz2', 'zstd', 'curl', 'yuv', 'ncurses'] + base_libs + qt_libs + ui_libs + qt_ui |
||||||
replay_env.Program("replay", ["main.cc"], LIBS=replay_libs, FRAMEWORKS=base_frameworks) |
replay_env.Program("replay", ["main.cc", asset_obj], LIBS=replay_libs, FRAMEWORKS=base_frameworks) |
||||||
|
|
||||||
if GetOption('extras'): |
if GetOption('extras'): |
||||||
replay_env.Program('tests/test_replay', ['tests/test_replay.cc'], LIBS=replay_libs) |
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> |
#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