refactor: stream and decoder&recorder decoupling

This commit is contained in:
Barry 2022-04-06 09:51:16 +08:00
commit 74b38e9ac5
7 changed files with 66 additions and 79 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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