Skip to content

Commit

Permalink
Adds support for FFmpeg 5.0
Browse files Browse the repository at this point in the history
FFmpeg 5.0 has removed several APIs Audacity used:

* `avcodec_decode_audio4`
* `avcodec_encode_audio2`
* `*_next` to iterate formats and codecs
* AVCodeContext is removed from the AVStream
  • Loading branch information
crsib committed Jul 5, 2022
1 parent d3b37da commit 20ab323
Show file tree
Hide file tree
Showing 34 changed files with 616 additions and 214 deletions.
20 changes: 15 additions & 5 deletions libraries/lib-ffmpeg-support/AVCodecFunctions.h
Expand Up @@ -14,6 +14,8 @@

#include "FFmpegTypes.h"

typedef struct AVCodecParameters AVCodecParameters;

struct FFMPEG_SUPPORT_API AVCodecFunctions
{
FFMPegVersion AVCodecVersion;
Expand All @@ -28,17 +30,25 @@ struct FFMPEG_SUPPORT_API AVCodecFunctions
int (*avcodec_open2) (AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options) = nullptr;
int (*avcodec_is_open) (AVCodecContext *avctx) = nullptr;
int (*avcodec_close) (AVCodecContext *avctx) = nullptr;
int (*avcodec_decode_audio4) (AVCodecContext *avctx, AVFrame *frame, int *got_output, const AVPacket *avpkt) = nullptr;
int (*avcodec_encode_audio2) (AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_output) = nullptr;
AVCodecContext* (*avcodec_alloc_context3) (const AVCodec* codec) = nullptr;
void (*avcodec_register_all) (void) = nullptr;
AVCodec* (*av_codec_next) (const AVCodec *c) = nullptr;
int (*av_codec_is_encoder) (const AVCodec *codec) = nullptr;
int (*avcodec_fill_audio_frame) (AVFrame *frame, int nb_channels, AVSampleFormatFwd sample_fmt, const uint8_t *buf, int buf_size, int align) = nullptr;


// The following functions are not present in all library versions:
AVPacket* (*av_packet_alloc) () = nullptr;
void (*av_packet_free)(AVPacket** pkt) = nullptr;
void (*avcodec_free_context) (AVCodecContext** avctx) = nullptr;
int (*avcodec_parameters_to_context)(AVCodecContext* codec, const AVCodecParameters* par) = nullptr;
int (*avcodec_parameters_from_context)(AVCodecParameters *par, const AVCodecContext *codec)= nullptr;
int (*avcodec_decode_audio4) (AVCodecContext *avctx, AVFrame *frame, int *got_output, const AVPacket *avpkt) = nullptr;
int (*avcodec_encode_audio2) (AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_output) = nullptr;
void (*avcodec_register_all)(void) = nullptr;
AVCodec* (*av_codec_next)(const AVCodec* c) = nullptr;
const AVCodec* (*av_codec_iterate)(void** opaque) = nullptr;

// New API for decoding and encoding. Audacity will preffer it when available.
int (*avcodec_send_packet)(AVCodecContext* avctx, const AVPacket* avpkt) = nullptr;
int (*avcodec_receive_frame)(AVCodecContext* avctx, AVFrame* frame) = nullptr;
int (*avcodec_send_frame)(AVCodecContext* avctx, const AVFrame* frame) = nullptr;
int (*avcodec_receive_packet)(AVCodecContext* avctx, AVPacket* avpkt) = nullptr;
};
1 change: 1 addition & 0 deletions libraries/lib-ffmpeg-support/AVFormatFunctions.h
Expand Up @@ -38,4 +38,5 @@ struct FFMPEG_SUPPORT_API AVFormatFunctions
// The following functions are not present in all library versions:
void (*av_register_all) (void) = nullptr;
void (*avio_context_free)(AVIOContext** s) = nullptr;
const AVOutputFormat* (*av_muxer_iterate)(void** opaque);
};
1 change: 1 addition & 0 deletions libraries/lib-ffmpeg-support/AVUtilFunctions.h
Expand Up @@ -21,6 +21,7 @@ struct FFMPEG_SUPPORT_API AVUtilFunctions

void* (*av_malloc) (size_t size) = nullptr;
void (*av_free) (void *ptr) = nullptr;
char* (*av_strdup) (const char *ptr) = nullptr;
void (*av_dict_free) (AVDictionary **m) = nullptr;
AudacityAVDictionaryEntry*
(*av_dict_get) (const AVDictionary *m, const char *key, const AudacityAVDictionaryEntry *prev, int flags) = nullptr;
Expand Down
35 changes: 21 additions & 14 deletions libraries/lib-ffmpeg-support/CMakeLists.txt
Expand Up @@ -42,29 +42,39 @@ if (${_OPT}use_ffmpeg)

impl/FFmpegLog.h

impl/ffmpeg-2.3.6-single-header.h
impl/avutil/52/avconfig.h
impl/avcodec/55/AVCodecIDLookup.cpp
impl/avcodec/55/AVCodecImpl.cpp
impl/avformat/55/AVFormatImpl.cpp
impl/avutil/52/AVUtilImpl.cpp

impl/ffmpeg-3.4.8-single-header.h
impl/avutil/55/avconfig.h
impl/avcodec/57/AVCodecIDLookup.cpp
impl/avcodec/57/AVCodecImpl.cpp
impl/avformat/57/AVFormatImpl.cpp
impl/avutil/55/AVUtilImpl.cpp

impl/ffmpeg-4.2.4-single-header.h
impl/avutil/56/avconfig.h
impl/avcodec/58/AVCodecIDLookup.cpp
impl/avcodec/58/AVCodecImpl.cpp
impl/avformat/58/AVFormatImpl.cpp
impl/avutil/56/AVUtilImpl.cpp

impl/ffmpeg-5.0.1-single-header.h
impl/avutil/57/avconfig.h
impl/avcodec/59/AVCodecIDLookup.cpp
impl/avcodec/59/AVCodecImpl.cpp
impl/avformat/59/AVFormatImpl.cpp
impl/avutil/57/AVUtilImpl.cpp

# Loaders
impl/avcodec/AVCodecFunctionsLoader.cpp
impl/avcodec/AVCodecFunctionsLoader.h

impl/avformat/55/AVFormatImpl.cpp
impl/avformat/57/AVFormatImpl.cpp
impl/avformat/58/AVFormatImpl.cpp

impl/avformat/AVFormatFunctionsLoader.cpp
impl/avformat/AVFormatFunctionsLoader.h

impl/avutil/52/AVUtilImpl.cpp
impl/avutil/55/AVUtilImpl.cpp
impl/avutil/56/AVUtilImpl.cpp

impl/avutil/AVUtilFunctionsLoader.cpp
impl/avutil/AVUtilFunctionsLoader.h

Expand All @@ -80,11 +90,8 @@ if (${_OPT}use_ffmpeg)
impl/avformat/AVStreamWrapperImpl.inl
impl/avutil/AVFrameWrapperImpl.inl
impl/avutil/FFmpegLogImpl.inl
impl/ffmpeg-2.3.6-single-header.h
impl/ffmpeg-4.2.4-single-header.h
impl/avutil/52/avconfig.h
impl/avutil/56/avconfig.h
)

set( LIBRARIES
PRIVATE
wxBase
Expand Down
105 changes: 83 additions & 22 deletions libraries/lib-ffmpeg-support/FFmpegFunctions.cpp
Expand Up @@ -208,7 +208,8 @@ struct FFmpegFunctions::Private final
functions.AVUtilVersion.Major, UtilFactories))
return false;

functions.avcodec_register_all();
if (functions.avcodec_register_all)
functions.avcodec_register_all();

if (functions.av_register_all)
functions.av_register_all();
Expand Down Expand Up @@ -346,9 +347,9 @@ FFmpegFunctions::CreateAVFormatContext() const
}

std::unique_ptr<AVStreamWrapper>
FFmpegFunctions::CreateAVStreamWrapper(AVStream* stream) const
FFmpegFunctions::CreateAVStreamWrapper(AVStream* stream, bool forEncoding) const
{
return mPrivate->FormatFactories.CreateAVStreamWrapper(*this, stream);
return mPrivate->FormatFactories.CreateAVStreamWrapper(*this, stream, forEncoding);
}

std::unique_ptr<AVPacketWrapper> FFmpegFunctions::CreateAVPacketWrapper() const
Expand Down Expand Up @@ -379,7 +380,7 @@ std::unique_ptr<AVOutputFormatWrapper> FFmpegFunctions::GuessOutputFormat(

std::unique_ptr<AVOutputFormatWrapper>
FFmpegFunctions::CreateAVOutputFormatWrapper(
AVOutputFormat* outputFormat) const
const AVOutputFormat* outputFormat) const
{
return mPrivate->FormatFactories.CreateAVOutputFormatWrapper(outputFormat);
}
Expand All @@ -398,7 +399,7 @@ FFmpegFunctions::CreateDecoder(AVCodecIDFwd codecID) const
std::unique_ptr<AVCodecWrapper>
FFmpegFunctions::CreateEncoder(AVCodecIDFwd codecID) const
{
AVCodec* codec = avcodec_find_encoder(codecID);
auto codec = avcodec_find_encoder(codecID);

if (codec == nullptr)
return {};
Expand All @@ -409,7 +410,7 @@ FFmpegFunctions::CreateEncoder(AVCodecIDFwd codecID) const
std::unique_ptr<AVCodecWrapper>
FFmpegFunctions::CreateEncoder(const char* name) const
{
AVCodec* codec = avcodec_find_encoder_by_name(name);
auto codec = avcodec_find_encoder_by_name(name);

if (codec == nullptr)
return {};
Expand All @@ -435,32 +436,92 @@ FFmpegFunctions::CreateAVCodecContextWrapperFromCodec(
*this, std::move(codec));
}

std::unique_ptr<AVOutputFormatWrapper>
FFmpegFunctions::GetNextOutputFormat(const AVOutputFormatWrapper* fmt) const
const std::vector<const AVOutputFormatWrapper*>&
FFmpegFunctions::GetOutputFormats() const
{
AVOutputFormat* outputFormat =
av_oformat_next(fmt != nullptr ? fmt->GetWrappedValue() : nullptr);
if (mOutputFormats.empty())
const_cast<FFmpegFunctions*>(this)->FillOuptutFormatsList();

if (outputFormat == nullptr)
return {};

return mPrivate->FormatFactories.CreateAVOutputFormatWrapper(outputFormat);
return mOutputFormatPointers;
}

std::unique_ptr<AVCodecWrapper>
FFmpegFunctions::GetNextCodec(const AVCodecWrapper* codec) const
const std::vector<const AVCodecWrapper*>& FFmpegFunctions::GetCodecs() const
{
AVCodec* nextCodec =
av_codec_next(codec != nullptr ? codec->GetWrappedValue() : nullptr);

if (nextCodec == nullptr)
return {};
if (mCodecs.empty())
const_cast<FFmpegFunctions*>(this)->FillCodecsList();

return mPrivate->CodecFactories.CreateAVCodecWrapper(nextCodec);
return mCodecPointers;
}

std::unique_ptr<AVFifoBufferWrapper>
FFmpegFunctions::CreateFifoBuffer(int size) const
{
return std::make_unique<AVFifoBufferWrapper>(*this, size);
}

void FFmpegFunctions::FillCodecsList()
{
mCodecs.clear();
mCodecPointers.clear();

if (av_codec_iterate != nullptr)
{
const AVCodec* currentCodec = nullptr;
void* i = 0;

while ((currentCodec = av_codec_iterate(&i)))
{
mCodecs.emplace_back(
mPrivate->CodecFactories.CreateAVCodecWrapper(currentCodec));
}
}
else if (av_codec_next != nullptr)
{
AVCodec* currentCodec = nullptr;

while ((currentCodec = av_codec_next(currentCodec)) != nullptr)
{
mCodecs.emplace_back(
mPrivate->CodecFactories.CreateAVCodecWrapper(currentCodec));
}
}

mCodecPointers.reserve(mCodecs.size());

for (const auto& codec : mCodecs)
mCodecPointers.emplace_back(codec.get());
}

void FFmpegFunctions::FillOuptutFormatsList()
{
mOutputFormats.clear();
mOutputFormatPointers.clear();

if (av_muxer_iterate != nullptr)
{
const AVOutputFormat* currentFormat = nullptr;
void* i = 0;

while ((currentFormat = av_muxer_iterate(&i)))
{
mOutputFormats.emplace_back(
mPrivate->FormatFactories.CreateAVOutputFormatWrapper(
currentFormat));
}
}
else if (av_oformat_next != nullptr)
{
AVOutputFormat* currentFormat = nullptr;

while ((currentFormat = av_oformat_next(currentFormat)) != nullptr)
{
mOutputFormats.emplace_back(
mPrivate->FormatFactories.CreateAVOutputFormatWrapper(currentFormat));
}
}

mOutputFormatPointers.reserve(mOutputFormats.size());

for (const auto& format : mOutputFormats)
mOutputFormatPointers.emplace_back(format.get());
}
19 changes: 14 additions & 5 deletions libraries/lib-ffmpeg-support/FFmpegFunctions.h
Expand Up @@ -96,7 +96,7 @@ struct FFMPEG_SUPPORT_API FFmpegFunctions :
std::unique_ptr<AVIOContextWrapper> CreateAVIOContext() const;
std::unique_ptr<AVFormatContextWrapper> CreateAVFormatContext() const;

std::unique_ptr<AVStreamWrapper> CreateAVStreamWrapper(AVStream* stream) const;
std::unique_ptr<AVStreamWrapper> CreateAVStreamWrapper(AVStream* stream, bool forEncoding) const;

//! @post return value is not null
std::unique_ptr<AVPacketWrapper> CreateAVPacketWrapper() const;
Expand All @@ -105,7 +105,7 @@ struct FFMPEG_SUPPORT_API FFmpegFunctions :
std::unique_ptr<AVFrameWrapper> CreateAVFrameWrapper() const;

std::unique_ptr<AVInputFormatWrapper> CreateAVInputFormatWrapper(AVInputFormat* inputFormat) const;
std::unique_ptr<AVOutputFormatWrapper> CreateAVOutputFormatWrapper(AVOutputFormat* outputFormat) const;
std::unique_ptr<AVOutputFormatWrapper> CreateAVOutputFormatWrapper(const AVOutputFormat* outputFormat) const;

std::unique_ptr<AVCodecWrapper> CreateDecoder(AVCodecIDFwd codecID) const;
std::unique_ptr<AVCodecWrapper> CreateEncoder(AVCodecIDFwd codecID) const;
Expand All @@ -115,9 +115,9 @@ struct FFMPEG_SUPPORT_API FFmpegFunctions :
std::unique_ptr<AVCodecContextWrapper> CreateAVCodecContextWrapperFromCodec(std::unique_ptr<AVCodecWrapper> codec) const;

std::unique_ptr<AVOutputFormatWrapper> GuessOutputFormat(const char* short_name, const char* filename, const char* mime_type);
std::unique_ptr<AVOutputFormatWrapper> GetNextOutputFormat(const AVOutputFormatWrapper* fmt) const;

std::unique_ptr<AVCodecWrapper> GetNextCodec(const AVCodecWrapper* codec) const;

const std::vector<const AVOutputFormatWrapper*>& GetOutputFormats() const;
const std::vector<const AVCodecWrapper*>& GetCodecs() const;

std::unique_ptr<AVFifoBufferWrapper> CreateFifoBuffer(int size) const;

Expand All @@ -128,8 +128,17 @@ struct FFMPEG_SUPPORT_API FFmpegFunctions :
}

private:
void FillCodecsList();
void FillOuptutFormatsList();

struct Private;
std::unique_ptr<Private> mPrivate;

std::vector<const AVCodecWrapper*> mCodecPointers;
std::vector<std::unique_ptr<AVCodecWrapper>> mCodecs;

std::vector<const AVOutputFormatWrapper*> mOutputFormatPointers;
std::vector<std::unique_ptr<AVOutputFormatWrapper>> mOutputFormats;
};

template<typename T>
Expand Down
5 changes: 5 additions & 0 deletions libraries/lib-ffmpeg-support/FFmpegTypes.h
Expand Up @@ -13,6 +13,9 @@
#include <cstdint>
#include <errno.h>

#define AUDACITY_MKTAG(a, b, c, d) ((a) | ((b) << 8) | ((c) << 16) | ((unsigned)(d) << 24))
#define AUDACITY_FFERRTAG(a, b, c, d) (-(int)AUDACITY_MKTAG(a, b, c, d))

#if EDOM > 0
# define AUDACITY_AVERROR(e) \
(-(e)) ///< Returns a negative error code from a POSIX error code, to
Expand All @@ -26,6 +29,8 @@
# define AUDACITY_AVUNERROR(e) (e)
#endif

#define AUDACITY_AVERROR_EOF AUDACITY_FFERRTAG('E', 'O', 'F', ' ')

#define AUDACITY_AVFMT_NOFILE 0x0001
/*
#define AVFMT_NEEDNUMBER 0x0002
Expand Down
6 changes: 3 additions & 3 deletions libraries/lib-ffmpeg-support/impl/FFmpegAPIResolver.h
Expand Up @@ -33,7 +33,7 @@ struct AVCodecFactories final
{
std::unique_ptr<AVCodecContextWrapper> (*CreateAVCodecContextWrapper)(const FFmpegFunctions&, AVCodecContext*) = nullptr;
std::unique_ptr<AVCodecContextWrapper> (*CreateAVCodecContextWrapperFromCodec)(const FFmpegFunctions&, std::unique_ptr<AVCodecWrapper>) = nullptr;
std::unique_ptr<AVCodecWrapper> (*CreateAVCodecWrapper) (AVCodec*) = nullptr;
std::unique_ptr<AVCodecWrapper> (*CreateAVCodecWrapper) (const AVCodec*) = nullptr;

//! @post return value is not null
std::unique_ptr<AVPacketWrapper> (*CreateAVPacketWrapper) (const FFmpegFunctions&) = nullptr;
Expand All @@ -50,8 +50,8 @@ struct AVFormatFactories final
std::unique_ptr<AVFormatContextWrapper> (*CreateAVFormatContextWrapper) (const FFmpegFunctions&) = nullptr;
std::unique_ptr<AVInputFormatWrapper> (*CreateAVInputFormatWrapper) (AVInputFormat*) = nullptr;
std::unique_ptr<AVIOContextWrapper> (*CreateAVIOContextWrapper) (const FFmpegFunctions&) = nullptr;
std::unique_ptr<AVOutputFormatWrapper> (*CreateAVOutputFormatWrapper) (AVOutputFormat*) = nullptr;
std::unique_ptr<AVStreamWrapper> (*CreateAVStreamWrapper) (const FFmpegFunctions&, AVStream*) = nullptr;
std::unique_ptr<AVOutputFormatWrapper> (*CreateAVOutputFormatWrapper) (const AVOutputFormat*) = nullptr;
std::unique_ptr<AVStreamWrapper> (*CreateAVStreamWrapper) (const FFmpegFunctions&, AVStream*, bool) = nullptr;
};

class AVFrameWrapper;
Expand Down

0 comments on commit 20ab323

Please sign in to comment.