Skip to content

Commit

Permalink
Fix compatibility with FFmpeg 5.0
Browse files Browse the repository at this point in the history
Signed-off-by: Silvio Traversaro <silvio@traversaro.it>
  • Loading branch information
traversaro committed Mar 19, 2022
1 parent 14c585a commit abde9e4
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 7 deletions.
80 changes: 79 additions & 1 deletion av/src/AudioDecoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ignition::common::AudioDecoderPrivate
public: AVCodecContext *codecCtx;

/// \brief libavcodec audio codec.
public: AVCodec *codec;
public: const AVCodec *codec;

/// \brief Index of the audio stream.
public: int audioStream;
Expand Down Expand Up @@ -77,8 +77,12 @@ void AudioDecoder::Cleanup()
/////////////////////////////////////////////////
bool AudioDecoder::Decode(uint8_t **_outBuffer, unsigned int *_outBufferSize)
{
#if LIBAVFORMAT_VERSION_MAJOR < 59
AVPacket *packet, packet1;
int bytesDecoded = 0;
#else
AVPacket *packet;
#endif
unsigned int maxBufferSize = 0;
AVFrame *decodedFrame = nullptr;

Expand Down Expand Up @@ -121,6 +125,53 @@ bool AudioDecoder::Decode(uint8_t **_outBuffer, unsigned int *_outBufferSize)
{
if (packet->stream_index == this->data->audioStream)
{
#if LIBAVFORMAT_VERSION_MAJOR >= 59
// Inspired from
// https://github.com/FFmpeg/FFmpeg/blob/n5.0/doc/examples/decode_audio.c#L71

// send the packet with the compressed data to the decoder
int ret = avcodec_send_packet(this->data->codecCtx, packet);
if (ret < 0)
{
ignerr << "Error submitting the packet to the decoder" << std::endl;
return false;
}

// read all the output frames
// (in general there may be any number of them)
while (ret >= 0)
{
ret = avcodec_receive_frame(this->data->codecCtx, decodedFrame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
{
break;
}
else if (ret < 0)
{
ignerr << "Error during decoding" << std::endl;
return false;
}

// Total size of the data. Some padding can be added to
// decodedFrame->data[0], which is why we can't use
// decodedFrame->linesize[0].
int size = decodedFrame->nb_samples *
av_get_bytes_per_sample(this->data->codecCtx->sample_fmt) *
this->data->codecCtx->channels;

// Resize the audio buffer as necessary
if (*_outBufferSize + size > maxBufferSize)
{
maxBufferSize += size * 5;
*_outBuffer = reinterpret_cast<uint8_t*>(realloc(*_outBuffer,
maxBufferSize * sizeof(*_outBuffer[0])));
}

memcpy(*_outBuffer + *_outBufferSize, decodedFrame->data[0],
size);
*_outBufferSize += size;
}
#else
int gotFrame = 0;

packet1 = *packet;
Expand Down Expand Up @@ -163,6 +214,7 @@ bool AudioDecoder::Decode(uint8_t **_outBuffer, unsigned int *_outBufferSize)
packet1.data += bytesDecoded;
packet1.size -= bytesDecoded;
}
#endif
}
av_packet_unref(packet);
}
Expand Down Expand Up @@ -224,8 +276,13 @@ bool AudioDecoder::SetFile(const std::string &_filename)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#if LIBAVFORMAT_VERSION_MAJOR >= 59
if (this->data->formatCtx->streams[i]->codecpar->codec_type == // NOLINT(*)
AVMEDIA_TYPE_AUDIO)
#else
if (this->data->formatCtx->streams[i]->codec->codec_type == // NOLINT(*)
AVMEDIA_TYPE_AUDIO)
#endif
#ifndef _WIN32
# pragma GCC diagnostic pop
#endif
Expand All @@ -249,14 +306,35 @@ bool AudioDecoder::SetFile(const std::string &_filename)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
#if LIBAVFORMAT_VERSION_MAJOR < 59
this->data->codecCtx = this->data->formatCtx->streams[
this->data->audioStream]->codec;
#endif
#ifndef _WIN32
# pragma GCC diagnostic pop
#endif

// Find a decoder
#if LIBAVFORMAT_VERSION_MAJOR >= 59
this->data->codec = avcodec_find_decoder(this->data->formatCtx->streams[
this->data->audioStream]->codecpar->codec_id);
if (!this->data->codec)
{
ignerr << "Failed to find the codec" << std::endl;
return false;
}
this->data->codecCtx = avcodec_alloc_context3(this->data->codec);
if (!this->data->codecCtx)
{
ignerr << "Failed to allocate the codec context" << std::endl;
return false;
}
// Copy all relevant parameters from codepar to codecCtx
avcodec_parameters_to_context(this->data->codecCtx,
this->data->formatCtx->streams[this->data->audioStream]->codecpar);
#else
this->data->codec = avcodec_find_decoder(this->data->codecCtx->codec_id);
#endif

if (this->data->codec == nullptr)
{
Expand Down
6 changes: 4 additions & 2 deletions av/src/AudioDecoder_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,12 @@ TEST(AudioDecoder, IGN_UTILS_TEST_DISABLED_ON_WIN32(CheerFile))
EXPECT_EQ(audio.SampleRate(), 44100);

audio.Decode(&dataBuffer, &dataBufferSize);
// In Ubuntu trusty the buffer size double for ogg decoding.
// In Ubuntu trusty (ffmpeg ) the buffer size double for ogg decoding.
// This check is suitable for both older and newer versions of Ubuntu.
// With ffmpeg 5.0 the value changed again (third value)
EXPECT_TRUE(dataBufferSize == 4989184u ||
dataBufferSize == 4989184u * 2u);
dataBufferSize == 4989184u * 2u ||
dataBufferSize == 9975224u);
}

// MP3
Expand Down
2 changes: 1 addition & 1 deletion av/src/Video.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void Video::Cleanup()
/////////////////////////////////////////////////
bool Video::Load(const std::string &_filename)
{
AVCodec *codec = nullptr;
const AVCodec * codec = nullptr;
this->dataPtr->videoStream = -1;

if (this->dataPtr->formatCtx || this->dataPtr->avFrame ||
Expand Down
6 changes: 3 additions & 3 deletions av/src/VideoEncoder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class IGNITION_COMMON_AV_HIDDEN ignition::common::VideoEncoderPrivate
/// Find a suitable encoder for the given codec ID.
/// \param[in] _codecId ID of the codec we seek the encoder for.
/// \return The matched encoder (or nullptr on failure).
public: AVCodec* FindEncoder(AVCodecID _codecId);
public: const AVCodec* FindEncoder(AVCodecID _codecId);

/// \brief Get a pointer to the frame that contains the encoder input. This
/// mainly serves for uploading the frame to GPU buffer if HW acceleration is
Expand All @@ -123,7 +123,7 @@ class IGNITION_COMMON_AV_HIDDEN ignition::common::VideoEncoderPrivate
};

/////////////////////////////////////////////////
AVCodec* VideoEncoderPrivate::FindEncoder(AVCodecID _codecId)
const AVCodec* VideoEncoderPrivate::FindEncoder(AVCodecID _codecId)
{
#ifdef IGN_COMMON_BUILD_HW_VIDEO
if (this->hwEncoder)
Expand Down Expand Up @@ -367,7 +367,7 @@ bool VideoEncoder::Start(
}
else
{
AVOutputFormat *outputFormat = av_guess_format(nullptr,
const AVOutputFormat *outputFormat = av_guess_format(nullptr,
this->dataPtr->filename.c_str(), nullptr);

if (!outputFormat)
Expand Down

0 comments on commit abde9e4

Please sign in to comment.