From ff4eb8bf0788acfe6e36ce1da10bf157bc3a70b0 Mon Sep 17 00:00:00 2001 From: Fancy code <258828110.@qq.com> Date: Tue, 2 Jul 2024 17:59:02 +0800 Subject: [PATCH] Improve:MediaBase module. --- utils/MediaBase/src/FfmpegDecoder.cpp | 74 +++++++++++++++++++++++---- utils/MediaBase/src/FfmpegDecoder.h | 6 +++ 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/utils/MediaBase/src/FfmpegDecoder.cpp b/utils/MediaBase/src/FfmpegDecoder.cpp index cd97a01..8be9226 100644 --- a/utils/MediaBase/src/FfmpegDecoder.cpp +++ b/utils/MediaBase/src/FfmpegDecoder.cpp @@ -33,8 +33,9 @@ extern "C" { #include #include #include +#include FfmpegDecoder::FfmpegDecoder(const enum AVCodecID &codecId) - : mCodecId(codecId), mCodec(nullptr), mCodecCtx(nullptr), mFrame(nullptr) + : mCodecId(codecId), mCodec(nullptr), mCodecCtx(nullptr), mFrame(nullptr), mPacket(nullptr), mParser(nullptr) { } bool FfmpegDecoder::Init(void) @@ -84,6 +85,16 @@ bool FfmpegDecoder::Init(void) LogError("Could not allocate video frame\n"); return false; } + mPacket = av_packet_alloc(); + if (!mPacket) { + LogError("Could not allocate video frame\n"); + return false; + } + mParser = av_parser_init(mCodec->id); + if (!mParser) { + LogError("mParser not found : %s\n", avcodec_get_name(mCodec->id)); + return false; + } if (AVMEDIA_TYPE_AUDIO == mCodec->type) { mFrame->nb_samples = mCodecCtx->frame_size; mFrame->format = mCodecCtx->sample_fmt; @@ -105,19 +116,63 @@ bool FfmpegDecoder::UnInit(void) avcodec_free_context(&mCodecCtx); mCodecCtx = nullptr; } + av_packet_free(&mPacket); + mPacket = nullptr; + if (mParser) { + av_parser_close(mParser); + mParser = nullptr; + } return true; } void FfmpegDecoder::DecodeData(const void *data, const size_t &size, std::function callback) { - AVPacket *packet = nullptr; - packet = av_packet_alloc(); - packet->data = (unsigned char *)data; - packet->size = size; - int ret = avcodec_send_packet(mCodecCtx, packet); + if (nullptr == mParser) { + mPacket->data = (uint8_t *)data; + mPacket->size = size; + // mPacket->stream_index = 0; + mPacket->pts = AV_NOPTS_VALUE; + mPacket->dts = AV_NOPTS_VALUE; + AVDecodeData(mPacket, callback); + return; + } + AVParseData(data, size, callback); +} +void inline FfmpegDecoder::AVParseData(const void *data, const size_t &size, + std::function callback) +{ + if (nullptr == data) { + LogError("data is null\n"); + return; + } + uint8_t *frameData = (uint8_t *)data; + size_t data_size = size; + while (data_size > 0) { + int ret = av_parser_parse2(mParser, + mCodecCtx, + &mPacket->data, + &mPacket->size, + frameData, + data_size, + AV_NOPTS_VALUE, + AV_NOPTS_VALUE, + 0); + if (ret < 0) { + LogError("av_parse_frame failed\n"); + break; + } + frameData += ret; + data_size -= ret; + if (mPacket->size) { + AVDecodeData(mPacket, callback); + } + } +} +void inline FfmpegDecoder::AVDecodeData(AVPacket *pkt, std::function callback) +{ + int ret = avcodec_send_packet(mCodecCtx, pkt); if (ret < 0) { LogError("Error sending a packet for decoding\n"); - av_packet_unref(packet); - av_packet_free(&packet); + av_packet_unref(pkt); return; } while (ret >= 0) { @@ -134,8 +189,7 @@ void FfmpegDecoder::DecodeData(const void *data, const size_t &size, std::functi } break; } - av_packet_unref(packet); - av_packet_free(&packet); + av_packet_unref(pkt); } /* just pick the highest supported samplerate */ int FfmpegDecoder::select_sample_rate(const AVCodec *codec) diff --git a/utils/MediaBase/src/FfmpegDecoder.h b/utils/MediaBase/src/FfmpegDecoder.h index ccf3666..3145704 100644 --- a/utils/MediaBase/src/FfmpegDecoder.h +++ b/utils/MediaBase/src/FfmpegDecoder.h @@ -42,6 +42,10 @@ public: bool UnInit(void); void DecodeData(const void *data, const size_t &size, std::function callback); +private: + void AVParseData(const void *data, const size_t &size, std::function callback); + void AVDecodeData(AVPacket *pkt, std::function callback); + private: static int select_sample_rate(const AVCodec *codec); static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst); @@ -52,5 +56,7 @@ private: AVCodec *mCodec; AVCodecContext *mCodecCtx; AVFrame *mFrame; + AVPacket *mPacket; + AVCodecParserContext *mParser; }; #endif \ No newline at end of file