Implement ffmpeg 5.0 support

Version 5.0 of ffmpeg removed a lot of deprecated API which causes akode
to fail to build against it. The ffmpeg plugin has been amended to allow
akode to build against the new version as well as older versions, plus a
call to "av_register_all" has been re-instated for earlier versions to
ensure the player functions correctly.

Signed-off-by: aneejit1 <aneejit1@gmail.com>
(cherry picked from commit 9e2710c9d8)
r14.0.x
aneejit1 2 years ago committed by Slávek Banko
parent e910166a78
commit 6618494412
No known key found for this signature in database
GPG Key ID: 608F5293A04BE668

@ -37,7 +37,7 @@ extern "C" {
#include "ffmpeg_decoder.h" #include "ffmpeg_decoder.h"
#include <iostream> #include <iostream>
#if LIBAVCODEC_VERSION_MAJOR < 58 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(57, 33, 100)
#define CODECPAR codec #define CODECPAR codec
#else #else
#define CODECPAR codecpar #define CODECPAR codecpar
@ -69,10 +69,6 @@ bool FFMPEGDecoderPlugin::canDecode(File* /*src*/) {
// ### FIXME // ### FIXME
return true; return true;
} }
/*
void FFMPEGDecoderPlugin::initializeFFMPEG() {
av_register_all();
}*/
extern "C" { FFMPEGDecoderPlugin ffmpeg_decoder; } extern "C" { FFMPEGDecoderPlugin ffmpeg_decoder; }
@ -81,7 +77,8 @@ extern "C" { FFMPEGDecoderPlugin ffmpeg_decoder; }
struct FFMPEGDecoder::private_data struct FFMPEGDecoder::private_data
{ {
private_data() : audioStream(-1), videoStream(-1), packetSize(0), position(0), private_data() : audioStream(-1), videoStream(-1), packetSize(0), position(0),
eof(false), error(false), initialized(false), retries(0) {}; eof(false), error(false), initialized(false), retries(0),
packet(NULL), audioStream_ctx(NULL), videoStream_ctx(NULL) {};
AVFormatContext* ic; AVFormatContext* ic;
AVCodec* codec; AVCodec* codec;
@ -90,8 +87,13 @@ struct FFMPEGDecoder::private_data
int audioStream; int audioStream;
int videoStream; int videoStream;
AVCodecContext *audioStream_ctx;
AVCodecContext *videoStream_ctx;
AVPacket packet; AVPacket *packet;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 12, 100)
AVPacket _packet;
#endif
uint8_t* packetData; uint8_t* packetData;
int packetSize; int packetSize;
@ -113,6 +115,9 @@ FFMPEGDecoder::FFMPEGDecoder(File *src) {
d = new private_data; d = new private_data;
d->src = src; d->src = src;
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100)
av_register_all();
#endif
} }
FFMPEGDecoder::~FFMPEGDecoder() { FFMPEGDecoder::~FFMPEGDecoder() {
@ -206,20 +211,41 @@ bool FFMPEGDecoder::openFile() {
av_dump_format(d->ic, d->audioStream, d->src->filename, 0); av_dump_format(d->ic, d->audioStream, d->src->filename, 0);
// Set config d->codec = (AVCodec *)avcodec_find_decoder(d->ic->streams[d->audioStream]->CODECPAR->codec_id);
if (!setAudioConfiguration(&d->config, d->ic->streams[d->audioStream]->codec)) if (!d->codec) {
{ std::cerr << "akode: FFMPEG: Codec not found\n";
closeFile(); closeFile();
return false; return false;
} }
d->codec = avcodec_find_decoder(d->ic->streams[d->audioStream]->CODECPAR->codec_id); #if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100)
if (!d->codec) { // allocate a codec context
std::cerr << "akode: FFMPEG: Codec not found\n"; d->audioStream_ctx = avcodec_alloc_context3(d->codec);
if (d->audioStream_ctx) {
avcodec_parameters_to_context(d->audioStream_ctx, d->ic->streams[d->audioStream]->codecpar);
}
else {
std::cerr << "akode: failed to allocate an audio codec context\n";
closeFile();
return false;
}
#else
d->audioStream_ctx = d->ic->streams[d->audioStream]->codec;
#endif
// Set config
if (!setAudioConfiguration(&d->config, d->audioStream_ctx))
{
closeFile(); closeFile();
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100)
avcodec_free_context(&d->audioStream_ctx);
#else
d->audioStream_ctx = NULL;
#endif
return false; return false;
} }
avcodec_open2( d->ic->streams[d->audioStream]->codec, d->codec, NULL );
avcodec_open2( d->audioStream_ctx, d->codec, NULL );
double ffpos = (double)d->ic->streams[d->audioStream]->start_time / (double)AV_TIME_BASE; double ffpos = (double)d->ic->streams[d->audioStream]->start_time / (double)AV_TIME_BASE;
d->position = (long)(ffpos * d->config.sample_rate); d->position = (long)(ffpos * d->config.sample_rate);
@ -239,20 +265,28 @@ void FFMPEGDecoder::closeFile() {
} }
if( d->packetSize > 0 ) { if( d->packetSize > 0 ) {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0)
av_free_packet(&d->packet); av_free_packet(&d->_packet);
#else #else
av_packet_unref( &d->packet ); av_packet_unref( d->packet );
#endif #endif
d->packet = NULL;
d->packetSize = 0; d->packetSize = 0;
} }
if( d->codec ) { if( d->codec ) {
avcodec_close( d->ic->streams[d->audioStream]->codec ); avcodec_close( d->audioStream_ctx );
#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100)
avcodec_free_context(&d->audioStream_ctx);
#else
d->audioStream_ctx = NULL;
#endif
d->codec = 0; d->codec = 0;
} }
if( d->ic ) { if( d->ic ) {
// make sure av_close_input_file doesn't actually close the file // make sure av_close_input_file doesn't actually close the file
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(59, 0, 100)
d->ic->iformat->flags = d->ic->iformat->flags | AVFMT_NOFILE; d->ic->iformat->flags = d->ic->iformat->flags | AVFMT_NOFILE;
#endif
avformat_close_input( &d->ic ); avformat_close_input( &d->ic );
d->ic = 0; d->ic = 0;
} }
@ -263,27 +297,34 @@ void FFMPEGDecoder::closeFile() {
bool FFMPEGDecoder::readPacket() { bool FFMPEGDecoder::readPacket() {
do { do {
av_init_packet(&d->packet); #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
if ( av_read_frame(d->ic, &d->packet) < 0 ) { d->packet = av_packet_alloc();
#else
av_init_packet(&d->_packet);
d->packet = &d->_packet;
#endif
if ( av_read_frame(d->ic, d->packet) < 0 ) {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0)
av_free_packet(&d->packet); av_free_packet(&d->_packet);
#else #else
av_packet_unref( &d->packet ); av_packet_unref( d->packet );
#endif #endif
d->packet = NULL;
d->packetSize = 0; d->packetSize = 0;
d->packetData = 0; d->packetData = 0;
return false; return false;
} }
if (d->packet.stream_index == d->audioStream) { if (d->packet->stream_index == d->audioStream) {
d->packetSize = d->packet.size; d->packetSize = d->packet->size;
d->packetData = d->packet.data; d->packetData = d->packet->data;
return true; return true;
} }
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0)
av_free_packet(&d->packet); av_free_packet(&d->_packet);
#else #else
av_packet_unref(&d->packet); av_packet_unref(d->packet);
#endif #endif
d->packet = NULL;
} while (true); } while (true);
return false; return false;
@ -324,7 +365,7 @@ bool FFMPEGDecoder::readFrame(AudioFrame* frame)
return false; return false;
} }
assert(d->packet.stream_index == d->audioStream); assert(d->packet->stream_index == d->audioStream);
retry: retry:
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 45, 101) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 45, 101)
@ -336,19 +377,43 @@ retry:
return false; return false;
} }
int decoded; int decoded;
int len = avcodec_decode_audio4( d->ic->streams[d->audioStream]->codec,
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
int len = avcodec_receive_frame(d->audioStream_ctx, decodeFrame);
if (len == 0) {
decoded = 1;
}
else if (len == AVERROR(EAGAIN)) {
len = 0;
}
if (len == 0) {
len = avcodec_send_packet(d->audioStream_ctx, d->packet);
if (len == AVERROR(EAGAIN)) {
len = 0;
}
else
{
len = d->packet->size;
d->packetSize = d->packet->size;
}
}
#else
int len = avcodec_decode_audio4( d->audioStream_ctx,
decodeFrame, &decoded, decodeFrame, &decoded,
&d->packet ); d->packet );
#if !defined(FFMPEG_AVFRAME_HAVE_PKT_SIZE) #if !defined(FFMPEG_AVFRAME_HAVE_PKT_SIZE)
d->packetSize = d->packet.size; d->packetSize = d->packet->size;
#else #else
d->packetSize = decodeFrame->pkt_size; d->packetSize = decodeFrame->pkt_size;
#endif #endif
#endif
d->buffer = decodeFrame->data; d->buffer = decodeFrame->data;
#if !defined(FFMPEG_AVFRAME_HAVE_CHANNELS) #if !defined(FFMPEG_AVFRAME_HAVE_CHANNELS)
d->buffer_size = decodeFrame->nb_samples * d->ic->streams[d->audioStream]->codec->channels * av_get_bytes_per_sample(d->ic->streams[d->audioStream]->codec->sample_fmt); d->buffer_size = decodeFrame->nb_samples * d->ic->streams[d->audioStream]->CODECPAR->channels * av_get_bytes_per_sample(d->ic->streams[d->audioStream]->codec->sample_fmt);
#else #else
d->buffer_size = decodeFrame->nb_samples * decodeFrame->channels * av_get_bytes_per_sample(d->ic->streams[d->audioStream]->codec->sample_fmt); d->buffer_size = decodeFrame->nb_samples * decodeFrame->channels * av_get_bytes_per_sample(d->audioStream_ctx->sample_fmt);
#endif #endif
if (len <= 0) { if (len <= 0) {
@ -394,10 +459,11 @@ retry:
if( d->packetSize <= 0 ) if( d->packetSize <= 0 )
{ {
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 7, 0)
av_free_packet(&d->packet); av_free_packet(&d->_packet);
#else #else
av_packet_unref( &d->packet ); av_packet_unref( d->packet );
#endif #endif
d->packet = NULL;
} }
frame->pos = (d->position*1000)/d->config.sample_rate; frame->pos = (d->position*1000)/d->config.sample_rate;

Loading…
Cancel
Save