Commit 3c339b39ab for ffmpeg
commit 3c339b39ab33fb57c79d52be15bfc07b30e10da6
Author: Kacper Michajłow <kasper93@gmail.com>
Date: Wed Sep 9 07:13:15 2026 +0200
avcodec/{dvenc,mpeg12enc,mpeg4videoenc}: declare the required chroma locations
DV is always top-left sited, dvenc already rejected anything else under
strict compliance but had no way to ask for a conversion. MPEG-2 has no
syntax element for the location either, it follows chroma_format, so
mpeg2video reports the value for the pixel format in use. When the format
is not decided yet it reports left, which fits 4:2:2 too, as that has no
vertical subsampling. MPEG-1 is center sited.
MPEG-4 Part 2 is left sited, which mpeg4videodec has asserted unconditionally
since 580a7465fb, the commit that gave H.263 center and MPEG-4 left in the
same hunk. Its encoder declared nothing, so what it wrote and what the decoder
reads back disagreed. Declaring it cannot be more wrong than the decoder
already is, it only makes the two agree.
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c
index f25c3ddfee..b612ec5a1b 100644
--- a/libavcodec/dvenc.c
+++ b/libavcodec/dvenc.c
@@ -1255,6 +1255,7 @@ const FFCodec ff_dvvideo_encoder = {
.init = dvvideo_encode_init,
FF_CODEC_ENCODE_CB(dvvideo_encode_frame),
CODEC_PIXFMTS(AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P),
+ CODEC_CHROMA_LOCS(AVCHROMA_LOC_TOPLEFT),
.color_ranges = AVCOL_RANGE_MPEG,
.p.priv_class = &dvvideo_encode_class,
};
diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index 7537327149..ab2df9d1f9 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -1314,6 +1314,7 @@ const FFCodec ff_mpeg1video_encoder = {
.close = ff_mpv_encode_end,
CODEC_FRAMERATES_ARRAY(ff_mpeg12_frame_rate_tab + 1),
CODEC_PIXFMTS(AV_PIX_FMT_YUV420P),
+ CODEC_CHROMA_LOCS(AVCHROMA_LOC_CENTER),
.color_ranges = AVCOL_RANGE_MPEG,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
AV_CODEC_CAP_SLICE_THREADS |
@@ -1322,6 +1323,27 @@ const FFCodec ff_mpeg1video_encoder = {
.p.priv_class = &mpeg1_class,
};
+static int mpeg2_get_supported_config(const AVCodecContext *avctx,
+ const AVCodec *codec,
+ enum AVCodecConfig config,
+ unsigned flags, const void **out,
+ int *out_num)
+{
+ if (config == AV_CODEC_CONFIG_CHROMA_LOCATION) {
+ static const enum AVChromaLocation left[] = { AVCHROMA_LOC_LEFT, AVCHROMA_LOC_UNSPECIFIED };
+ static const enum AVChromaLocation topleft[] = { AVCHROMA_LOC_TOPLEFT, AVCHROMA_LOC_UNSPECIFIED };
+ enum AVPixelFormat pix_fmt = avctx ? avctx->pix_fmt : AV_PIX_FMT_NONE;
+
+ /* 4:2:2 has no vertical subsampling, so the left siting of 4:2:0
+ * fits it too when the pixel format is not decided yet. */
+ *out = pix_fmt == AV_PIX_FMT_YUV422P ? topleft : left;
+ *out_num = 1;
+ return 0;
+ }
+
+ return ff_default_get_supported_config(avctx, codec, config, flags, out, out_num);
+}
+
const FFCodec ff_mpeg2video_encoder = {
.p.name = "mpeg2video",
CODEC_LONG_NAME("MPEG-2 video"),
@@ -1333,6 +1355,7 @@ const FFCodec ff_mpeg2video_encoder = {
.close = ff_mpv_encode_end,
CODEC_FRAMERATES_ARRAY(ff_mpeg2_frame_rate_tab),
CODEC_PIXFMTS(AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P),
+ .get_supported_config = mpeg2_get_supported_config,
.color_ranges = AVCOL_RANGE_MPEG,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
AV_CODEC_CAP_SLICE_THREADS |
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index a610c36856..2d1cc3ad09 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -1363,6 +1363,7 @@ const FFCodec ff_mpeg4_encoder = {
FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
.close = ff_mpv_encode_end,
CODEC_PIXFMTS(AV_PIX_FMT_YUV420P),
+ CODEC_CHROMA_LOCS(AVCHROMA_LOC_LEFT),
.color_ranges = AVCOL_RANGE_MPEG,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
AV_CODEC_CAP_SLICE_THREADS |