diff --git a/QtScrcpy/dialog.cpp b/QtScrcpy/dialog.cpp index db67f0a..c4a21a6 100644 --- a/QtScrcpy/dialog.cpp +++ b/QtScrcpy/dialog.cpp @@ -74,6 +74,10 @@ void Dialog::initUI() ui->videoSizeBox->addItem("1080"); ui->videoSizeBox->addItem("native"); ui->videoSizeBox->setCurrentIndex(1); + + ui->formatBox->addItem("mp4"); + ui->formatBox->addItem("mkv"); + ui->videoSizeBox->setCurrentIndex(0); } void Dialog::on_updateDevice_clicked() @@ -92,8 +96,9 @@ void Dialog::on_startServerBtn_clicked() QString fileDir(ui->recordPathEdt->text().trimmed()); if (!fileDir.isEmpty()) { QDateTime dateTime = QDateTime::currentDateTime(); - QString fileName = dateTime.toString("_yyyyMMdd_hhmmss.zzz"); - fileName = windowTitle() + fileName + ".mp4"; + QString fileName = dateTime.toString("_yyyyMMdd_hhmmss_zzz"); + QString ext = ui->formatBox->currentText().trimmed(); + fileName = windowTitle() + fileName + "." + ext; QDir dir(fileDir); absFilePath = dir.absoluteFilePath(fileName); } diff --git a/QtScrcpy/dialog.ui b/QtScrcpy/dialog.ui index a2b8cea..55bddf0 100644 --- a/QtScrcpy/dialog.ui +++ b/QtScrcpy/dialog.ui @@ -6,19 +6,19 @@ 0 0 - 502 + 639 600 - 502 + 520 0 - 502 + 639 16777215 @@ -158,6 +158,20 @@ Config + + + + record save path: + + + + + + + format: + + + @@ -165,6 +179,13 @@ + + + + bit rate: + + + @@ -182,28 +203,17 @@ - - - - bit rate: - - + + - - - - record save path: - - - - + true - + select path diff --git a/QtScrcpy/recorder/recorder.cpp b/QtScrcpy/recorder/recorder.cpp index e9807fc..ae19bda 100644 --- a/QtScrcpy/recorder/recorder.cpp +++ b/QtScrcpy/recorder/recorder.cpp @@ -1,4 +1,5 @@ #include +#include #include "recorder.h" @@ -16,6 +17,7 @@ static const AVRational SCRCPY_TIME_BASE = {1, 1000000}; // timestamps in us Recorder::Recorder(const QString& fileName) : m_fileName(fileName) + , m_format(guessRecordFormat(fileName)) { } @@ -30,11 +32,18 @@ void Recorder::setFrameSize(const QSize &declaredFrameSize) m_declaredFrameSize = declaredFrameSize; } +void Recorder::setFormat(Recorder::RecorderFormat format) +{ + m_format = format; +} + bool Recorder::open(AVCodec *inputCodec) { - const AVOutputFormat* mp4 = findMp4Muxer(); - if (!mp4) { - qCritical("Could not find mp4 muxer"); + QString formatName = recorderGetFormatName(m_format); + Q_ASSERT(!formatName.isEmpty()); + const AVOutputFormat* format = findMuxer(formatName.toUtf8()); + if (!format) { + qCritical("Could not find muxer"); return false; } @@ -49,7 +58,7 @@ bool Recorder::open(AVCodec *inputCodec) // still expects a pointer-to-non-const (it has not be updated accordingly) // - m_formatCtx->oformat = (AVOutputFormat*)mp4; + m_formatCtx->oformat = (AVOutputFormat*)format; AVStream* outStream = avformat_new_stream(m_formatCtx, inputCodec); if (!outStream) { @@ -115,7 +124,7 @@ bool Recorder::write(AVPacket *packet) return av_write_frame(m_formatCtx, packet) >= 0; } -const AVOutputFormat *Recorder::findMp4Muxer() +const AVOutputFormat *Recorder::findMuxer(const char* name) { #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100) void* opaque = Q_NULLPTR; @@ -127,8 +136,8 @@ const AVOutputFormat *Recorder::findMp4Muxer() #else outFormat = av_oformat_next(outFormat); #endif - // until null or with name "mp4" - } while (outFormat && strcmp(outFormat->name, "mp4")); + // until null or with name "name" + } while (outFormat && strcmp(outFormat->name, name)); return outFormat; } @@ -167,3 +176,29 @@ void Recorder::recorderRescalePacket(AVPacket *packet) AVStream *ostream = m_formatCtx->streams[0]; av_packet_rescale_ts(packet, SCRCPY_TIME_BASE, ostream->time_base); } + +QString Recorder::recorderGetFormatName(Recorder::RecorderFormat format) +{ + switch (format) { + case RECORDER_FORMAT_MP4: return "mp4"; + case RECORDER_FORMAT_MKV: return "matroska"; + default: return ""; + } +} + +Recorder::RecorderFormat Recorder::guessRecordFormat(const QString &fileName) +{ + if (4 > fileName.length()) { + return Recorder::RECORDER_FORMAT_NULL; + } + QFileInfo fileInfo = QFileInfo(fileName); + QString ext = fileInfo.suffix(); + if (0 == ext.compare("mp4")) { + return Recorder::RECORDER_FORMAT_MP4; + } + if (0 == ext.compare("mkv")) { + return Recorder::RECORDER_FORMAT_MKV; + } + + return Recorder::RECORDER_FORMAT_NULL; +} diff --git a/QtScrcpy/recorder/recorder.h b/QtScrcpy/recorder/recorder.h index 8183db6..31dfc63 100644 --- a/QtScrcpy/recorder/recorder.h +++ b/QtScrcpy/recorder/recorder.h @@ -11,24 +11,34 @@ extern "C" class Recorder { public: + enum RecorderFormat { + RECORDER_FORMAT_NULL = 0, + RECORDER_FORMAT_MP4, + RECORDER_FORMAT_MKV, + }; + Recorder(const QString& fileName); virtual ~Recorder(); void setFrameSize(const QSize& declaredFrameSize); + void setFormat(Recorder::RecorderFormat format); bool open(AVCodec* inputCodec); void close(); bool write(AVPacket* packet); private: - const AVOutputFormat* findMp4Muxer(); + const AVOutputFormat* findMuxer(const char* name); bool recorderWriteHeader(AVPacket* packet); void recorderRescalePacket(AVPacket *packet); + QString recorderGetFormatName(Recorder::RecorderFormat format); + RecorderFormat guessRecordFormat(const QString& fileName); private: QString m_fileName = ""; AVFormatContext* m_formatCtx = Q_NULLPTR; QSize m_declaredFrameSize; bool m_headerWritten = false; + RecorderFormat m_format = RECORDER_FORMAT_NULL; }; #endif // RECORDER_H diff --git a/QtScrcpy/videoform.cpp b/QtScrcpy/videoform.cpp index 14416e1..63cf458 100644 --- a/QtScrcpy/videoform.cpp +++ b/QtScrcpy/videoform.cpp @@ -13,11 +13,11 @@ #include #include "videoform.h" +#include "recorder.h" #include "ui_videoform.h" #include "iconhelper.h" #include "toolform.h" #include "controlevent.h" -#include "recorder.h" #include "mousetap/mousetap.h" VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate, const QString& fileName, QWidget *parent) : diff --git a/QtScrcpy/videoform.h b/QtScrcpy/videoform.h index 3cd7994..fe048c9 100644 --- a/QtScrcpy/videoform.h +++ b/QtScrcpy/videoform.h @@ -44,7 +44,7 @@ private: void initUI(); void initSignals(); void showToolFrom(bool show = true); - void postKeyCodeClick(AndroidKeycode keycode); + void postKeyCodeClick(AndroidKeycode keycode); protected: void mousePressEvent(QMouseEvent *event);