diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c index a83d24cf18..189721870d 100644 --- a/audio/filter/af_lavcac3enc.c +++ b/audio/filter/af_lavcac3enc.c @@ -45,6 +45,7 @@ #include "filters/filter_internal.h" #include "filters/user_filters.h" #include "options/m_option.h" +#include "misc/lavc_compat.h" #define AC3_MAX_CHANNELS 6 @@ -283,10 +284,14 @@ static const struct mp_filter_info af_lavcac3enc_filter = { static void add_chmaps_to_autoconv(struct mp_filter *f, struct mp_autoconvert *conv, - const struct AVCodec *codec) + const AVCodecContext *avctx) { - const AVChannelLayout *lch = codec->ch_layouts; - for (int n = 0; lch && lch[n].nb_channels; n++) { + const AVChannelLayout *lch; + int ret = mp_avcodec_get_supported_config(avctx, NULL, + AV_CODEC_CONFIG_CHANNEL_LAYOUT, + (const void **)&lch); + + for (int n = 0; ret >= 0 && lch && lch[n].nb_channels; n++) { struct mp_chmap chmap = {0}; if (!mp_chmap_from_av_layout(&chmap, &lch[n])) { @@ -339,10 +344,20 @@ static struct mp_filter *af_lavcac3enc_create(struct mp_filter *parent, if (mp_set_avopts(f->log, s->lavc_actx, s->opts->avopts) < 0) goto error; + const AVChannelLayout *ch_layouts; + int ret_ch = mp_avcodec_get_supported_config(s->lavc_actx, s->lavc_acodec, + AV_CODEC_CONFIG_CHANNEL_LAYOUT, + (const void **)&ch_layouts); + + const enum AVSampleFormat *sample_fmts; + int ret_fmt = mp_avcodec_get_supported_config(s->lavc_actx, s->lavc_acodec, + AV_CODEC_CONFIG_SAMPLE_FORMAT, + (const void **)&sample_fmts); + // For this one, we require the decoder to export lists of all supported // parameters. (Not all decoders do that, but the ones we're interested // in do.) - if (!s->lavc_acodec->sample_fmts || !s->lavc_acodec->ch_layouts) { + if (ret_ch < 0 || !ch_layouts || ret_fmt < 0 || !sample_fmts) { MP_ERR(f, "Audio encoder doesn't list supported parameters.\n"); goto error; } @@ -366,14 +381,13 @@ static struct mp_filter *af_lavcac3enc_create(struct mp_filter *parent, if (!conv) abort(); - const enum AVSampleFormat *lf = s->lavc_acodec->sample_fmts; - for (int i = 0; lf && lf[i] != AV_SAMPLE_FMT_NONE; i++) { - int mpfmt = af_from_avformat(lf[i]); + for (int i = 0; sample_fmts[i] != AV_SAMPLE_FMT_NONE; i++) { + int mpfmt = af_from_avformat(sample_fmts[i]); if (mpfmt) mp_autoconvert_add_afmt(conv, mpfmt); } - add_chmaps_to_autoconv(f, conv, s->lavc_acodec); + add_chmaps_to_autoconv(f, conv, s->lavc_actx); // At least currently, the AC3 encoder doesn't export sample rates. mp_autoconvert_add_srate(conv, 48000); diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index 83f52e590f..dece312753 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -37,6 +37,7 @@ #include "audio/fmt-conversion.h" #include "filters/filter_internal.h" #include "filters/f_utils.h" +#include "misc/lavc_compat.h" #include "mpv_talloc.h" #include "ao.h" #include "internal.h" @@ -65,9 +66,13 @@ static bool write_frame(struct ao *ao, struct mp_frame frame); static bool supports_format(const AVCodec *codec, int format) { - for (const enum AVSampleFormat *sampleformat = codec->sample_fmts; - sampleformat && *sampleformat != AV_SAMPLE_FMT_NONE; - sampleformat++) + const enum AVSampleFormat *sampleformat; + int ret = mp_avcodec_get_supported_config(NULL, codec, + AV_CODEC_CONFIG_SAMPLE_FORMAT, + (const void **)&sampleformat); + if (ret >= 0 && !sampleformat) + return true; + for (; ret >= 0 && *sampleformat != AV_SAMPLE_FMT_NONE; sampleformat++) { if (af_from_avformat(*sampleformat) == format) return true; @@ -111,8 +116,14 @@ static int init(struct ao *ao) AVCodecContext *encoder = ac->enc->encoder; const AVCodec *codec = encoder->codec; - int samplerate = af_select_best_samplerate(ao->samplerate, - codec->supported_samplerates); + const int *samplerates; + int ret = mp_avcodec_get_supported_config(NULL, codec, + AV_CODEC_CONFIG_SAMPLE_RATE, + (const void **)&samplerates); + + int samplerate = 0; + if (ret >= 0) + samplerate = af_select_best_samplerate(ao->samplerate, samplerates); if (samplerate > 0) ao->samplerate = samplerate; diff --git a/misc/lavc_compat.h b/misc/lavc_compat.h new file mode 100644 index 0000000000..2738469909 --- /dev/null +++ b/misc/lavc_compat.h @@ -0,0 +1,66 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#pragma once + +#include + +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(61, 13, 100) +enum AVCodecConfig { + AV_CODEC_CONFIG_PIX_FORMAT, ///< AVPixelFormat, terminated by AV_PIX_FMT_NONE + AV_CODEC_CONFIG_FRAME_RATE, ///< AVRational, terminated by {0, 0} + AV_CODEC_CONFIG_SAMPLE_RATE, ///< int, terminated by 0 + AV_CODEC_CONFIG_SAMPLE_FORMAT, ///< AVSampleFormat, terminated by AV_SAMPLE_FMT_NONE + AV_CODEC_CONFIG_CHANNEL_LAYOUT, ///< AVChannelLayout, terminated by {0} + AV_CODEC_CONFIG_COLOR_RANGE, ///< AVColorRange, terminated by AVCOL_RANGE_UNSPECIFIED + AV_CODEC_CONFIG_COLOR_SPACE, ///< AVColorSpace, terminated by AVCOL_SPC_UNSPECIFIED +}; +#endif + +static inline int mp_avcodec_get_supported_config(const AVCodecContext *avctx, + const AVCodec *codec, + enum AVCodecConfig config, + const void **out_configs) +{ +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) + return avcodec_get_supported_config(avctx, codec, config, 0, out_configs, NULL); +#else + const AVCodec *avcodec = codec ? codec : avctx->codec; + + switch (config) { + case AV_CODEC_CONFIG_PIX_FORMAT: + *out_configs = avcodec->pix_fmts; + break; + case AV_CODEC_CONFIG_FRAME_RATE: + *out_configs = avcodec->supported_framerates; + break; + case AV_CODEC_CONFIG_SAMPLE_RATE: + *out_configs = avcodec->supported_samplerates; + break; + case AV_CODEC_CONFIG_SAMPLE_FORMAT: + *out_configs = avcodec->sample_fmts; + break; + case AV_CODEC_CONFIG_CHANNEL_LAYOUT: + *out_configs = avcodec->ch_layouts; + break; + default: + abort(); // Not implemented + } + + return *out_configs ? 0 : -1; +#endif +} diff --git a/video/image_writer.c b/video/image_writer.c index d91e1e7b2c..0b7eb36c0c 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -42,6 +42,7 @@ #include "common/msg.h" #include "image_writer.h" #include "mpv_talloc.h" +#include "misc/lavc_compat.h" #include "video/fmt-conversion.h" #include "video/img_format.h" #include "video/mp_image.h" @@ -490,9 +491,12 @@ free_data: static int get_encoder_format(const AVCodec *codec, int srcfmt, bool highdepth) { - const enum AVPixelFormat *pix_fmts = codec->pix_fmts; + const enum AVPixelFormat *pix_fmts; + int ret = mp_avcodec_get_supported_config(NULL, codec, + AV_CODEC_CONFIG_PIX_FORMAT, + (const void **)&pix_fmts); int current = 0; - for (int n = 0; pix_fmts && pix_fmts[n] != AV_PIX_FMT_NONE; n++) { + for (int n = 0; ret >= 0 && pix_fmts && pix_fmts[n] != AV_PIX_FMT_NONE; n++) { int fmt = pixfmt2imgfmt(pix_fmts[n]); if (!fmt) continue; diff --git a/video/out/vo_lavc.c b/video/out/vo_lavc.c index 2842335d13..8e643c65a8 100644 --- a/video/out/vo_lavc.c +++ b/video/out/vo_lavc.c @@ -27,6 +27,7 @@ #include "common/common.h" #include "options/options.h" +#include "misc/lavc_compat.h" #include "video/fmt-conversion.h" #include "video/mp_image.h" #include "mpv_talloc.h" @@ -129,8 +130,11 @@ static int reconfig2(struct vo *vo, struct mp_image *img) tb.num = 24000; tb.den = 1; - const AVRational *rates = encoder->codec->supported_framerates; - if (rates && rates[0].den) + const AVRational *rates; + int ret = mp_avcodec_get_supported_config(encoder, NULL, + AV_CODEC_CONFIG_FRAME_RATE, + (const void **)&rates); + if (ret >= 0 && rates && rates[0].den) tb = rates[av_find_nearest_q_idx(tb, rates)]; encoder->time_base = av_inv_q(tb); @@ -161,12 +165,15 @@ static int query_format(struct vo *vo, int format) struct priv *vc = vo->priv; enum AVPixelFormat pix_fmt = imgfmt2pixfmt(format); - const enum AVPixelFormat *p = vc->enc->encoder->codec->pix_fmts; + const enum AVPixelFormat *p; + int ret = mp_avcodec_get_supported_config(vc->enc->encoder, NULL, + AV_CODEC_CONFIG_PIX_FORMAT, + (const void **)&p); - if (!p) + if (ret >= 0 && !p) return 1; - while (*p != AV_PIX_FMT_NONE) { + while (ret >= 0 && p && *p != AV_PIX_FMT_NONE) { if (*p == pix_fmt) return 1; p++;