diff --git a/src/audio/codec/libavcodec.c b/src/audio/codec/libavcodec.c index 72787d849..1164214fd 100644 --- a/src/audio/codec/libavcodec.c +++ b/src/audio/codec/libavcodec.c @@ -299,9 +299,10 @@ static void *libavcodec_init(audio_codec_t audio_codec, audio_codec_direction_t } /* check that a given sample format is supported by the encoder */ -static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt) +static int +check_sample_fmt(const AVCodecContext *ctx, enum AVSampleFormat sample_fmt) { - const enum AVSampleFormat *p = codec->sample_fmts; + const enum AVSampleFormat *p = avc_get_supported_sample_fmts(ctx, NULL); while (*p != AV_SAMPLE_FMT_NONE) { if (*p == sample_fmt) @@ -367,7 +368,7 @@ static bool reinitialize_encoder(struct libavcodec_codec_state *s, struct audio_ s->codec_ctx->sample_fmt = AV_SAMPLE_FMT_NONE; for (int i = 0; i < count; ++i) { - if (check_sample_fmt(s->codec, sample_fmts[i])) { + if (check_sample_fmt(s->codec_ctx, sample_fmts[i])) { s->codec_ctx->sample_fmt = sample_fmts[i]; break; } @@ -375,10 +376,12 @@ static bool reinitialize_encoder(struct libavcodec_codec_state *s, struct audio_ if (s->codec_ctx->sample_fmt == AV_SAMPLE_FMT_NONE) { int i = 0; - while (s->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE) { - if (s->codec->sample_fmts[i] != AV_SAMPLE_FMT_DBL && - s->codec->sample_fmts[i] != AV_SAMPLE_FMT_DBLP) { - s->codec_ctx->sample_fmt = s->codec->sample_fmts[i]; + const enum AVSampleFormat *sample_fmts = + avc_get_supported_sample_fmts(s->codec_ctx, NULL); + while (sample_fmts[i] != AV_SAMPLE_FMT_NONE) { + if (sample_fmts[i] != AV_SAMPLE_FMT_DBL && + sample_fmts[i] != AV_SAMPLE_FMT_DBLP) { + s->codec_ctx->sample_fmt = sample_fmts[i]; break; } i++; @@ -736,7 +739,7 @@ static const int *libavcodec_get_sample_rates(void *state) { struct libavcodec_codec_state *s = (struct libavcodec_codec_state *) state; - return s->codec->supported_samplerates; + return avc_get_supported_sample_rates(s->codec_ctx, NULL); } static void cleanup_common(struct libavcodec_codec_state *s) diff --git a/src/libavcodec/lavc_common.c b/src/libavcodec/lavc_common.c index 6ac0631b3..95e48b219 100644 --- a/src/libavcodec/lavc_common.c +++ b/src/libavcodec/lavc_common.c @@ -347,4 +347,61 @@ get_avpixfmts_names(const enum AVPixelFormat *pixfmts) } return buf; } + +/** + * @param ctx may be nullptr if codec is not + * @param codec may be nullptr if ctx is not + * + * If passed ctx, values such as `strict_std_compliance` may afect the result. + */ +static const void * +avc_get_supported_config(const AVCodecContext *ctx, const AVCodec *codec, + enum AVCodecConfig config) +{ +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(61, 13, 100) + const void *ret = NULL; + int unused_count = 0; + const int rc = avcodec_get_supported_config( + ctx, codec, config, /*flags*/ 0, &ret, + &unused_count); + if (rc != 0) { + MSG(ERROR, "Cannot get list of supported config %d for %s!\n", + (int) config, codec->name); + return NULL; + } + + return ret; +#else + abort(); // cannot reach here (shouldn't be called) +#endif +} +///< @copydoc avc_get_supported_config +const enum AVPixelFormat * +avc_get_supported_pix_fmts(const AVCodecContext *ctx, const AVCodec *codec) +{ +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(61, 13, 100) + return avc_get_supported_config(ctx, codec, AV_CODEC_CONFIG_PIX_FORMAT); +#else + return codec->pix_fmts; +#endif +} +///< @copydoc avc_get_supported_config +const enum AVSampleFormat * +avc_get_supported_sample_fmts(const AVCodecContext *ctx, const AVCodec *codec) +{ +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(61, 13, 100) + return avc_get_supported_config(ctx, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT); +#else + return codec->pix_fmts; +#endif +} +///< @copydoc avc_get_supported_config +const int *avc_get_supported_sample_rates(const AVCodecContext *ctx, const AVCodec *codec) +{ +#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(61, 13, 100) + return avc_get_supported_config(ctx, codec, AV_CODEC_CONFIG_SAMPLE_RATE); +#else + return codec->supported_samplerates; +#endif +} /* vi: set expandtab sw=8: */ diff --git a/src/libavcodec/lavc_common.h b/src/libavcodec/lavc_common.h index df084bd00..6ba807fb9 100644 --- a/src/libavcodec/lavc_common.h +++ b/src/libavcodec/lavc_common.h @@ -122,6 +122,13 @@ struct audio_desc audio_desc_from_av_frame(const AVFrame *frm); enum AVSampleFormat audio_bps_to_av_sample_fmt(int bps, bool planar); const char *get_avpixfmts_names(const enum AVPixelFormat *pixfmts); +const enum AVPixelFormat *avc_get_supported_pix_fmts(const AVCodecContext *ctx, + const AVCodec *codec); +const enum AVSampleFormat * +avc_get_supported_sample_fmts(const AVCodecContext *ctx, const AVCodec *codec); +const int *avc_get_supported_sample_rates(const AVCodecContext *ctx, + const AVCodec *codec); + #ifdef __cplusplus } #endif diff --git a/src/video_compress/libavcodec.cpp b/src/video_compress/libavcodec.cpp index 91fb715d1..0489b29df 100644 --- a/src/video_compress/libavcodec.cpp +++ b/src/video_compress/libavcodec.cpp @@ -480,7 +480,8 @@ handle_help(bool full, string const &req_encoder, string const &req_codec) avcodec_find_encoder_by_name(req_encoder.c_str()); if (codec != nullptr) { cout << "\n"; - print_codec_supp_pix_fmts(codec->pix_fmts); + print_codec_supp_pix_fmts( + avc_get_supported_pix_fmts(nullptr, codec)); } else { MSG(ERROR, "Cannot open encoder: %s\n", req_encoder.c_str()); @@ -1123,11 +1124,11 @@ try_open_remaining_pixfmts(state_video_compress_libav *s, video_desc desc, return AV_PIX_FMT_NONE; #endif unsigned usable_fmt_cnt = 0; - if (codec->pix_fmts == nullptr) { + if (avc_get_supported_pix_fmts(nullptr, codec) == nullptr) { return AV_PIX_FMT_NONE; } - for (const auto *pix = codec->pix_fmts; *pix != AV_PIX_FMT_NONE; - ++pix) { + for (const auto *pix = avc_get_supported_pix_fmts(nullptr, codec); + *pix != AV_PIX_FMT_NONE; ++pix) { usable_fmt_cnt += 1; } if (usable_fmt_cnt == fmts_tried.size()) { @@ -1136,8 +1137,8 @@ try_open_remaining_pixfmts(state_video_compress_libav *s, video_desc desc, LOG(LOG_LEVEL_WARNING) << MOD_NAME "No direct decoder format for: " << get_codec_name(desc.color_spec) << ". Trying to convert with swscale instead.\n"; - for (const auto *pix = codec->pix_fmts; *pix != AV_PIX_FMT_NONE; - ++pix) { + for (const auto *pix = avc_get_supported_pix_fmts(nullptr, codec); + *pix != AV_PIX_FMT_NONE; ++pix) { const AVPixFmtDescriptor *fmt_desc = av_pix_fmt_desc_get(*pix); if (fmts_tried.count(*pix) == 1 || fmt_desc == nullptr || (fmt_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) != 0U) { @@ -1179,7 +1180,10 @@ static bool configure_with(struct state_video_compress_libav *s, struct video_de apply_blacklist(requested_pix_fmt, codec->name); auto requested_pix_fmt_it = requested_pix_fmt.cbegin(); set fmts_tried; - while ((pix_fmt = get_first_matching_pix_fmt(requested_pix_fmt_it, requested_pix_fmt.cend(), codec->pix_fmts)) != AV_PIX_FMT_NONE) { + while ((pix_fmt = get_first_matching_pix_fmt( + requested_pix_fmt_it, requested_pix_fmt.cend(), + avc_get_supported_pix_fmts(nullptr, codec))) != + AV_PIX_FMT_NONE) { fmts_tried.insert(pix_fmt); if(try_open_codec(s, pix_fmt, desc, ug_codec, codec)){ break; @@ -1187,7 +1191,8 @@ static bool configure_with(struct state_video_compress_libav *s, struct video_de } if (pix_fmt == AV_PIX_FMT_NONE || log_level >= LOG_LEVEL_VERBOSE) { - print_pix_fmts(requested_pix_fmt, codec->pix_fmts); + print_pix_fmts(requested_pix_fmt, + avc_get_supported_pix_fmts(nullptr, codec)); } if (pix_fmt == AV_PIX_FMT_NONE && get_commandline_param("lavc-use-codec") == NULL) {