mirror of
https://github.com/barry-ran/QtScrcpy.git
synced 2025-08-03 14:18:45 +00:00
refactor: stream and decoder&recorder decoupling
This commit is contained in:
parent
ae3b13efc1
commit
74b38e9ac5
7 changed files with 66 additions and 79 deletions
|
@ -8,8 +8,16 @@ Decoder::Decoder(VideoBuffer *vb, QObject *parent) : QObject(parent), m_vb(vb) {
|
||||||
|
|
||||||
Decoder::~Decoder() {}
|
Decoder::~Decoder() {}
|
||||||
|
|
||||||
bool Decoder::open(const AVCodec *codec)
|
bool Decoder::open()
|
||||||
{
|
{
|
||||||
|
// codec
|
||||||
|
AVCodec *codec = Q_NULLPTR;
|
||||||
|
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||||
|
if (!codec) {
|
||||||
|
qCritical("H.264 decoder not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// codec context
|
// codec context
|
||||||
m_codecCtx = avcodec_alloc_context3(codec);
|
m_codecCtx = avcodec_alloc_context3(codec);
|
||||||
if (!m_codecCtx) {
|
if (!m_codecCtx) {
|
||||||
|
@ -26,6 +34,10 @@ bool Decoder::open(const AVCodec *codec)
|
||||||
|
|
||||||
void Decoder::close()
|
void Decoder::close()
|
||||||
{
|
{
|
||||||
|
if (m_vb) {
|
||||||
|
m_vb->interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_codecCtx) {
|
if (!m_codecCtx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -98,13 +110,6 @@ bool Decoder::push(const AVPacket *packet)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Decoder::interrupt()
|
|
||||||
{
|
|
||||||
if (m_vb) {
|
|
||||||
m_vb->interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Decoder::pushFrame()
|
void Decoder::pushFrame()
|
||||||
{
|
{
|
||||||
if (!m_vb) {
|
if (!m_vb) {
|
||||||
|
|
|
@ -15,10 +15,9 @@ public:
|
||||||
Decoder(VideoBuffer *vb, QObject *parent = Q_NULLPTR);
|
Decoder(VideoBuffer *vb, QObject *parent = Q_NULLPTR);
|
||||||
virtual ~Decoder();
|
virtual ~Decoder();
|
||||||
|
|
||||||
bool open(const AVCodec *codec);
|
bool open();
|
||||||
void close();
|
void close();
|
||||||
bool push(const AVPacket *packet);
|
bool push(const AVPacket *packet);
|
||||||
void interrupt();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onNewFrame();
|
void onNewFrame();
|
||||||
|
|
|
@ -45,13 +45,10 @@ Device::Device(DeviceParams params, QObject *parent) : QObject(parent), m_params
|
||||||
|
|
||||||
return videoSocket->subThreadRecvData(buf, bufSize);
|
return videoSocket->subThreadRecvData(buf, bufSize);
|
||||||
}, this);
|
}, this);
|
||||||
if (m_decoder) {
|
|
||||||
m_stream->setDecoder(m_decoder);
|
|
||||||
}
|
|
||||||
m_server = new Server(this);
|
m_server = new Server(this);
|
||||||
if (!m_params.recordFileName.trimmed().isEmpty()) {
|
if (!m_params.recordFileName.trimmed().isEmpty()) {
|
||||||
m_recorder = new Recorder(m_params.recordFileName);
|
m_recorder = new Recorder(m_params.recordFileName);
|
||||||
m_stream->setRecoder(m_recorder);
|
|
||||||
}
|
}
|
||||||
initSignals();
|
initSignals();
|
||||||
startServer();
|
startServer();
|
||||||
|
@ -62,12 +59,22 @@ Device::~Device()
|
||||||
if (m_server) {
|
if (m_server) {
|
||||||
m_server->stop();
|
m_server->stop();
|
||||||
}
|
}
|
||||||
// server must stop before decoder, because decoder block main thread
|
|
||||||
if (m_stream) {
|
if (m_stream) {
|
||||||
m_stream->stopDecode();
|
m_stream->stopDecode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// server must stop before decoder, because decoder block main thread
|
||||||
|
if (m_decoder) {
|
||||||
|
m_decoder->close();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_recorder) {
|
if (m_recorder) {
|
||||||
|
if (m_recorder->isRunning()) {
|
||||||
|
m_recorder->stopRecorder();
|
||||||
|
m_recorder->wait();
|
||||||
|
}
|
||||||
|
m_recorder->close();
|
||||||
delete m_recorder;
|
delete m_recorder;
|
||||||
}
|
}
|
||||||
if (m_vb) {
|
if (m_vb) {
|
||||||
|
@ -249,6 +256,18 @@ void Device::initSignals()
|
||||||
// init recorder
|
// init recorder
|
||||||
if (m_recorder) {
|
if (m_recorder) {
|
||||||
m_recorder->setFrameSize(size);
|
m_recorder->setFrameSize(size);
|
||||||
|
if (!m_recorder->open()) {
|
||||||
|
qCritical("Could not open recorder");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_recorder->startRecorder()) {
|
||||||
|
qCritical("Could not start recorder");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// init decoder
|
||||||
|
if (m_decoder) {
|
||||||
|
m_decoder->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
// init decoder
|
// init decoder
|
||||||
|
@ -276,6 +295,20 @@ void Device::initSignals()
|
||||||
deleteLater();
|
deleteLater();
|
||||||
qDebug() << "stream thread stop";
|
qDebug() << "stream thread stop";
|
||||||
});
|
});
|
||||||
|
connect(m_stream, &Stream::getFrame, this, [this](AVPacket *packet) {
|
||||||
|
if (m_decoder && !m_decoder->push(packet)) {
|
||||||
|
qCritical("Could not send packet to decoder");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_recorder && !m_recorder->push(packet)) {
|
||||||
|
qCritical("Could not send packet to recorder");
|
||||||
|
}
|
||||||
|
}, Qt::DirectConnection);
|
||||||
|
connect(m_stream, &Stream::getConfigFrame, this, [this](AVPacket *packet) {
|
||||||
|
if (m_recorder && !m_recorder->push(packet)) {
|
||||||
|
qCritical("Could not send config packet to recorder");
|
||||||
|
}
|
||||||
|
}, Qt::DirectConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_decoder && m_vb) {
|
if (m_decoder && m_vb) {
|
||||||
|
|
|
@ -51,8 +51,15 @@ void Recorder::setFormat(Recorder::RecorderFormat format)
|
||||||
m_format = format;
|
m_format = format;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Recorder::open(const AVCodec *inputCodec)
|
bool Recorder::open()
|
||||||
{
|
{
|
||||||
|
// codec
|
||||||
|
AVCodec* inputCodec = avcodec_find_decoder(AV_CODEC_ID_H264);
|
||||||
|
if (!inputCodec) {
|
||||||
|
qCritical("H.264 decoder not found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QString formatName = recorderGetFormatName(m_format);
|
QString formatName = recorderGetFormatName(m_format);
|
||||||
Q_ASSERT(!formatName.isEmpty());
|
Q_ASSERT(!formatName.isEmpty());
|
||||||
const AVOutputFormat *format = findMuxer(formatName.toUtf8());
|
const AVOutputFormat *format = findMuxer(formatName.toUtf8());
|
||||||
|
|
|
@ -28,7 +28,7 @@ public:
|
||||||
|
|
||||||
void setFrameSize(const QSize &declaredFrameSize);
|
void setFrameSize(const QSize &declaredFrameSize);
|
||||||
void setFormat(Recorder::RecorderFormat format);
|
void setFormat(Recorder::RecorderFormat format);
|
||||||
bool open(const AVCodec *inputCodec);
|
bool open();
|
||||||
void close();
|
void close();
|
||||||
bool write(AVPacket *packet);
|
bool write(AVPacket *packet);
|
||||||
bool startRecorder();
|
bool startRecorder();
|
||||||
|
|
|
@ -67,11 +67,6 @@ void Stream::deInit()
|
||||||
avformat_network_deinit(); // ignore failure
|
avformat_network_deinit(); // ignore failure
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::setDecoder(Decoder *decoder)
|
|
||||||
{
|
|
||||||
m_decoder = decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
static quint32 bufferRead32be(quint8 *buf)
|
static quint32 bufferRead32be(quint8 *buf)
|
||||||
{
|
{
|
||||||
return static_cast<quint32>((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
|
return static_cast<quint32>((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
|
||||||
|
@ -84,11 +79,6 @@ static quint64 bufferRead64be(quint8 *buf)
|
||||||
return (static_cast<quint64>(msb) << 32) | lsb;
|
return (static_cast<quint64>(msb) << 32) | lsb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stream::setRecoder(Recorder *recorder)
|
|
||||||
{
|
|
||||||
m_recorder = recorder;
|
|
||||||
}
|
|
||||||
|
|
||||||
qint32 Stream::recvData(quint8 *buf, qint32 bufSize)
|
qint32 Stream::recvData(quint8 *buf, qint32 bufSize)
|
||||||
{
|
{
|
||||||
if (!buf || !m_recvData) {
|
if (!buf || !m_recvData) {
|
||||||
|
@ -110,9 +100,6 @@ bool Stream::startDecode()
|
||||||
|
|
||||||
void Stream::stopDecode()
|
void Stream::stopDecode()
|
||||||
{
|
{
|
||||||
if (m_decoder) {
|
|
||||||
m_decoder->interrupt();
|
|
||||||
}
|
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,23 +123,6 @@ void Stream::run()
|
||||||
goto runQuit;
|
goto runQuit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_decoder && !m_decoder->open(codec)) {
|
|
||||||
qCritical("Could not open m_decoder");
|
|
||||||
goto runQuit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_recorder) {
|
|
||||||
if (!m_recorder->open(codec)) {
|
|
||||||
qCritical("Could not open recorder");
|
|
||||||
goto runQuit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_recorder->startRecorder()) {
|
|
||||||
qCritical("Could not start recorder");
|
|
||||||
goto runQuit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_parser = av_parser_init(AV_CODEC_ID_H264);
|
m_parser = av_parser_init(AV_CODEC_ID_H264);
|
||||||
if (!m_parser) {
|
if (!m_parser) {
|
||||||
qCritical("Could not initialize parser");
|
qCritical("Could not initialize parser");
|
||||||
|
@ -188,16 +158,6 @@ void Stream::run()
|
||||||
av_parser_close(m_parser);
|
av_parser_close(m_parser);
|
||||||
|
|
||||||
runQuit:
|
runQuit:
|
||||||
if (m_recorder) {
|
|
||||||
if (m_recorder->isRunning()) {
|
|
||||||
m_recorder->stopRecorder();
|
|
||||||
m_recorder->wait();
|
|
||||||
}
|
|
||||||
m_recorder->close();
|
|
||||||
}
|
|
||||||
if (m_decoder) {
|
|
||||||
m_decoder->close();
|
|
||||||
}
|
|
||||||
if (m_codecCtx) {
|
if (m_codecCtx) {
|
||||||
avcodec_free_context(&m_codecCtx);
|
avcodec_free_context(&m_codecCtx);
|
||||||
}
|
}
|
||||||
|
@ -305,10 +265,7 @@ bool Stream::pushPacket(AVPacket *packet)
|
||||||
|
|
||||||
bool Stream::processConfigPacket(AVPacket *packet)
|
bool Stream::processConfigPacket(AVPacket *packet)
|
||||||
{
|
{
|
||||||
if (m_recorder && !m_recorder->push(packet)) {
|
emit getConfigFrame(packet);
|
||||||
qCritical("Could not send config packet to recorder");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,18 +297,7 @@ bool Stream::parse(AVPacket *packet)
|
||||||
|
|
||||||
bool Stream::processFrame(AVPacket *packet)
|
bool Stream::processFrame(AVPacket *packet)
|
||||||
{
|
{
|
||||||
if (m_decoder && !m_decoder->push(packet)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_recorder) {
|
|
||||||
packet->dts = packet->pts;
|
packet->dts = packet->pts;
|
||||||
|
emit getFrame(packet);
|
||||||
if (!m_recorder->push(packet)) {
|
|
||||||
qCritical("Could not send packet to recorder");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,13 @@ public:
|
||||||
static bool init();
|
static bool init();
|
||||||
static void deInit();
|
static void deInit();
|
||||||
|
|
||||||
void setDecoder(Decoder *decoder);
|
|
||||||
void setRecoder(Recorder *recorder);
|
|
||||||
bool startDecode();
|
bool startDecode();
|
||||||
void stopDecode();
|
void stopDecode();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onStreamStop();
|
void onStreamStop();
|
||||||
|
void getFrame(AVPacket* packet);
|
||||||
|
void getConfigFrame(AVPacket* packet);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void run();
|
void run();
|
||||||
|
@ -43,9 +43,6 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::function<qint32(quint8*, qint32)> m_recvData = nullptr;
|
std::function<qint32(quint8*, qint32)> m_recvData = nullptr;
|
||||||
// for recorder
|
|
||||||
Recorder *m_recorder = Q_NULLPTR;
|
|
||||||
Decoder *m_decoder = Q_NULLPTR;
|
|
||||||
|
|
||||||
AVCodecContext *m_codecCtx = Q_NULLPTR;
|
AVCodecContext *m_codecCtx = Q_NULLPTR;
|
||||||
AVCodecParserContext *m_parser = Q_NULLPTR;
|
AVCodecParserContext *m_parser = Q_NULLPTR;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue