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 <aneejit1@gmail.com>
pull/14/head
aneejit1 2 years ago
parent 1f4a3ab86e
commit 8e7556b9a8

@ -34,8 +34,6 @@ extern "C" {
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
#define FFMPEG_CODEC(s) (s->codec)
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 101, 0) #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52, 101, 0)
#define av_dump_format(c, x, f, y) dump_format(c, x, f, y) #define av_dump_format(c, x, f, y) dump_format(c, x, f, y)
#endif #endif
@ -102,9 +100,13 @@ public:
::AVFormatContext *formatContext; ::AVFormatContext *formatContext;
::AVCodec *codec; ::AVCodec *codec;
::AVStream *audio_stream; ::AVStream *audio_stream;
::AVCodecContext *audio_stream_ctx;
::AVSampleFormat sampleFormat; ::AVSampleFormat sampleFormat;
::AVFrame *frame; ::AVFrame *frame;
::AVPacket packet; ::AVPacket *packet;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 12, 100)
::AVPacket _packet;
#endif
char *outputBufferPos; char *outputBufferPos;
int outputBufferSize; int outputBufferSize;
@ -117,8 +119,10 @@ K3bFFMpegFile::K3bFFMpegFile(const TQString &filename) : m_filename(filename) {
d->formatContext = NULL; d->formatContext = NULL;
d->codec = NULL; d->codec = NULL;
d->audio_stream = NULL; d->audio_stream = NULL;
d->audio_stream_ctx = NULL;
d->frame = av_frame_alloc(); d->frame = av_frame_alloc();
d->outputBufferPos = NULL; d->outputBufferPos = NULL;
d->packet = NULL;
} }
K3bFFMpegFile::~K3bFFMpegFile() { K3bFFMpegFile::~K3bFFMpegFile() {
@ -158,22 +162,43 @@ bool K3bFFMpegFile::open() {
} }
// urgh... ugly // urgh... ugly
::AVCodecContext *codecContext = FFMPEG_CODEC(d->audio_stream); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100)
if (codecContext->codec_type != AVMEDIA_TYPE_AUDIO) { 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; kdDebug() << "(K3bFFMpegFile) not a simple audio stream: " << m_filename;
return false; return false;
} }
// get the codec // 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) { if (!d->codec) {
kdDebug() << "(K3bFFMpegFile) no codec found for " << m_filename; kdDebug() << "(K3bFFMpegFile) no codec found for " << m_filename;
return false; 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 // open the codec on our context
kdDebug() << "(K3bFFMpegFile) found codec for " << m_filename; kdDebug() << "(K3bFFMpegFile) found codec for " << m_filename << endl;
if (::avcodec_open2(codecContext, d->codec, NULL) < 0) { if (::avcodec_open2(d->audio_stream_ctx, d->codec, NULL) < 0) {
kdDebug() << "(K3bFFMpegDecoderFactory) could not open codec."; kdDebug() << "(K3bFFMpegDecoderFactory) could not open codec.";
return false; return false;
} }
@ -207,8 +232,12 @@ void K3bFFMpegFile::close() {
d->packetData = NULL; d->packetData = NULL;
if (d->codec) { 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; d->codec = NULL;
#endif
} }
if (d->formatContext) { if (d->formatContext) {
@ -301,13 +330,18 @@ int K3bFFMpegFile::read(char *buf, int bufLen) {
// fill d->packetData with data to decode // fill d->packetData with data to decode
int K3bFFMpegFile::readPacket() { int K3bFFMpegFile::readPacket() {
if (d->packetSize <= 0) { 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; return 0;
} }
d->packetSize = d->packet.size; d->packetSize = d->packet->size;
d->packetData = d->packet.data; d->packetData = d->packet->data;
} }
return d->packetSize; return d->packetSize;
@ -324,16 +358,43 @@ int K3bFFMpegFile::fillOutputBuffer() {
} }
int gotFrame = 0; int gotFrame = 0;
int len = ::avcodec_decode_audio4(FFMPEG_CODEC(d->audio_stream), d->frame, #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
&gotFrame, &d->packet); 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) if (d->packetSize <= 0 || len < 0) {
::av_packet_unref(&d->packet); #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) { if (len < 0) {
kdDebug() << "(K3bFFMpegFile) decoding failed for " << m_filename; kdDebug() << "(K3bFFMpegFile) decoding failed for " << m_filename;
return -1; return -1;
} }
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
len = d->packet->size;
#endif
if (gotFrame) { if (gotFrame) {
int nb_s = d->frame->nb_samples; int nb_s = d->frame->nb_samples;
int nb_ch = 2; // copy only two channels even if there're more 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 // 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; } K3bFFMpegWrapper::~K3bFFMpegWrapper() { s_instance = NULL; }

Loading…
Cancel
Save