| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567 |
- #pragma once
- /**
- * FFmpeg Version Compatibility Header
- * This file provides compatibility macros and functions for different FFmpeg versions
- * Supports FFmpeg 3.x, 4.x, 5.x, 6.x, and 7.x
- */
- extern "C" {
- #include <libavcodec/avcodec.h>
- #include <libavcodec/bsf.h>
- #include <libavdevice/avdevice.h>
- #include <libavformat/avformat.h>
- #include <libavutil/channel_layout.h>
- #include <libavutil/frame.h>
- #include <libavutil/imgutils.h>
- #include <libavutil/pixfmt.h>
- #include <libavutil/time.h>
- #include <libswresample/swresample.h>
- #include <libswscale/swscale.h>
- }
- // FFmpeg version detection
- #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100)
- #define FFMPEG_VERSION_MAJOR 3
- #elif LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(59, 0, 100)
- #define FFMPEG_VERSION_MAJOR 4
- #elif LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(60, 0, 100)
- #define FFMPEG_VERSION_MAJOR 5
- #elif LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(61, 0, 100)
- #define FFMPEG_VERSION_MAJOR 6
- #else
- #define FFMPEG_VERSION_MAJOR 7
- #endif
- // Compatibility functions for deprecated functions
- inline void ffmpeg_register_all() {
- #if FFMPEG_VERSION_MAJOR < 4
- av_register_all();
- #endif
- // No-op in FFmpeg 4.0+
- }
- inline void ffmpeg_register_devices() {
- #if FFMPEG_VERSION_MAJOR < 4
- avdevice_register_all();
- #endif
- // No-op in FFmpeg 4.0+
- }
- // Compatibility for AVInputFormat/AVOutputFormat
- #if FFMPEG_VERSION_MAJOR >= 4
- using FFmpegInputFormat = const AVInputFormat;
- using FFmpegOutputFormat = const AVOutputFormat;
- #else
- using FFmpegInputFormat = AVInputFormat;
- using FFmpegOutputFormat = AVOutputFormat;
- #endif
- // Compatibility for AVCodec pointer
- #if FFMPEG_VERSION_MAJOR >= 7
- using FFmpegCodec = const AVCodec;
- #else
- using FFmpegCodec = AVCodec;
- #endif
- // Compatibility for av_err2str macro (C++ safe version)
- #ifdef __cplusplus
- #undef av_err2str
- #ifdef _MSC_VER
- #include <malloc.h>
- #define av_err2str(errnum) av_make_error_string((char*)_alloca(AV_ERROR_MAX_STRING_SIZE), AV_ERROR_MAX_STRING_SIZE, errnum)
- #else
- #define av_err2str(errnum) av_make_error_string((char*)__builtin_alloca(AV_ERROR_MAX_STRING_SIZE), AV_ERROR_MAX_STRING_SIZE, errnum)
- #endif
- #endif
- // Compatibility for bitstream filter context
- #if FFMPEG_VERSION_MAJOR >= 4
- using AVBitStreamFilterContext = AVBSFContext;
- #else
- // For FFmpeg 3.x, AVBitStreamFilterContext is already defined
- // No need to redefine it
- #endif
- // Compatibility functions for codec context access
- inline AVMediaType ffmpeg_get_codec_type(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->codec_type;
- #else
- return stream->codec->codec_type;
- #endif
- }
- inline AVCodecID ffmpeg_get_codec_id(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->codec_id;
- #else
- return stream->codec->codec_id;
- #endif
- }
- inline int ffmpeg_get_codec_width(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->width;
- #else
- return stream->codec->width;
- #endif
- }
- inline int ffmpeg_get_codec_height(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->height;
- #else
- return stream->codec->height;
- #endif
- }
- inline AVPixelFormat ffmpeg_get_codec_pix_fmt(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return static_cast<AVPixelFormat>(stream->codecpar->format);
- #else
- return stream->codec->pix_fmt;
- #endif
- }
- inline int ffmpeg_get_codec_sample_rate(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->sample_rate;
- #else
- return stream->codec->sample_rate;
- #endif
- }
- inline int ffmpeg_get_codec_channels(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 7
- return stream->codecpar->ch_layout.nb_channels;
- #elif FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->channels;
- #else
- return stream->codec->channels;
- #endif
- }
- inline uint64_t ffmpeg_get_codec_channel_layout(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 7
- // In FFmpeg 7, use ch_layout.u.mask directly if it's a mask layout
- if (stream->codecpar->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
- return stream->codecpar->ch_layout.u.mask;
- } else {
- // For non-mask layouts, return a default stereo layout
- return AV_CH_LAYOUT_STEREO;
- }
- #elif FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->channel_layout;
- #else
- return stream->codec->channel_layout;
- #endif
- }
- inline AVSampleFormat ffmpeg_get_codec_sample_fmt(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return static_cast<AVSampleFormat>(stream->codecpar->format);
- #else
- return stream->codec->sample_fmt;
- #endif
- }
- // Compatibility for channel layout functions
- inline uint64_t ffmpeg_get_default_channel_layout(int channels) {
- #if FFMPEG_VERSION_MAJOR >= 7
- AVChannelLayout ch_layout;
- av_channel_layout_default(&ch_layout, channels);
- if (ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
- return ch_layout.u.mask;
- } else {
- // Fallback for common channel counts
- switch (channels) {
- case 1: return AV_CH_LAYOUT_MONO;
- case 2: return AV_CH_LAYOUT_STEREO;
- case 6: return AV_CH_LAYOUT_5POINT1;
- case 8: return AV_CH_LAYOUT_7POINT1;
- default: return AV_CH_LAYOUT_STEREO;
- }
- }
- #else
- return av_get_default_channel_layout(channels);
- #endif
- }
- // Compatibility for filter registration
- inline void ffmpeg_register_filters() {
- #if FFMPEG_VERSION_MAJOR < 4
- avfilter_register_all();
- #endif
- // No-op in FFmpeg 4.0+
- }
- // Compatibility for channel layout string functions
- inline int ffmpeg_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout) {
- #if FFMPEG_VERSION_MAJOR >= 7
- (void)nb_channels; // Suppress unused parameter warning
- AVChannelLayout ch_layout;
- av_channel_layout_from_mask(&ch_layout, channel_layout);
- return av_channel_layout_describe(&ch_layout, buf, buf_size);
- #else
- av_get_channel_layout_string(buf, buf_size, nb_channels, channel_layout);
- return strlen(buf);
- #endif
- }
- // Compatibility for AVFrame channels access
- inline int ffmpeg_get_frame_channels(AVFrame* frame) {
- #if FFMPEG_VERSION_MAJOR >= 7
- return frame->ch_layout.nb_channels;
- #else
- return frame->channels;
- #endif
- }
- // Compatibility for AVFrame channel_layout access
- inline uint64_t ffmpeg_get_frame_channel_layout(AVFrame* frame) {
- #if FFMPEG_VERSION_MAJOR >= 7
- if (frame->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
- return frame->ch_layout.u.mask;
- } else {
- return AV_CH_LAYOUT_STEREO;
- }
- #else
- return frame->channel_layout;
- #endif
- }
- // Compatibility for av_samples_get_buffer_size
- inline int ffmpeg_get_buffer_size(enum AVSampleFormat sample_fmt, int nb_channels, int nb_samples, int align) {
- #if FFMPEG_VERSION_MAJOR >= 7
- return av_samples_get_buffer_size(nullptr, nb_channels, nb_samples, sample_fmt, align);
- #else
- return av_samples_get_buffer_size(nullptr, nb_channels, nb_samples, sample_fmt, align);
- #endif
- }
- // Compatibility for codec context creation from stream
- inline AVCodecContext* ffmpeg_get_codec_context(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- const AVCodec* codec = avcodec_find_decoder(stream->codecpar->codec_id);
- if (!codec) return nullptr;
-
- AVCodecContext* ctx = avcodec_alloc_context3(codec);
- if (!ctx) return nullptr;
-
- if (avcodec_parameters_to_context(ctx, stream->codecpar) < 0) {
- avcodec_free_context(&ctx);
- return nullptr;
- }
-
- return ctx;
- #else
- return stream->codec;
- #endif
- }
- // Compatibility for setting stream codec parameters
- inline void ffmpeg_set_stream_codec_id(AVStream* stream, enum AVCodecID codec_id) {
- #if FFMPEG_VERSION_MAJOR >= 4
- stream->codecpar->codec_id = codec_id;
- #else
- stream->codec->codec_id = codec_id;
- #endif
- }
- inline void ffmpeg_set_stream_codec_type(AVStream* stream, enum AVMediaType codec_type) {
- #if FFMPEG_VERSION_MAJOR >= 4
- stream->codecpar->codec_type = codec_type;
- #else
- stream->codec->codec_type = codec_type;
- #endif
- }
- inline void ffmpeg_set_stream_bit_rate(AVStream* stream, int64_t bit_rate) {
- #if FFMPEG_VERSION_MAJOR >= 4
- stream->codecpar->bit_rate = bit_rate;
- #else
- stream->codec->bit_rate = bit_rate;
- #endif
- }
- inline void ffmpeg_set_stream_pix_fmt(AVStream* stream, enum AVPixelFormat pix_fmt) {
- #if FFMPEG_VERSION_MAJOR >= 4
- stream->codecpar->format = pix_fmt;
- #else
- stream->codec->pix_fmt = pix_fmt;
- #endif
- }
- inline void ffmpeg_set_stream_dimensions(AVStream* stream, int width, int height) {
- #if FFMPEG_VERSION_MAJOR >= 4
- stream->codecpar->width = width;
- stream->codecpar->height = height;
- #else
- stream->codec->width = width;
- stream->codec->height = height;
- #endif
- }
- // Compatibility for stream codec parameters
- inline int ffmpeg_copy_codec_params_to_stream(AVStream* stream, AVCodecContext* codec_ctx) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return avcodec_parameters_from_context(stream->codecpar, codec_ctx);
- #else
- return 0; // No-op for older versions
- #endif
- }
- // Compatibility for extradata access
- inline uint8_t* ffmpeg_get_extradata(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->extradata;
- #else
- return stream->codec->extradata;
- #endif
- }
- inline int ffmpeg_get_extradata_size(AVStream* stream) {
- #if FFMPEG_VERSION_MAJOR >= 4
- return stream->codecpar->extradata_size;
- #else
- return stream->codec->extradata_size;
- #endif
- }
- inline void ffmpeg_set_stream_extradata(AVStream* stream, uint8_t* data, int size) {
- #if FFMPEG_VERSION_MAJOR >= 4
- stream->codecpar->extradata = data;
- stream->codecpar->extradata_size = size;
- #else
- stream->codec->extradata = data;
- stream->codec->extradata_size = size;
- #endif
- }
- // Compatibility for AVCodecContext channels and channel_layout
- inline void ffmpeg_set_codec_channels(AVCodecContext* ctx, int channels) {
- #if FFMPEG_VERSION_MAJOR >= 7
- av_channel_layout_default(&ctx->ch_layout, channels);
- #else
- ctx->channels = channels;
- #endif
- }
- inline void ffmpeg_set_codec_channel_layout(AVCodecContext* ctx, uint64_t channel_layout) {
- #if FFMPEG_VERSION_MAJOR >= 7
- av_channel_layout_from_mask(&ctx->ch_layout, channel_layout);
- #else
- ctx->channel_layout = channel_layout;
- #endif
- }
- inline int ffmpeg_get_codec_context_channels(AVCodecContext* ctx) {
- #if FFMPEG_VERSION_MAJOR >= 7
- return ctx->ch_layout.nb_channels;
- #else
- return ctx->channels;
- #endif
- }
- // Compatibility for swr_alloc_set_opts
- inline SwrContext* ffmpeg_swr_alloc_set_opts(SwrContext *s,
- int64_t out_ch_layout, enum AVSampleFormat out_sample_fmt, int out_sample_rate,
- int64_t in_ch_layout, enum AVSampleFormat in_sample_fmt, int in_sample_rate,
- int log_offset, void *log_ctx) {
- #if FFMPEG_VERSION_MAJOR >= 7
- SwrContext *swr_ctx = swr_alloc();
- if (!swr_ctx) return NULL;
-
- AVChannelLayout out_ch_layout_new, in_ch_layout_new;
- av_channel_layout_from_mask(&out_ch_layout_new, out_ch_layout);
- av_channel_layout_from_mask(&in_ch_layout_new, in_ch_layout);
-
- av_opt_set_chlayout(swr_ctx, "ochl", &out_ch_layout_new, 0);
- av_opt_set_int(swr_ctx, "osf", out_sample_fmt, 0);
- av_opt_set_int(swr_ctx, "osr", out_sample_rate, 0);
- av_opt_set_chlayout(swr_ctx, "ichl", &in_ch_layout_new, 0);
- av_opt_set_int(swr_ctx, "isf", in_sample_fmt, 0);
- av_opt_set_int(swr_ctx, "isr", in_sample_rate, 0);
-
- av_channel_layout_uninit(&out_ch_layout_new);
- av_channel_layout_uninit(&in_ch_layout_new);
-
- return swr_ctx;
- #else
- return swr_alloc_set_opts(s, out_ch_layout, out_sample_fmt, out_sample_rate,
- in_ch_layout, in_sample_fmt, in_sample_rate,
- log_offset, log_ctx);
- #endif
- }
- // Compatibility for codec parameters setting
- inline int ffmpeg_av_samples_alloc(uint8_t **audio_data, int *linesize, int nb_channels,
- int nb_samples, enum AVSampleFormat sample_fmt, int align) {
- #if FFMPEG_VERSION_MAJOR >= 7
- return av_samples_alloc_array_and_samples(&audio_data, linesize, nb_channels, nb_samples, sample_fmt, align);
- #else
- return av_samples_alloc(audio_data, linesize, nb_channels, nb_samples, sample_fmt, align);
- #endif
- }
- inline void ffmpeg_set_frame_channel_layout(AVFrame* frame, AVCodecContext* codec_ctx) {
- #if FFMPEG_VERSION_MAJOR >= 7
- av_channel_layout_copy(&frame->ch_layout, &codec_ctx->ch_layout);
- #else
- frame->channel_layout = codec_ctx->channel_layout;
- #endif
- }
- inline void ffmpeg_set_stream_codec_params(AVStream* stream, AVCodecContext* codec_ctx) {
- #if FFMPEG_VERSION_MAJOR >= 7
- stream->codecpar->codec_id = codec_ctx->codec_id;
- stream->codecpar->bit_rate = codec_ctx->bit_rate;
- stream->codecpar->width = codec_ctx->width;
- stream->codecpar->height = codec_ctx->height;
- stream->codecpar->format = codec_ctx->pix_fmt;
- stream->codecpar->sample_rate = codec_ctx->sample_rate;
- av_channel_layout_copy(&stream->codecpar->ch_layout, &codec_ctx->ch_layout);
- stream->time_base = codec_ctx->time_base;
- #elif FFMPEG_VERSION_MAJOR >= 4
- stream->codecpar->codec_id = codec_ctx->codec_id;
- stream->codecpar->bit_rate = codec_ctx->bit_rate;
- stream->codecpar->width = codec_ctx->width;
- stream->codecpar->height = codec_ctx->height;
- stream->codecpar->format = codec_ctx->pix_fmt;
- stream->codecpar->sample_rate = codec_ctx->sample_rate;
- stream->codecpar->channels = codec_ctx->channels;
- stream->codecpar->channel_layout = codec_ctx->channel_layout;
- stream->time_base = codec_ctx->time_base;
- #else
- *(stream->codec) = *codec_ctx;
- #endif
- }
- // Additional compatibility functions for missing identifiers
- inline int ffmpeg_get_channels(AVCodecContext* ctx) {
- #if FFMPEG_VERSION_MAJOR >= 7
- return ctx->ch_layout.nb_channels;
- #else
- return ctx->channels;
- #endif
- }
- inline void ffmpeg_set_channels(AVCodecContext* ctx, int channels) {
- #if FFMPEG_VERSION_MAJOR >= 7
- av_channel_layout_default(&ctx->ch_layout, channels);
- #else
- ctx->channels = channels;
- #endif
- }
- inline void ffmpeg_set_channel_layout(AVCodecContext* ctx, uint64_t channel_layout) {
- #if FFMPEG_VERSION_MAJOR >= 7
- av_channel_layout_from_mask(&ctx->ch_layout, channel_layout);
- #else
- ctx->channel_layout = channel_layout;
- #endif
- }
- inline void ffmpeg_set_frame_channels(AVFrame* frame, int channels) {
- #if FFMPEG_VERSION_MAJOR >= 7
- av_channel_layout_default(&frame->ch_layout, channels);
- #else
- frame->channels = channels;
- #endif
- }
- inline void ffmpeg_set_frame_channel_layout(AVFrame* frame, uint64_t channel_layout) {
- #if FFMPEG_VERSION_MAJOR >= 7
- av_channel_layout_from_mask(&frame->ch_layout, channel_layout);
- #else
- frame->channel_layout = channel_layout;
- #endif
- }
- inline void ffmpeg_set_frame_pkt_pts(AVFrame* frame, int64_t pts) {
- #if FFMPEG_VERSION_MAJOR >= 4
- frame->pts = pts;
- #else
- frame->pkt_pts = pts;
- #endif
- }
- // Compatibility for bitstream filter initialization
- #if FFMPEG_VERSION_MAJOR >= 4
- inline AVBitStreamFilterContext* ffmpeg_bitstream_filter_init(const char* name)
- {
- const AVBitStreamFilter* bsf = av_bsf_get_by_name(name);
- if (!bsf) return nullptr;
-
- AVBSFContext* ctx = nullptr;
- if (av_bsf_alloc(bsf, &ctx) < 0) return nullptr;
-
- return ctx;
- }
- #else
- inline AVBitStreamFilterContext* ffmpeg_bitstream_filter_init(const char* name) {
- // For FFmpeg 3.x, use the old API
- return av_bitstream_filter_init(name);
- }
- #endif
- #if FFMPEG_VERSION_MAJOR >= 4
- inline void ffmpeg_bitstream_filter_close(AVBitStreamFilterContext* ctx) {
- if (ctx) {
- av_bsf_free(&ctx);
- }
- }
- #else
- inline void ffmpeg_bitstream_filter_close(AVBitStreamFilterContext* ctx) {
- if (ctx) {
- av_bitstream_filter_close(ctx);
- }
- }
- #endif
- #if FFMPEG_VERSION_MAJOR >= 4
- inline int ffmpeg_bitstream_filter_filter(AVBitStreamFilterContext* ctx, AVPacket* packet) {
- if (!ctx || !packet) return -1;
-
- // 对于新版本FFmpeg,需要先初始化BSF上下文
- if (ctx->par_in && ctx->par_in->codec_type == AVMEDIA_TYPE_UNKNOWN) {
- // 从packet推断参数
- ctx->par_in->codec_type = AVMEDIA_TYPE_AUDIO;
- ctx->par_in->codec_id = AV_CODEC_ID_AAC;
-
- if (avcodec_parameters_copy(ctx->par_out, ctx->par_in) < 0) {
- return -1;
- }
-
- if (av_bsf_init(ctx) < 0) {
- return -1;
- }
- }
-
- int ret = av_bsf_send_packet(ctx, packet);
- if (ret < 0) return ret;
-
- ret = av_bsf_receive_packet(ctx, packet);
- return ret;
- }
- #else
- inline int ffmpeg_bitstream_filter_filter(AVBitStreamFilterContext* ctx, AVPacket* packet) {
- if (!ctx || !packet) return -1;
-
- uint8_t* output_data = nullptr;
- int output_size = 0;
-
- int ret = av_bitstream_filter_filter(ctx, nullptr, nullptr, &output_data, &output_size,
- packet->data, packet->size, packet->flags & AV_PKT_FLAG_KEY);
-
- if (ret >= 0 && output_data && output_size > 0) {
- av_packet_unref(packet);
- packet->data = output_data;
- packet->size = output_size;
- packet->buf = av_buffer_create(output_data, output_size, av_buffer_default_free, nullptr, 0);
- }
-
- return ret;
- }
- #endif
|