From 4557795f14e2f080c6a04154299c268c86a0251f Mon Sep 17 00:00:00 2001 From: Barry <870709864@qq.com> Date: Sun, 27 Jan 2019 13:37:49 +0800 Subject: [PATCH] =?UTF-8?q?update:mp4=E5=BD=95=E5=88=B6=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- QtScrcpy/decoder/decoder.cpp | 26 +++--- QtScrcpy/decoder/decoder.h | 2 +- QtScrcpy/dialog.cpp | 33 +++++++- QtScrcpy/dialog.h | 4 + QtScrcpy/dialog.ui | 144 ++++++++++++++++++++------------- QtScrcpy/main.cpp | 2 +- QtScrcpy/recorder/recorder.cpp | 26 ++++-- QtScrcpy/recorder/recorder.h | 3 +- QtScrcpy/videoform.cpp | 23 ++++-- QtScrcpy/videoform.h | 2 +- TODO.txt | 4 +- 11 files changed, 179 insertions(+), 90 deletions(-) diff --git a/QtScrcpy/decoder/decoder.cpp b/QtScrcpy/decoder/decoder.cpp index 45c397d..860a3b8 100644 --- a/QtScrcpy/decoder/decoder.cpp +++ b/QtScrcpy/decoder/decoder.cpp @@ -111,7 +111,6 @@ static qint32 readPacketWithMeta(void *opaque, uint8_t *buf, int bufSize) { // It is followed by bytes containing the packet/frame. if (!state->remaining) { -#define HEADER_SIZE 12 quint8 header[HEADER_SIZE]; qint32 r = decoder->recvData(header, HEADER_SIZE); if (r == -1) { @@ -121,7 +120,9 @@ static qint32 readPacketWithMeta(void *opaque, uint8_t *buf, int bufSize) { return AVERROR_EOF; } // no partial read (net_recv_all()) - Q_ASSERT(r == HEADER_SIZE); + if (r != HEADER_SIZE) { + return AVERROR(ENOMEM); + } uint64_t pts = bufferRead64be(header); state->remaining = bufferRead32be(&header[8]); @@ -155,9 +156,16 @@ static qint32 readPacketWithMeta(void *opaque, uint8_t *buf, int bufSize) { static qint32 readRawPacket(void *opaque, quint8 *buf, qint32 bufSize) { Decoder *decoder = (Decoder*)opaque; if (decoder) { - return decoder->recvData(buf, bufSize); + qint32 len = decoder->recvData(buf, bufSize); + if (len == -1) { + return AVERROR(errno); + } + if (len == 0) { + return AVERROR_EOF; + } + return len; } - return 0; + return AVERROR_EOF; } void Decoder::setDeviceSocket(DeviceSocket* deviceSocket) @@ -177,15 +185,9 @@ qint32 Decoder::recvData(quint8* buf, qint32 bufSize) } if (m_deviceSocket) { qint32 len = m_deviceSocket->subThreadRecvData(buf, bufSize); - if (len == -1) { - return AVERROR(errno); - } - if (len == 0) { - return AVERROR_EOF; - } return len; } - return AVERROR_EOF; + return 0; } bool Decoder::startDecode() @@ -204,7 +206,7 @@ void Decoder::stopDecode() if (m_frames) { m_frames->stop(); } - //wait(); + wait(); } Decoder::ReceiverState *Decoder::getReceiverState() diff --git a/QtScrcpy/decoder/decoder.h b/QtScrcpy/decoder/decoder.h index a483b31..e5d704f 100644 --- a/QtScrcpy/decoder/decoder.h +++ b/QtScrcpy/decoder/decoder.h @@ -59,7 +59,7 @@ private: Frames* m_frames; // for recorder - Recorder* m_recorder; + Recorder* m_recorder = Q_NULLPTR; ReceiverState m_receiverState; }; diff --git a/QtScrcpy/dialog.cpp b/QtScrcpy/dialog.cpp index d2e75f0..ec92a5e 100644 --- a/QtScrcpy/dialog.cpp +++ b/QtScrcpy/dialog.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "dialog.h" #include "ui_dialog.h" @@ -86,10 +87,22 @@ void Dialog::on_updateDevice_clicked() void Dialog::on_startServerBtn_clicked() { if (!m_videoForm) { + QString absFilePath; + QString fileDir(ui->recordPathEdt->text().trimmed()); + if (!fileDir.isEmpty()) { + QDateTime dateTime = QDateTime::currentDateTime(); + QString fileName = dateTime.toString("_yyyyMMdd_hhmmss.zzz"); + fileName = windowTitle() + fileName + ".mp4"; + QDir dir(fileDir); + absFilePath = dir.absoluteFilePath(fileName); + } + quint32 bitRate = ui->bitRateBox->currentText().trimmed().toUInt(); // this is ok that "native" toUshort is 0 quint16 videoSize = ui->videoSizeBox->currentText().trimmed().toUShort(); - m_videoForm = new VideoForm(ui->serialBox->currentText().trimmed(), videoSize, bitRate); + m_videoForm = new VideoForm(ui->serialBox->currentText().trimmed(), videoSize, bitRate, absFilePath); + + outLog("start server..."); } m_videoForm->show(); } @@ -98,6 +111,7 @@ void Dialog::on_stopServerBtn_clicked() { if (m_videoForm) { m_videoForm->close(); + outLog("stop server...", false); } } @@ -180,3 +194,20 @@ void Dialog::on_wirelessDisConnectBtn_clicked() adbArgs << addr; m_adb.execute("", adbArgs); } + +void Dialog::on_selectRecordPathBtn_clicked() +{ + QFileDialog::Options options = QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly; + QString directory = QFileDialog::getExistingDirectory(this, + tr("select path"), + "", + options); + if (!directory.isEmpty()) { + ui->recordPathEdt->setText(directory); + } +} + +void Dialog::on_recordPathEdt_textChanged(const QString &arg1) +{ + ui->recordPathEdt->setToolTip(arg1); +} diff --git a/QtScrcpy/dialog.h b/QtScrcpy/dialog.h index 09ba9a8..524977c 100644 --- a/QtScrcpy/dialog.h +++ b/QtScrcpy/dialog.h @@ -37,6 +37,10 @@ private slots: void on_wirelessDisConnectBtn_clicked(); + void on_selectRecordPathBtn_clicked(); + + void on_recordPathEdt_textChanged(const QString &arg1); + private: bool checkAdbRun(); void initUI(); diff --git a/QtScrcpy/dialog.ui b/QtScrcpy/dialog.ui index 46a4dd3..e96930c 100644 --- a/QtScrcpy/dialog.ui +++ b/QtScrcpy/dialog.ui @@ -7,7 +7,7 @@ 0 0 560 - 486 + 577 @@ -26,18 +26,62 @@ QtScrcpy - - - - - - - true + + + + USB line + + + + + get device ip + + + + + + + stop server + + + + + + + update device + + + + + + + start adbd + + + + + + + device serial: + + + + + + + + + + start server + + + + - - + + Wireless @@ -98,40 +142,26 @@ - - - - USB line + + + + - - - - - - - - stop server - - - - - - - start server - - - - - - - device serial: - - - - - - - bit rate: + + true + + + + + + + Config + + + + + + @@ -152,31 +182,31 @@ - - - - + + + + bit rate: - - + + - start adbd + record save path: - - - - get device ip + + + + true - - + + - update device + select path diff --git a/QtScrcpy/main.cpp b/QtScrcpy/main.cpp index 4e5174a..6e208e8 100644 --- a/QtScrcpy/main.cpp +++ b/QtScrcpy/main.cpp @@ -84,6 +84,6 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS } } if (QtFatalMsg == type) { - abort(); + //abort(); } } diff --git a/QtScrcpy/recorder/recorder.cpp b/QtScrcpy/recorder/recorder.cpp index 20888d6..702d0be 100644 --- a/QtScrcpy/recorder/recorder.cpp +++ b/QtScrcpy/recorder/recorder.cpp @@ -2,9 +2,8 @@ #include "recorder.h" -Recorder::Recorder(const QString& fileName, const QSize& declaredFrameSize) +Recorder::Recorder(const QString& fileName) : m_fileName(fileName) - , m_declaredFrameSize(declaredFrameSize) { } @@ -14,6 +13,11 @@ Recorder::~Recorder() } +void Recorder::setFrameSize(const QSize &declaredFrameSize) +{ + m_declaredFrameSize = declaredFrameSize; +} + bool Recorder::open(AVCodec *inputCodec) { const AVOutputFormat* mp4 = findMp4Muxer(); @@ -38,6 +42,7 @@ bool Recorder::open(AVCodec *inputCodec) AVStream* outStream = avformat_new_stream(m_formatCtx, inputCodec); if (!outStream) { avformat_free_context(m_formatCtx); + m_formatCtx = Q_NULLPTR; return false; } @@ -70,6 +75,7 @@ bool Recorder::open(AVCodec *inputCodec) qCritical(QString("Failed to open output file: %1").arg(m_fileName).toUtf8().toStdString().c_str()); // ostream will be cleaned up during context cleaning avformat_free_context(m_formatCtx); + m_formatCtx = Q_NULLPTR; return false; } @@ -78,6 +84,7 @@ bool Recorder::open(AVCodec *inputCodec) qCritical(QString("Failed to write header to %1").arg(m_fileName).toUtf8().toStdString().c_str()); avio_closep(&m_formatCtx->pb); avformat_free_context(m_formatCtx); + m_formatCtx = Q_NULLPTR; return false; } @@ -86,12 +93,17 @@ bool Recorder::open(AVCodec *inputCodec) void Recorder::close() { - int ret = av_write_trailer(m_formatCtx); - if (ret < 0) { - qCritical(QString("Failed to write trailer to %1").arg(m_fileName).toUtf8().toStdString().c_str()); + if (Q_NULLPTR != m_formatCtx) { + int ret = av_write_trailer(m_formatCtx); + if (ret < 0) { + qCritical(QString("Failed to write trailer to %1").arg(m_fileName).toUtf8().toStdString().c_str()); + } else { + qInfo(QString("success record %1").arg(m_fileName).toStdString().c_str()); + } + avio_close(m_formatCtx->pb); + avformat_free_context(m_formatCtx); + m_formatCtx = Q_NULLPTR; } - avio_close(m_formatCtx->pb); - avformat_free_context(m_formatCtx); } bool Recorder::write(AVPacket *packet) diff --git a/QtScrcpy/recorder/recorder.h b/QtScrcpy/recorder/recorder.h index ceec666..00c5ec0 100644 --- a/QtScrcpy/recorder/recorder.h +++ b/QtScrcpy/recorder/recorder.h @@ -11,9 +11,10 @@ extern "C" class Recorder { public: - Recorder(const QString& fileName, const QSize& declaredFrameSize); + Recorder(const QString& fileName); virtual ~Recorder(); + void setFrameSize(const QSize& declaredFrameSize); bool open(AVCodec* inputCodec); void close(); bool write(AVPacket* packet); diff --git a/QtScrcpy/videoform.cpp b/QtScrcpy/videoform.cpp index f2b1a3d..0cc4823 100644 --- a/QtScrcpy/videoform.cpp +++ b/QtScrcpy/videoform.cpp @@ -19,7 +19,7 @@ #include "controlevent.h" #include "recorder.h" -VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate,QWidget *parent) : +VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate, const QString& fileName, QWidget *parent) : QWidget(parent), ui(new Ui::videoForm), m_serial(serial), @@ -30,10 +30,12 @@ VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate,QWi initUI(); m_server = new Server(); - m_recorder = new Recorder("./test.mp4", QSize(600, 300)); m_frames.init(); m_decoder.setFrames(&m_frames); - m_decoder.setRecoder(m_recorder); + if (!fileName.trimmed().isEmpty()) { + m_recorder = new Recorder(fileName.trimmed()); + m_decoder.setRecoder(m_recorder); + } initSignals(); @@ -56,11 +58,13 @@ VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate,QWi VideoForm::~VideoForm() { + m_server->stop(); + // server must stop before decoder, because decoder block main thread m_decoder.stopDecode(); - m_server->stop(); - m_decoder.wait(); delete m_server; - delete m_recorder; + if (m_recorder) { + delete m_recorder; + } m_frames.deInit(); delete ui; } @@ -132,7 +136,12 @@ void VideoForm::initSignals() setWindowTitle(deviceName); updateShowSize(size); - // init decode + // init recorder + if (m_recorder) { + m_recorder->setFrameSize(size); + } + + // init decoder m_decoder.setDeviceSocket(m_server->getDeviceSocket()); m_decoder.startDecode(); diff --git a/QtScrcpy/videoform.h b/QtScrcpy/videoform.h index 53e7105..1ef4444 100644 --- a/QtScrcpy/videoform.h +++ b/QtScrcpy/videoform.h @@ -22,7 +22,7 @@ class VideoForm : public QWidget Q_OBJECT public: - explicit VideoForm(const QString& serial, quint16 maxSize = 720, quint32 bitRate = 8000000, QWidget *parent = 0); + explicit VideoForm(const QString& serial, quint16 maxSize = 720, quint32 bitRate = 8000000, const QString& fileName = "", QWidget *parent = 0); ~VideoForm(); void switchFullScreen(); diff --git a/TODO.txt b/TODO.txt index b5bd9df..2ea2e95 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,5 @@ -mp4录制如何保证正确收到最后的数据 - +mp4录制:server启动时间,翻译 +横屏防止工具窗口超出屏幕 工具栏扩展(模拟点击指定次数等) 模拟点击改用手指(注意:辅助按键就都没了)