diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c
index a83d24cf18a8b..189721870d55c 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 83f52e590fa33..dece312753890 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 0000000000000..273846990952d
--- /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 d91e1e7b2c04b..0b7eb36c0c820 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 @@ static bool write_avif(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
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 2842335d1391f..8e643c65a813c 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++;