From fad8c6359d53c5004bd3a80cbbccce89cf9fea6c Mon Sep 17 00:00:00 2001 From: aneejit1 Date: Wed, 4 May 2022 04:42:55 +0000 Subject: [PATCH] Enable ffmpeg 5.0 compatibility The release of version 5.0 of ffmpeg removes a lot of deprecated API functions, some of which are being used by k3b. The ffmpeg support has been modified to support 5.0 as well as older versions. Signed-off-by: aneejit1 (cherry picked from commit 8e7556b9a85e88f6d6f83bfba5b22657fa87848f) --- plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp | 101 ++++++++++++++++---- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp b/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp index 7b91b58..2a113a1 100644 --- a/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp +++ b/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp @@ -34,8 +34,6 @@ extern "C" { #include #include -#define FFMPEG_CODEC(s) (s->codec) - #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 101, 0) #define av_dump_format(c, x, f, y) dump_format(c, x, f, y) #endif @@ -102,9 +100,13 @@ public: ::AVFormatContext *formatContext; ::AVCodec *codec; ::AVStream *audio_stream; + ::AVCodecContext *audio_stream_ctx; ::AVSampleFormat sampleFormat; ::AVFrame *frame; - ::AVPacket packet; + ::AVPacket *packet; +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 12, 100) + ::AVPacket _packet; +#endif char *outputBufferPos; int outputBufferSize; @@ -117,8 +119,10 @@ K3bFFMpegFile::K3bFFMpegFile(const TQString &filename) : m_filename(filename) { d->formatContext = NULL; d->codec = NULL; d->audio_stream = NULL; + d->audio_stream_ctx = NULL; d->frame = av_frame_alloc(); d->outputBufferPos = NULL; + d->packet = NULL; } K3bFFMpegFile::~K3bFFMpegFile() { @@ -158,22 +162,43 @@ bool K3bFFMpegFile::open() { } // urgh... ugly - ::AVCodecContext *codecContext = FFMPEG_CODEC(d->audio_stream); - if (codecContext->codec_type != AVMEDIA_TYPE_AUDIO) { +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) + if (d->audio_stream->codecpar->codec_type != AVMEDIA_TYPE_AUDIO) +#else + d->audio_stream_ctx = d->audio_stream->codec; + if (d->audio_stream_ctx->codec_type != AVMEDIA_TYPE_AUDIO) +#endif + { kdDebug() << "(K3bFFMpegFile) not a simple audio stream: " << m_filename; return false; } // get the codec - d->codec = ::avcodec_find_decoder(codecContext->codec_id); +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) + d->codec = (AVCodec *)::avcodec_find_decoder(d->audio_stream->codecpar->codec_id); +#else + d->codec = (AVCodec *)::avcodec_find_decoder(d->audio_stream_ctx->codec_id); +#endif if (!d->codec) { kdDebug() << "(K3bFFMpegFile) no codec found for " << m_filename; return false; } +#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) + // allocate a codec context + d->audio_stream_ctx = avcodec_alloc_context3(d->codec); + if (d->audio_stream_ctx) { + avcodec_parameters_to_context(d->audio_stream_ctx, d->audio_stream->codecpar); + } + else { + kdDebug() << "(K3bFFMpegFile) failed to allocate a codec context for " + << m_filename; + } +#endif + // open the codec on our context - kdDebug() << "(K3bFFMpegFile) found codec for " << m_filename; - if (::avcodec_open2(codecContext, d->codec, NULL) < 0) { + kdDebug() << "(K3bFFMpegFile) found codec for " << m_filename << endl; + if (::avcodec_open2(d->audio_stream_ctx, d->codec, NULL) < 0) { kdDebug() << "(K3bFFMpegDecoderFactory) could not open codec."; return false; } @@ -207,8 +232,12 @@ void K3bFFMpegFile::close() { d->packetData = NULL; if (d->codec) { - ::avcodec_close(FFMPEG_CODEC(d->audio_stream)); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 63, 100) + ::avcodec_free_context(&d->audio_stream_ctx); +#else + ::avcodec_close(d->audio_stream_ctx); d->codec = NULL; +#endif } if (d->formatContext) { @@ -301,13 +330,18 @@ int K3bFFMpegFile::read(char *buf, int bufLen) { // fill d->packetData with data to decode int K3bFFMpegFile::readPacket() { if (d->packetSize <= 0) { - ::av_init_packet(&d->packet); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100) + d->packet = ::av_packet_alloc(); +#else + ::av_init_packet(&d->_packet); + d->packet = &d->_packet; +#endif - if (::av_read_frame(d->formatContext, &d->packet) < 0) { + if (::av_read_frame(d->formatContext, d->packet) < 0) { return 0; } - d->packetSize = d->packet.size; - d->packetData = d->packet.data; + d->packetSize = d->packet->size; + d->packetData = d->packet->data; } return d->packetSize; @@ -324,16 +358,43 @@ int K3bFFMpegFile::fillOutputBuffer() { } int gotFrame = 0; - int len = ::avcodec_decode_audio4(FFMPEG_CODEC(d->audio_stream), d->frame, - &gotFrame, &d->packet); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100) + int len = avcodec_receive_frame(d->audio_stream_ctx, d->frame); + if (len == 0) { + gotFrame = 1; + } + else if (len == AVERROR(EAGAIN)) { + len = 0; + } + + if (len == 0) { + len = avcodec_send_packet(d->audio_stream_ctx, d->packet); + if (len == AVERROR(EAGAIN)) { + len = 0; + } + } +#else + int len = ::avcodec_decode_audio4(d->audio_stream_ctx, d->frame, + &gotFrame, d->packet); +#endif - if (d->packetSize <= 0 || len < 0) - ::av_packet_unref(&d->packet); + if (d->packetSize <= 0 || len < 0) { +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100) + ::av_packet_free(&d->packet); +#else + ::av_packet_unref(d->packet); + d->packet = NULL; +#endif + } if (len < 0) { kdDebug() << "(K3bFFMpegFile) decoding failed for " << m_filename; return -1; } +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100) + len = d->packet->size; +#endif + if (gotFrame) { int nb_s = d->frame->nb_samples; int nb_ch = 2; // copy only two channels even if there're more @@ -386,7 +447,11 @@ bool K3bFFMpegFile::seek(const K3b::Msf &msf) { // // av_register_all is deprecated since ffmpeg 4.0, can be dropped -K3bFFMpegWrapper::K3bFFMpegWrapper() { ::av_register_all(); } +K3bFFMpegWrapper::K3bFFMpegWrapper() { +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58,9,100) + ::av_register_all(); +#endif +} K3bFFMpegWrapper::~K3bFFMpegWrapper() { s_instance = NULL; }