refactor: stream and decoder&recorder decoupling

This commit is contained in:
Barry 2022-04-06 09:51:16 +08:00
parent dbbe5297b0
commit 0b39bbc719
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() {}
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
m_codecCtx = avcodec_alloc_context3(codec);
if (!m_codecCtx) {
@ -26,6 +34,10 @@ bool Decoder::open(const AVCodec *codec)
void Decoder::close()
{
if (m_vb) {
m_vb->interrupt();
}
if (!m_codecCtx) {
return;
}
@ -98,13 +110,6 @@ bool Decoder::push(const AVPacket *packet)
return true;
}
void Decoder::interrupt()
{
if (m_vb) {
m_vb->interrupt();
}
}
void Decoder::pushFrame()
{
if (!m_vb) {

View file

@ -15,10 +15,9 @@ public:
Decoder(VideoBuffer *vb, QObject *parent = Q_NULLPTR);
virtual ~Decoder();
bool open(const AVCodec *codec);
bool open();
void close();
bool push(const AVPacket *packet);
void interrupt();
signals:
void onNewFrame();

View file

@ -45,13 +45,10 @@ Device::Device(DeviceParams params, QObject *parent) : QObject(parent), m_params
return videoSocket->subThreadRecvData(buf, bufSize);
}, this);
if (m_decoder) {
m_stream->setDecoder(m_decoder);
}
m_server = new Server(this);
if (!m_params.recordFileName.trimmed().isEmpty()) {
m_recorder = new Recorder(m_params.recordFileName);
m_stream->setRecoder(m_recorder);
}
initSignals();
startServer();
@ -62,12 +59,22 @@ Device::~Device()
if (m_server) {
m_server->stop();
}
// server must stop before decoder, because decoder block main thread
if (m_stream) {
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->isRunning()) {
m_recorder->stopRecorder();
m_recorder->wait();
}
m_recorder->close();
delete m_recorder;
}
if (m_vb) {
@ -249,6 +256,18 @@ void Device::initSignals()
// init recorder
if (m_recorder) {
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
@ -276,6 +295,20 @@ void Device::initSignals()
deleteLater();
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) {

View file

@ -51,8 +51,15 @@ void Recorder::setFormat(Recorder::RecorderFormat 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);
Q_ASSERT(!formatName.isEmpty());
const AVOutputFormat *format = findMuxer(formatName.toUtf8());

View file

@ -28,7 +28,7 @@ public:
void setFrameSize(const QSize &declaredFrameSize);
void setFormat(Recorder::RecorderFormat format);
bool open(const AVCodec *inputCodec);
bool open();
void close();
bool write(AVPacket *packet);
bool startRecorder();

View file

@ -67,11 +67,6 @@ void Stream::deInit()
avformat_network_deinit(); // ignore failure
}
void Stream::setDecoder(Decoder *decoder)
{
m_decoder = decoder;
}
static quint32 bufferRead32be(quint8 *buf)
{
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;
}
void Stream::setRecoder(Recorder *recorder)
{
m_recorder = recorder;
}
qint32 Stream::recvData(quint8 *buf, qint32 bufSize)
{
if (!buf || !m_recvData) {
@ -110,9 +100,6 @@ bool Stream::startDecode()
void Stream::stopDecode()
{
if (m_decoder) {
m_decoder->interrupt();
}
wait();
}
@ -136,23 +123,6 @@ void Stream::run()
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);
if (!m_parser) {
qCritical("Could not initialize parser");
@ -188,16 +158,6 @@ void Stream::run()
av_parser_close(m_parser);
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) {
avcodec_free_context(&m_codecCtx);
}
@ -305,10 +265,7 @@ bool Stream::pushPacket(AVPacket *packet)
bool Stream::processConfigPacket(AVPacket *packet)
{
if (m_recorder && !m_recorder->push(packet)) {
qCritical("Could not send config packet to recorder");
return false;
}
emit getConfigFrame(packet);
return true;
}
@ -340,18 +297,7 @@ bool Stream::parse(AVPacket *packet)
bool Stream::processFrame(AVPacket *packet)
{
if (m_decoder && !m_decoder->push(packet)) {
return false;
}
if (m_recorder) {
packet->dts = packet->pts;
if (!m_recorder->push(packet)) {
qCritical("Could not send packet to recorder");
return false;
}
}
packet->dts = packet->pts;
emit getFrame(packet);
return true;
}

View file

@ -24,13 +24,13 @@ public:
static bool init();
static void deInit();
void setDecoder(Decoder *decoder);
void setRecoder(Recorder *recorder);
bool startDecode();
void stopDecode();
signals:
void onStreamStop();
void getFrame(AVPacket* packet);
void getConfigFrame(AVPacket* packet);
protected:
void run();
@ -43,9 +43,6 @@ protected:
private:
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;
AVCodecParserContext *m_parser = Q_NULLPTR;