add:录像支持mkv

This commit is contained in:
Barry 2019-06-15 06:45:12 +08:00
commit f02bae1e70
6 changed files with 90 additions and 30 deletions

View file

@ -74,6 +74,10 @@ void Dialog::initUI()
ui->videoSizeBox->addItem("1080"); ui->videoSizeBox->addItem("1080");
ui->videoSizeBox->addItem("native"); ui->videoSizeBox->addItem("native");
ui->videoSizeBox->setCurrentIndex(1); ui->videoSizeBox->setCurrentIndex(1);
ui->formatBox->addItem("mp4");
ui->formatBox->addItem("mkv");
ui->videoSizeBox->setCurrentIndex(0);
} }
void Dialog::on_updateDevice_clicked() void Dialog::on_updateDevice_clicked()
@ -92,8 +96,9 @@ void Dialog::on_startServerBtn_clicked()
QString fileDir(ui->recordPathEdt->text().trimmed()); QString fileDir(ui->recordPathEdt->text().trimmed());
if (!fileDir.isEmpty()) { if (!fileDir.isEmpty()) {
QDateTime dateTime = QDateTime::currentDateTime(); QDateTime dateTime = QDateTime::currentDateTime();
QString fileName = dateTime.toString("_yyyyMMdd_hhmmss.zzz"); QString fileName = dateTime.toString("_yyyyMMdd_hhmmss_zzz");
fileName = windowTitle() + fileName + ".mp4"; QString ext = ui->formatBox->currentText().trimmed();
fileName = windowTitle() + fileName + "." + ext;
QDir dir(fileDir); QDir dir(fileDir);
absFilePath = dir.absoluteFilePath(fileName); absFilePath = dir.absoluteFilePath(fileName);
} }

View file

@ -6,19 +6,19 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>502</width> <width>639</width>
<height>600</height> <height>600</height>
</rect> </rect>
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>502</width> <width>520</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>502</width> <width>639</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
@ -158,6 +158,20 @@
<string>Config</string> <string>Config</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="1" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>record save path:</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_6">
<property name="text">
<string>format</string>
</property>
</widget>
</item>
<item row="0" column="3"> <item row="0" column="3">
<widget class="QComboBox" name="videoSizeBox"> <widget class="QComboBox" name="videoSizeBox">
<property name="toolTip"> <property name="toolTip">
@ -165,6 +179,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>bit rate:</string>
</property>
</widget>
</item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="bitRateBox"> <widget class="QComboBox" name="bitRateBox">
<property name="toolTip"> <property name="toolTip">
@ -182,28 +203,17 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0"> <item row="0" column="5">
<widget class="QLabel" name="label_3"> <widget class="QComboBox" name="formatBox"/>
<property name="text">
<string>bit rate:</string>
</property>
</widget>
</item> </item>
<item row="1" column="0"> <item row="1" column="1" colspan="3">
<widget class="QLabel" name="label_5">
<property name="text">
<string>record save path:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLineEdit" name="recordPathEdt"> <widget class="QLineEdit" name="recordPathEdt">
<property name="readOnly"> <property name="readOnly">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="3"> <item row="1" column="4" colspan="2">
<widget class="QPushButton" name="selectRecordPathBtn"> <widget class="QPushButton" name="selectRecordPathBtn">
<property name="text"> <property name="text">
<string>select path</string> <string>select path</string>

View file

@ -1,4 +1,5 @@
#include <QDebug> #include <QDebug>
#include <QFileInfo>
#include "recorder.h" #include "recorder.h"
@ -16,6 +17,7 @@ static const AVRational SCRCPY_TIME_BASE = {1, 1000000}; // timestamps in us
Recorder::Recorder(const QString& fileName) Recorder::Recorder(const QString& fileName)
: m_fileName(fileName) : m_fileName(fileName)
, m_format(guessRecordFormat(fileName))
{ {
} }
@ -30,11 +32,18 @@ void Recorder::setFrameSize(const QSize &declaredFrameSize)
m_declaredFrameSize = declaredFrameSize; m_declaredFrameSize = declaredFrameSize;
} }
void Recorder::setFormat(Recorder::RecorderFormat format)
{
m_format = format;
}
bool Recorder::open(AVCodec *inputCodec) bool Recorder::open(AVCodec *inputCodec)
{ {
const AVOutputFormat* mp4 = findMp4Muxer(); QString formatName = recorderGetFormatName(m_format);
if (!mp4) { Q_ASSERT(!formatName.isEmpty());
qCritical("Could not find mp4 muxer"); const AVOutputFormat* format = findMuxer(formatName.toUtf8());
if (!format) {
qCritical("Could not find muxer");
return false; return false;
} }
@ -49,7 +58,7 @@ bool Recorder::open(AVCodec *inputCodec)
// still expects a pointer-to-non-const (it has not be updated accordingly) // still expects a pointer-to-non-const (it has not be updated accordingly)
// <https://github.com/FFmpeg/FFmpeg/commit/0694d8702421e7aff1340038559c438b61bb30dd> // <https://github.com/FFmpeg/FFmpeg/commit/0694d8702421e7aff1340038559c438b61bb30dd>
m_formatCtx->oformat = (AVOutputFormat*)mp4; m_formatCtx->oformat = (AVOutputFormat*)format;
AVStream* outStream = avformat_new_stream(m_formatCtx, inputCodec); AVStream* outStream = avformat_new_stream(m_formatCtx, inputCodec);
if (!outStream) { if (!outStream) {
@ -115,7 +124,7 @@ bool Recorder::write(AVPacket *packet)
return av_write_frame(m_formatCtx, packet) >= 0; 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) #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 9, 100)
void* opaque = Q_NULLPTR; void* opaque = Q_NULLPTR;
@ -127,8 +136,8 @@ const AVOutputFormat *Recorder::findMp4Muxer()
#else #else
outFormat = av_oformat_next(outFormat); outFormat = av_oformat_next(outFormat);
#endif #endif
// until null or with name "mp4" // until null or with name "name"
} while (outFormat && strcmp(outFormat->name, "mp4")); } while (outFormat && strcmp(outFormat->name, name));
return outFormat; return outFormat;
} }
@ -167,3 +176,29 @@ void Recorder::recorderRescalePacket(AVPacket *packet)
AVStream *ostream = m_formatCtx->streams[0]; AVStream *ostream = m_formatCtx->streams[0];
av_packet_rescale_ts(packet, SCRCPY_TIME_BASE, ostream->time_base); 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;
}

View file

@ -11,24 +11,34 @@ extern "C"
class Recorder class Recorder
{ {
public: public:
enum RecorderFormat {
RECORDER_FORMAT_NULL = 0,
RECORDER_FORMAT_MP4,
RECORDER_FORMAT_MKV,
};
Recorder(const QString& fileName); Recorder(const QString& fileName);
virtual ~Recorder(); virtual ~Recorder();
void setFrameSize(const QSize& declaredFrameSize); void setFrameSize(const QSize& declaredFrameSize);
void setFormat(Recorder::RecorderFormat format);
bool open(AVCodec* inputCodec); bool open(AVCodec* inputCodec);
void close(); void close();
bool write(AVPacket* packet); bool write(AVPacket* packet);
private: private:
const AVOutputFormat* findMp4Muxer(); const AVOutputFormat* findMuxer(const char* name);
bool recorderWriteHeader(AVPacket* packet); bool recorderWriteHeader(AVPacket* packet);
void recorderRescalePacket(AVPacket *packet); void recorderRescalePacket(AVPacket *packet);
QString recorderGetFormatName(Recorder::RecorderFormat format);
RecorderFormat guessRecordFormat(const QString& fileName);
private: private:
QString m_fileName = ""; QString m_fileName = "";
AVFormatContext* m_formatCtx = Q_NULLPTR; AVFormatContext* m_formatCtx = Q_NULLPTR;
QSize m_declaredFrameSize; QSize m_declaredFrameSize;
bool m_headerWritten = false; bool m_headerWritten = false;
RecorderFormat m_format = RECORDER_FORMAT_NULL;
}; };
#endif // RECORDER_H #endif // RECORDER_H

View file

@ -13,11 +13,11 @@
#include <QMessageBox> #include <QMessageBox>
#include "videoform.h" #include "videoform.h"
#include "recorder.h"
#include "ui_videoform.h" #include "ui_videoform.h"
#include "iconhelper.h" #include "iconhelper.h"
#include "toolform.h" #include "toolform.h"
#include "controlevent.h" #include "controlevent.h"
#include "recorder.h"
#include "mousetap/mousetap.h" #include "mousetap/mousetap.h"
VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate, const QString& fileName, QWidget *parent) : VideoForm::VideoForm(const QString& serial, quint16 maxSize, quint32 bitRate, const QString& fileName, QWidget *parent) :