diff options
author | Niklas Haas <git@haasn.dev> | 2024-04-03 22:19:28 +0200 |
---|---|---|
committer | Niklas Haas <git@haasn.dev> | 2024-09-08 13:59:25 +0200 |
commit | 3305767560a6303f474fffa3afb10c500059b455 (patch) | |
tree | c94bba9e72eebcbf78288a7e1c02f2797dd58854 /libavcodec/avcodec.c | |
parent | 703288cec6522655e8533c89efa3cd6df9613b99 (diff) | |
download | ffmpeg-3305767560a6303f474fffa3afb10c500059b455.tar.gz |
avcodec: add avcodec_get_supported_config()
This replaces the myriad of existing lists in AVCodec by a unified API
call, allowing us to (ultimately) trim down the sizeof(AVCodec) quite
substantially, while also making this more trivially extensible.
In addition to the already covered lists, add two new entries for color
space and color range, mirroring the newly added negotiable fields in
libavfilter.
Once the deprecation period passes for the existing public fields, the
rough plan is to move the commonly used fields (such as
pix_fmt/sample_fmt) into FFCodec, possibly as a union of audio and video
configuration types, and then implement the rarely used fields with
custom callbacks.
Diffstat (limited to 'libavcodec/avcodec.c')
-rw-r--r-- | libavcodec/avcodec.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index 765328660b..cb89236549 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -28,6 +28,7 @@ #include "libavutil/avstring.h" #include "libavutil/bprint.h" #include "libavutil/channel_layout.h" +#include "libavutil/common.h" #include "libavutil/emms.h" #include "libavutil/fifo.h" #include "libavutil/imgutils.h" @@ -706,3 +707,96 @@ int attribute_align_arg avcodec_receive_frame(AVCodecContext *avctx, AVFrame *fr return ff_decode_receive_frame(avctx, frame); return ff_encode_receive_frame(avctx, frame); } + +#define WRAP_CONFIG(allowed_type, field, terminator) \ + do { \ + static const __typeof__(*(field)) end = terminator; \ + if (codec->type != (allowed_type)) \ + return AVERROR(EINVAL); \ + *out_configs = (field); \ + if (out_num_configs) { \ + for (int i = 0;; i++) { \ + if (!(field) || !memcmp(&(field)[i], &end, sizeof(end))) { \ + *out_num_configs = i; \ + break; \ + } \ + } \ + } \ + return 0; \ + } while (0) + +static const enum AVColorRange color_range_jpeg[] = { + AVCOL_RANGE_JPEG, AVCOL_RANGE_UNSPECIFIED +}; + +static const enum AVColorRange color_range_mpeg[] = { + AVCOL_RANGE_MPEG, AVCOL_RANGE_UNSPECIFIED +}; + +static const enum AVColorRange color_range_all[] = { + AVCOL_RANGE_MPEG, AVCOL_RANGE_JPEG, AVCOL_RANGE_UNSPECIFIED +}; + +static const enum AVColorRange *color_range_table[] = { + [AVCOL_RANGE_MPEG] = color_range_mpeg, + [AVCOL_RANGE_JPEG] = color_range_jpeg, + [AVCOL_RANGE_MPEG | AVCOL_RANGE_JPEG] = color_range_all, +}; + +int ff_default_get_supported_config(const AVCodecContext *avctx, + const AVCodec *codec, + enum AVCodecConfig config, + unsigned flags, + const void **out_configs, + int *out_num_configs) +{ + switch (config) { +FF_DISABLE_DEPRECATION_WARNINGS + case AV_CODEC_CONFIG_PIX_FORMAT: + WRAP_CONFIG(AVMEDIA_TYPE_VIDEO, codec->pix_fmts, AV_PIX_FMT_NONE); + case AV_CODEC_CONFIG_FRAME_RATE: + WRAP_CONFIG(AVMEDIA_TYPE_VIDEO, codec->supported_framerates, (AVRational){0}); + case AV_CODEC_CONFIG_SAMPLE_RATE: + WRAP_CONFIG(AVMEDIA_TYPE_AUDIO, codec->supported_samplerates, 0); + case AV_CODEC_CONFIG_SAMPLE_FORMAT: + WRAP_CONFIG(AVMEDIA_TYPE_AUDIO, codec->sample_fmts, AV_SAMPLE_FMT_NONE); + case AV_CODEC_CONFIG_CHANNEL_LAYOUT: + WRAP_CONFIG(AVMEDIA_TYPE_AUDIO, codec->ch_layouts, (AVChannelLayout){0}); +FF_ENABLE_DEPRECATION_WARNINGS + + case AV_CODEC_CONFIG_COLOR_RANGE: + if (codec->type != AVMEDIA_TYPE_VIDEO) + return AVERROR(EINVAL); + *out_configs = color_range_table[ffcodec(codec)->color_ranges]; + if (out_num_configs) + *out_num_configs = av_popcount(ffcodec(codec)->color_ranges); + return 0; + + case AV_CODEC_CONFIG_COLOR_SPACE: + *out_configs = NULL; + if (out_num_configs) + *out_num_configs = 0; + return 0; + default: + return AVERROR(EINVAL); + } +} + +int avcodec_get_supported_config(const AVCodecContext *avctx, const AVCodec *codec, + enum AVCodecConfig config, unsigned flags, + const void **out, int *out_num) +{ + const FFCodec *codec2; + int dummy_num = 0; + if (!codec) + codec = avctx->codec; + if (!out_num) + out_num = &dummy_num; + + codec2 = ffcodec(codec); + if (codec2->get_supported_config) { + return codec2->get_supported_config(avctx, codec, config, flags, out, out_num); + } else { + return ff_default_get_supported_config(avctx, codec, config, flags, out, out_num); + } +} |