PR #22693 opened by sohamukute URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22693 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/22693.patch
Fixes #22686 liboapv advertises several APV pixel formats, but in practice only yuv422p10le encoded successfully. The wrapper was leaving profile_idc at liboapvs default 422-10, so the other advertised formats reached oapve_encode() with the wrong APV profile and failed. This series fixes that by deriving the default APV profile from avctx->pix_fmt and validating explicit overrides. While validating the fix, I also found that APV profile names were not exposed through FFmpegs generic -profile:v handling or the APV codec descriptor. The second commit wires that up so named APV profiles work properly Split as: 1. fix the actual liboapv encode failure 2. expose APV profile names and improve profile mismatch reporting >From a4f1c224aed1102258e5bbf26eaf00a78d1c109d Mon Sep 17 00:00:00 2001 From: Soham Kute <[email protected]> Date: Fri, 3 Apr 2026 00:30:41 +0530 Subject: [PATCH 1/2] avcodec/liboapvenc: derive APV profile from pixel format The liboapv wrapper advertises gray10, 422-12, 444-10/12 and 4444-10/12 support, but it leaves profile_idc at the liboapv default set by oapve_param_default(), which is 422-10. As a result only yuv422p10le can be encoded successfully and the other advertised formats fail in oapve_encode(). Resolve this by deriving the default APV profile from avctx->pix_fmt, validating any explicit profile override after parsing oapv-params, and writing the resolved profile back to avctx. Also use ifrms.num_frms in the close path so the allocated input image buffer is actually released. Fixes #22686. --- libavcodec/liboapvenc.c | 59 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/libavcodec/liboapvenc.c b/libavcodec/liboapvenc.c index 84bd175ef6..3337513900 100644 --- a/libavcodec/liboapvenc.c +++ b/libavcodec/liboapvenc.c @@ -59,8 +59,6 @@ typedef struct ApvEncContext { oapv_frms_t ifrms; // frames for input - int num_frames; // number of frames in an access unit - int preset_id; // preset of apv ( fastest, fast, medium, slow, placebo) int qp; // quantization parameter (QP) [0,63] @@ -129,6 +127,53 @@ static inline int get_color_format(enum AVPixelFormat pix_fmt) return cf; } +static inline int get_profile(enum AVPixelFormat pix_fmt) +{ + int profile = AV_PROFILE_UNKNOWN; + + switch (pix_fmt) { + case AV_PIX_FMT_GRAY10: + profile = AV_PROFILE_APV_400_10; + break; + case AV_PIX_FMT_YUV422P10: + profile = AV_PROFILE_APV_422_10; + break; + case AV_PIX_FMT_YUV422P12: + profile = AV_PROFILE_APV_422_12; + break; + case AV_PIX_FMT_YUV444P10: + profile = AV_PROFILE_APV_444_10; + break; + case AV_PIX_FMT_YUV444P12: + profile = AV_PROFILE_APV_444_12; + break; + case AV_PIX_FMT_YUVA444P10: + profile = AV_PROFILE_APV_4444_10; + break; + case AV_PIX_FMT_YUVA444P12: + profile = AV_PROFILE_APV_4444_12; + break; + default: + av_assert0(profile != AV_PROFILE_UNKNOWN); + } + + return profile; +} + +static int validate_profile(AVCodecContext *avctx, int profile) +{ + const int expected = get_profile(avctx->pix_fmt); + + if (profile != expected) { + av_log(avctx, AV_LOG_ERROR, + "Profile %d is incompatible with pixel format %s; expected %d\n", + profile, av_get_pix_fmt_name(avctx->pix_fmt), expected); + return AVERROR(EINVAL); + } + + return 0; +} + static oapv_imgb_t *apv_imgb_create(AVCodecContext *avctx) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); @@ -228,6 +273,8 @@ static int get_conf(AVCodecContext *avctx, oapve_cdesc_t *cdsc) cdsc->param[FRM_IDX].fps_den = avctx->time_base.num; } + cdsc->param[FRM_IDX].profile_idc = avctx->profile == AV_PROFILE_UNKNOWN ? + get_profile(avctx->pix_fmt) : avctx->profile; cdsc->param[FRM_IDX].preset = apv->preset_id; cdsc->param[FRM_IDX].qp = apv->qp; if (avctx->bit_rate / 1000 > INT_MAX || avctx->rc_max_rate / 1000 > INT_MAX) { @@ -275,6 +322,12 @@ static int get_conf(AVCodecContext *avctx, oapve_cdesc_t *cdsc) av_log(avctx, AV_LOG_WARNING, "Error parsing option '%s = %s'.\n", en->key, en->value); } + ret = validate_profile(avctx, cdsc->param[FRM_IDX].profile_idc); + if (ret < 0) + return ret; + + avctx->profile = cdsc->param[FRM_IDX].profile_idc; + return 0; } @@ -426,7 +479,7 @@ static av_cold int liboapve_close(AVCodecContext *avctx) { ApvEncContext *apv = avctx->priv_data; - for (int i = 0; i < apv->num_frames; i++) { + for (int i = 0; i < apv->ifrms.num_frms; i++) { if (apv->ifrms.frm[i].imgb != NULL) apv->ifrms.frm[i].imgb->release(apv->ifrms.frm[i].imgb); apv->ifrms.frm[i].imgb = NULL; -- 2.52.0 >From 9efa2942ba2c0374566ada8a42d27cfa2f71a162 Mon Sep 17 00:00:00 2001 From: Soham Kute <[email protected]> Date: Fri, 3 Apr 2026 00:31:16 +0530 Subject: [PATCH 2/2] avcodec/liboapvenc: expose APV profile names While fixing #22686, it became clear that FFmpeg does not expose APV profile names through the generic avctx.profile option handling or the APV codec descriptor. Register the APV profile names so -profile:v 422-10/444-10 and the other APV profile values are accepted by name, expose the APV profile table through the codec descriptor, and use those names in liboapv profile validation errors. This follow-up is not required for the implicit pix_fmt-driven fix itself, but it resolves the additional profile handling issue uncovered while validating it. --- libavcodec/codec_desc.c | 1 + libavcodec/liboapvenc.c | 9 +++++++-- libavcodec/profiles.h | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index b3f4e73e1d..a1fb0d41d4 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1991,6 +1991,7 @@ static const AVCodecDescriptor codec_descriptors[] = { .name = "apv", .long_name = NULL_IF_CONFIG_SMALL("Advanced Professional Video"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, + .profiles = NULL_IF_CONFIG_SMALL(ff_apv_profiles), }, { .id = AV_CODEC_ID_PRORES_RAW, diff --git a/libavcodec/liboapvenc.c b/libavcodec/liboapvenc.c index 3337513900..6a0033155a 100644 --- a/libavcodec/liboapvenc.c +++ b/libavcodec/liboapvenc.c @@ -163,11 +163,15 @@ static inline int get_profile(enum AVPixelFormat pix_fmt) static int validate_profile(AVCodecContext *avctx, int profile) { const int expected = get_profile(avctx->pix_fmt); + const char *profile_name = avcodec_profile_name(AV_CODEC_ID_APV, profile); + const char *expected_name = avcodec_profile_name(AV_CODEC_ID_APV, expected); if (profile != expected) { av_log(avctx, AV_LOG_ERROR, - "Profile %d is incompatible with pixel format %s; expected %d\n", - profile, av_get_pix_fmt_name(avctx->pix_fmt), expected); + "Profile %s (%d) is incompatible with pixel format %s; expected %s (%d)\n", + profile_name ? profile_name : "unknown", profile, + av_get_pix_fmt_name(avctx->pix_fmt), + expected_name ? expected_name : "unknown", expected); return AVERROR(EINVAL); } @@ -528,6 +532,7 @@ static const AVOption liboapv_options[] = { { "default", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = OAPV_PRESET_DEFAULT }, INT_MIN, INT_MAX, VE, .unit = "preset" }, { "qp", "Quantization parameter value for CQP rate control mode", OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 32 }, 0, 63, VE }, + FF_APV_PROFILE_OPTS { "oapv-params", "Override the apv configuration using a :-separated list of key=value parameters", OFFSET(oapv_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, { NULL } }; diff --git a/libavcodec/profiles.h b/libavcodec/profiles.h index 6f4011ff0c..eb2683bc99 100644 --- a/libavcodec/profiles.h +++ b/libavcodec/profiles.h @@ -58,6 +58,15 @@ FF_AVCTX_PROFILE_OPTION("high", NULL, VIDEO, AV_PROFILE_AV1_HIGH)\ FF_AVCTX_PROFILE_OPTION("professional", NULL, VIDEO, AV_PROFILE_AV1_PROFESSIONAL)\ +#define FF_APV_PROFILE_OPTS \ + FF_AVCTX_PROFILE_OPTION("422-10", NULL, VIDEO, AV_PROFILE_APV_422_10)\ + FF_AVCTX_PROFILE_OPTION("422-12", NULL, VIDEO, AV_PROFILE_APV_422_12)\ + FF_AVCTX_PROFILE_OPTION("444-10", NULL, VIDEO, AV_PROFILE_APV_444_10)\ + FF_AVCTX_PROFILE_OPTION("444-12", NULL, VIDEO, AV_PROFILE_APV_444_12)\ + FF_AVCTX_PROFILE_OPTION("4444-10", NULL, VIDEO, AV_PROFILE_APV_4444_10)\ + FF_AVCTX_PROFILE_OPTION("4444-12", NULL, VIDEO, AV_PROFILE_APV_4444_12)\ + FF_AVCTX_PROFILE_OPTION("400-10", NULL, VIDEO, AV_PROFILE_APV_400_10)\ + extern const AVProfile ff_aac_profiles[]; extern const AVProfile ff_dca_profiles[]; extern const AVProfile ff_eac3_profiles[]; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
