update:mp4录制功能完善

This commit is contained in:
Barry 2019-01-27 13:37:49 +08:00
parent ea9deb3b9f
commit 79d5a0ca77
11 changed files with 179 additions and 90 deletions

View file

@ -111,7 +111,6 @@ static qint32 readPacketWithMeta(void *opaque, uint8_t *buf, int bufSize) {
// It is followed by <packet_size> 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()

View file

@ -59,7 +59,7 @@ private:
Frames* m_frames;
// for recorder
Recorder* m_recorder;
Recorder* m_recorder = Q_NULLPTR;
ReceiverState m_receiverState;
};

View file

@ -1,6 +1,7 @@
#include <QFile>
#include <QTime>
#include <QKeyEvent>
#include <QFileDialog>
#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);
}

View file

@ -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();

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>560</width>
<height>486</height>
<height>577</height>
</rect>
</property>
<property name="minimumSize">
@ -26,18 +26,62 @@
<string notr="true">QtScrcpy</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="2" column="0">
<widget class="QTextEdit" name="outEdit">
<property name="documentTitle">
<string/>
</property>
<property name="readOnly">
<bool>true</bool>
<item row="1" column="0">
<widget class="QGroupBox" name="usbGroupBox">
<property name="title">
<string>USB line</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="3" column="2">
<widget class="QPushButton" name="getIPBtn">
<property name="text">
<string>get device ip</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="stopServerBtn">
<property name="text">
<string>stop server</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="updateDevice">
<property name="text">
<string>update device</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QPushButton" name="startAdbdBtn">
<property name="text">
<string>start adbd</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>device serial:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="serialBox"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="startServerBtn">
<property name="text">
<string>start server</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox">
<item row="2" column="0">
<widget class="QGroupBox" name="wirelessGroupBox">
<property name="title">
<string>Wireless</string>
</property>
@ -98,40 +142,26 @@
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="topGroupBox">
<property name="title">
<string>USB line</string>
<item row="3" column="0">
<widget class="QTextEdit" name="outEdit">
<property name="documentTitle">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="1">
<widget class="QComboBox" name="serialBox"/>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="stopServerBtn">
<property name="text">
<string>stop server</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="startServerBtn">
<property name="text">
<string>start server</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>device serial:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>bit rate:</string>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="configGroupBox">
<property name="title">
<string>Config</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="3">
<widget class="QComboBox" name="videoSizeBox">
<property name="toolTip">
<string/>
</property>
</widget>
</item>
@ -152,31 +182,31 @@
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="videoSizeBox">
<property name="toolTip">
<string/>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>bit rate:</string>
</property>
</widget>
</item>
<item row="4" column="3">
<widget class="QPushButton" name="startAdbdBtn">
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>start adbd</string>
<string>record save path:</string>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QPushButton" name="getIPBtn">
<property name="text">
<string>get device ip</string>
<item row="1" column="1" colspan="2">
<widget class="QLineEdit" name="recordPathEdt">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="updateDevice">
<item row="1" column="3">
<widget class="QPushButton" name="selectRecordPathBtn">
<property name="text">
<string>update device</string>
<string>select path</string>
</property>
</widget>
</item>

View file

@ -84,6 +84,6 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS
}
}
if (QtFatalMsg == type) {
abort();
//abort();
}
}

View file

@ -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)

View file

@ -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);

View file

@ -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();

View file

@ -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();

View file

@ -1,5 +1,5 @@
mp4录制如何保证正确收到最后的数据
mp4录制server启动时间翻译
横屏防止工具窗口超出屏幕
工具栏扩展(模拟点击指定次数等)
模拟点击改用手指(注意:辅助按键就都没了)