PR #25140 opened by Romain Beauxis (toots) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25140 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25140.patch
# Summary of changes FFmpeg's colour enums are a slot-for-slot copy of the H.273 / ISO/IEC 23091-2 code-point table, reserved slots included. `AVCOL_PRI_RESERVED0`, `AVCOL_TRC_RESERVED0` and `AVCOL_*_RESERVED` only exist to keep the numbering aligned: they have a name (`"reserved"`) but no meaning, and swscale rejects them with ENOTSUP. That origin causes two kinds of confusion in the parsers: - `!av_color_*_name()` is used as a validity check, but reserved slots are named, so they pass. - Formats with their own table cannot be copied as is. ProRes uses 0 for "unknown" in all three fields (RDD 36); MPEG-2 and MPEG-4 Part 2 forbid 0. Copied into the enum, a ProRes 0 becomes reserved for primaries and transfer, and RGB for the matrix. The latter is accepted by swscale, which then converts the YUV data with an identity matrix and silently produces wrong colours. The rule this series applies: once parsed, a colour tag is either a meaningful value or `AVCOL_*_UNSPECIFIED`. Every value mapped to unspecified here (reserved, forbidden, "unknown" or unassigned) carries no colour information in its own format, so nothing is lost. `h2645_vui.c` already does this since c80002aa81. Covered: - the ProRes frame header, including a 0 matrix - the mov `colr` and `vpcC` boxes - the MPEG-2 sequence display extension - the MPEG-4 Part 2 Visual Object colour description Fixes #25119 ## Tests The first commit adds one test per parser, with references showing the current output; each fix commit flips its own reference to `unknown`. The MPEG-4 Part 2 and `vpcC` tests need the two synthetic samples below: a one-frame mpeg4 stream with its Visual Object header patched to carry primaries 0, transfer 3 and matrix 3, and a one-frame VP9 mp4 with `vpcC` set to 3/3/3 and its `colr` box renamed to `free`. Matrix 0 in MPEG-2 and MPEG-4 Part 2, where it is forbidden, is left for a separate change. ```fate-samples mpeg4/reserved-color-tags.m4v mov/vpcc-reserved-color-tags.mp4 ``` >From 7bf1f5aedfbc7e84176b6326cbda15192d567305 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Fri, 16 Oct 2026 18:54:24 +0200 Subject: [PATCH 1/5] tests/fate: check colour tags with unknown or reserved values Some writers store 0 or another reserved value for the colour primaries and the transfer characteristics. The ProRes, MPEG-2 and MPEG-4 Part 2 decoders and the mov colr and vpcC parsers hand these over as they are, so the frames and streams carry AVCOL_PRI_RESERVED0, AVCOL_TRC_RESERVED0 or another reserved value and the swscale frame checks reject them. The references show that for now. The MPEG-4 Part 2 and vpcC tests use new synthetic samples: mpeg4/reserved-color-tags.m4v is one frame from the mpeg4 encoder with its Visual Object header patched to carry primaries 0, transfer 3 and matrix 3; mov/vpcc-reserved-color-tags.mp4 is one VP9 frame stream copied with all three tags set to 3, its colr box renamed to free so only vpcC is read. --- tests/fate/mov.mak | 12 ++++++++++++ tests/fate/mpeg4.mak | 9 ++++++++- tests/fate/mpegps.mak | 6 ++++++ tests/fate/prores.mak | 6 ++++++ tests/ref/fate/mov-colr-reserved-color-tags | 11 +++++++++++ tests/ref/fate/mov-vpcc-reserved-color-tags | 3 +++ tests/ref/fate/mpeg2-reserved-color-tags | 13 +++++++++++++ tests/ref/fate/mpeg4-reserved-color-tags | 3 +++ tests/ref/fate/prores-unknown-color-tags | 12 ++++++++++++ 9 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 tests/ref/fate/mov-colr-reserved-color-tags create mode 100644 tests/ref/fate/mov-vpcc-reserved-color-tags create mode 100644 tests/ref/fate/mpeg2-reserved-color-tags create mode 100644 tests/ref/fate/mpeg4-reserved-color-tags create mode 100644 tests/ref/fate/prores-unknown-color-tags diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index e36ddff7ed..5ada831626 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -47,6 +47,12 @@ FATE_MOV_FFPROBE-$(call DEMDEC, MOV, HEVC) += fate-mov-dovi-hvce-mp4-read FATE_MOV_FFPROBE-$(call DEMDEC, MOV, H264) += fate-mov-vfr-bframes-duration +# vpcC set to 3/3/3, with no colr box +FATE_MOV_FFPROBE-$(call DEMDEC, MOV, VP9) += fate-mov-vpcc-reserved-color-tags +fate-mov-vpcc-reserved-color-tags: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -v error \ + -show_entries stream=color_primaries,color_transfer,color_space -of default=nw=1 \ + $(TARGET_SAMPLES)/mov/vpcc-reserved-color-tags.mp4 + FATE_MOV_FFPROBE-$(CONFIG_MOV_DEMUXER) += fate-ffprobe-stream-entries-tmcd \ fate-ffprobe-group-stream-entries-tmcd \ fate-ffprobe-show-groups-tmcd @@ -318,6 +324,12 @@ FATE_MOV_FFMPEG_SAMPLES-$(call REMUX, MP4 MOV, AAC_PARSER) \ += fate-mov-mp4-edst-remainder fate-mov-mp4-edst-remainder: CMD = stream_remux mov $(TARGET_SAMPLES)/audiomatch/tones_fdkaac_44100_stereo_aac_lc.m4a "" mp4 "" "" "-c:a copy" +# A colr box can carry reserved colour values; they must not reach the stream +FATE_MOV_FFMPEG_FFPROBE_SAMPLES-$(call REMUX, MOV, QTRLE_DECODER) += fate-mov-colr-reserved-color-tags +fate-mov-colr-reserved-color-tags: CMD = stream_remux mov $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov "" mov \ + "-map 0:v -frames:v 1 -color_primaries 3 -color_trc 3 -colorspace 3" "" "" \ + "-select_streams v -show_entries stream=color_primaries,color_transfer,color_space -of default=nw=1" + # format-level branding: major_brand, minor_version, compatible_brands should be deleted on re-encode FATE_MOV_FFMPEG_FFPROBE_SAMPLES-$(call ENCDEC, AAC AAC, NUT MOV) += fate-mov-reenc-delete-format-metadata fate-mov-reenc-delete-format-metadata: CMD = transcode mov $(TARGET_SAMPLES)/cover_art/Owner-iTunes_9.0.3.15.m4a nut "-map 0:a:0 -c:a aac -bitexact -t 0.1" "-c copy -t 0.1" "-show_entries format_tags" "" "" "" null diff --git a/tests/fate/mpeg4.mak b/tests/fate/mpeg4.mak index c914f61731..d0c680bfc1 100644 --- a/tests/fate/mpeg4.mak +++ b/tests/fate/mpeg4.mak @@ -27,5 +27,12 @@ fate-m4v-cfr: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/ FATE_MPEG4-$(call FRAMECRC, MOV, H264, AAC_DECODER) += fate-mpeg4-fragmented-seek fate-mpeg4-fragmented-seek: CMD = framecrc -use_mfra_for pts -ss 1.04 -copyts -noaccurate_seek -i $(TARGET_SAMPLES)/mpeg4/fragmented.mp4 -frames:v 1 -an +# VO colour description with primaries 0 (forbidden), trc 3 and matrix 3 (reserved) +FATE_MPEG4_FFPROBE-$(call DEMDEC, M4V, MPEG4) += fate-mpeg4-reserved-color-tags +fate-mpeg4-reserved-color-tags: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -v error \ + -show_entries frame=color_primaries,color_transfer,color_space -of default=nw=1 \ + $(TARGET_SAMPLES)/mpeg4/reserved-color-tags.m4v + FATE_SAMPLES_AVCONV += $(FATE_MPEG4-yes) -fate-mpeg4: $(FATE_MPEG4-yes) +FATE_SAMPLES_FFPROBE += $(FATE_MPEG4_FFPROBE-yes) +fate-mpeg4: $(FATE_MPEG4-yes) $(FATE_MPEG4_FFPROBE-yes) diff --git a/tests/fate/mpegps.mak b/tests/fate/mpegps.mak index a6114b1a8a..ec8880f5c9 100644 --- a/tests/fate/mpegps.mak +++ b/tests/fate/mpegps.mak @@ -5,3 +5,9 @@ fate-mpegps-remuxed-pcm-demux: CMD = stream_remux "mpeg" "$(TARGET_SAMPLES)/mpeg FATE_SAMPLES_FFMPEG += $(FATE_MPEGPS-yes) fate-mpegps: $(FATE_MPEGPS-yes) + +# A sequence display extension can carry reserved colour values; they must not reach the frame +FATE_SAMPLES_FFMPEG_FFPROBE-$(call ALLYES, MPEGVIDEO_DEMUXER MPEG2VIDEO_MUXER MPEG2_METADATA_BSF MPEG2VIDEO_DECODER) += fate-mpeg2-reserved-color-tags +fate-mpeg2-reserved-color-tags: CMD = stream_remux mpegvideo $(TARGET_SAMPLES)/mpeg2/tcela-6.bits "" mpeg2video \ + "-map 0:v:0 -frames:v 3 -bsf:v mpeg2_metadata=colour_primaries=3:transfer_characteristics=3" "" "" \ + "-select_streams v -read_intervals %+\#1 -show_entries frame=color_primaries,color_transfer,color_space -of default=nw=1" diff --git a/tests/fate/prores.mak b/tests/fate/prores.mak index e3759dfb50..6e0a9d526b 100644 --- a/tests/fate/prores.mak +++ b/tests/fate/prores.mak @@ -28,4 +28,10 @@ fate-prores-metadata: CMD = md5 -i $(TARGET_SAMPLES)/prores/Sequence_1-Apple_Pro FATE_SAMPLES_FFMPEG_FFPROBE-$(call FRAMECRC, MOV, PRORES,) += fate-prores-probe fate-prores-probe: CMD = stream_demux mov $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_HQ.mov "" "-c:v copy" "-show_frames" +# A frame header can carry 0 for "unknown"; it must not reach the frame as reserved or RGB +FATE_SAMPLES_FFMPEG_FFPROBE-$(call ALLYES, MOV_DEMUXER MOV_MUXER PRORES_METADATA_BSF PRORES_DECODER) += fate-prores-unknown-color-tags +fate-prores-unknown-color-tags: CMD = stream_remux mov $(TARGET_SAMPLES)/prores/Sequence_1-Apple_ProRes_422_Proxy.mov "" mov \ + "-map 0:v -bsf:v prores_metadata=color_primaries=0:color_trc=0:colorspace=0" "" "" \ + "-select_streams v -read_intervals %+\#1 -show_entries frame=color_primaries,color_transfer,color_space -of default=nw=1" + FATE_SAMPLES_FFMPEG-$(call DEMMUX, MOV, MOV, PRORES_METADATA_BSF) += $(FATE_PRORES_METADATA_BSF) diff --git a/tests/ref/fate/mov-colr-reserved-color-tags b/tests/ref/fate/mov-colr-reserved-color-tags new file mode 100644 index 0000000000..1163cebd3c --- /dev/null +++ b/tests/ref/fate/mov-colr-reserved-color-tags @@ -0,0 +1,11 @@ +c6b96e10140cb9554d1eb6a5dccc1c1b *tests/data/fate/mov-colr-reserved-color-tags.mov +7552 tests/data/fate/mov-colr-reserved-color-tags.mov +#tb 0: 1/10 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 160x120 +#sar 0: 0/1 +0, 0, 0, 1, 57600, 0x3718ad00 +color_space=reserved +color_transfer=reserved +color_primaries=reserved diff --git a/tests/ref/fate/mov-vpcc-reserved-color-tags b/tests/ref/fate/mov-vpcc-reserved-color-tags new file mode 100644 index 0000000000..b9422ea102 --- /dev/null +++ b/tests/ref/fate/mov-vpcc-reserved-color-tags @@ -0,0 +1,3 @@ +color_space=reserved +color_transfer=reserved +color_primaries=reserved diff --git a/tests/ref/fate/mpeg2-reserved-color-tags b/tests/ref/fate/mpeg2-reserved-color-tags new file mode 100644 index 0000000000..838f79528b --- /dev/null +++ b/tests/ref/fate/mpeg2-reserved-color-tags @@ -0,0 +1,13 @@ +90733b51c7218c64e7dc8ce80349142a *tests/data/fate/mpeg2-reserved-color-tags.mpeg2video +268865 tests/data/fate/mpeg2-reserved-color-tags.mpeg2video +#tb 0: 1/30 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 720x480 +#sar 0: 8/9 +0, 0, 0, 1, 518400, 0xaccb5f9e +0, 1, 1, 1, 518400, 0xf3177385 +0, 2, 2, 1, 518400, 0xee9adfdf +color_space=unknown +color_primaries=reserved +color_transfer=reserved diff --git a/tests/ref/fate/mpeg4-reserved-color-tags b/tests/ref/fate/mpeg4-reserved-color-tags new file mode 100644 index 0000000000..55c9df3bad --- /dev/null +++ b/tests/ref/fate/mpeg4-reserved-color-tags @@ -0,0 +1,3 @@ +color_space=reserved +color_primaries=reserved +color_transfer=reserved diff --git a/tests/ref/fate/prores-unknown-color-tags b/tests/ref/fate/prores-unknown-color-tags new file mode 100644 index 0000000000..01b819917e --- /dev/null +++ b/tests/ref/fate/prores-unknown-color-tags @@ -0,0 +1,12 @@ +c496c29c4d3d52445f70e8973885ffcd *tests/data/fate/prores-unknown-color-tags.mov +115285 tests/data/fate/prores-unknown-color-tags.mov +#tb 0: 100/2997 +#media_type 0: video +#codec_id 0: rawvideo +#dimensions 0: 1920x1080 +#sar 0: 0/1 +0, 0, 0, 1, 8294400, 0x007ba770 +0, 1, 1, 1, 8294400, 0x007ba770 +color_space=gbr +color_primaries=reserved +color_transfer=reserved -- 2.54.0 >From 9bce9e1fb6e5039d189929b2a59e1c829fd84953 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Fri, 16 Oct 2026 18:54:50 +0200 Subject: [PATCH 2/5] avcodec/proresdec, avformat/mov: report reserved colour tags as unspecified The ProRes frame header and the mov colr atom are copied into the codec context as they are. ProRes uses 0 for "unknown" in all three fields (RDD 36), and some writers store values that have no name, so decoded frames carry AVCOL_PRI_RESERVED0, AVCOL_TRC_RESERVED0, AVCOL_SPC_RGB or an out of range value. The swscale frame checks reject the reserved ones, so scaling such a file fails with ENOTSUP. The RGB matrix is accepted, and the YUV data is then converted with the wrong coefficients. Report reserved and unnamed values as unspecified, and a 0 ProRes matrix too. h2645_vui.c does the same for reserved values in H.264 and HEVC since c80002aa81 ("avcodec/h2645_vui: Ensure color primaries/trc/space isn't reserved value"). Valid values are untouched. ffprobe now prints unknown for these fields instead of reserved or gbr. Fixes: #25119 --- libavcodec/proresdec.c | 11 ++++++++--- libavformat/mov.c | 12 +++++++++--- tests/ref/fate/mov-colr-reserved-color-tags | 6 +++--- tests/ref/fate/prores-unknown-color-tags | 6 +++--- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/libavcodec/proresdec.c b/libavcodec/proresdec.c index cfcc866885..9d92831d2e 100644 --- a/libavcodec/proresdec.c +++ b/libavcodec/proresdec.c @@ -31,6 +31,7 @@ #include "libavutil/internal.h" #include "libavutil/mem.h" #include "libavutil/mem_internal.h" +#include "libavutil/pixdesc.h" #include "avcodec.h" #include "codec_internal.h" @@ -280,9 +281,13 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, #endif } - avctx->color_primaries = buf[14]; - avctx->color_trc = buf[15]; - avctx->colorspace = buf[16]; + // 0 means unknown in all three fields (RDD 36), unlike in H.273 + avctx->color_primaries = buf[14] && buf[14] != AVCOL_PRI_RESERVED && + av_color_primaries_name(buf[14]) ? buf[14] : AVCOL_PRI_UNSPECIFIED; + avctx->color_trc = buf[15] && buf[15] != AVCOL_TRC_RESERVED && + av_color_transfer_name(buf[15]) ? buf[15] : AVCOL_TRC_UNSPECIFIED; + avctx->colorspace = buf[16] && buf[16] != AVCOL_SPC_RESERVED && + av_color_space_name(buf[16]) ? buf[16] : AVCOL_SPC_UNSPECIFIED; avctx->color_range = AVCOL_RANGE_MPEG; ptr = buf + 20; diff --git a/libavformat/mov.c b/libavformat/mov.c index f7c12922d9..9d3f8df7c1 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2282,11 +2282,17 @@ static int mov_read_colr(MOVContext *c, AVIOContext *pb, MOVAtom atom) st->codecpar->color_range = AVCOL_RANGE_MPEG; } - if (!av_color_primaries_name(color_primaries)) + // Reserved and unassigned values carry no colour information + if (color_primaries == AVCOL_PRI_RESERVED0 || + color_primaries == AVCOL_PRI_RESERVED || + !av_color_primaries_name(color_primaries)) color_primaries = AVCOL_PRI_UNSPECIFIED; - if (!av_color_transfer_name(color_trc)) + if (color_trc == AVCOL_TRC_RESERVED0 || + color_trc == AVCOL_TRC_RESERVED || + !av_color_transfer_name(color_trc)) color_trc = AVCOL_TRC_UNSPECIFIED; - if (!av_color_space_name(color_matrix)) + if (color_matrix == AVCOL_SPC_RESERVED || + !av_color_space_name(color_matrix)) color_matrix = AVCOL_SPC_UNSPECIFIED; st->codecpar->color_primaries = color_primaries; diff --git a/tests/ref/fate/mov-colr-reserved-color-tags b/tests/ref/fate/mov-colr-reserved-color-tags index 1163cebd3c..1fbd4be8ec 100644 --- a/tests/ref/fate/mov-colr-reserved-color-tags +++ b/tests/ref/fate/mov-colr-reserved-color-tags @@ -6,6 +6,6 @@ c6b96e10140cb9554d1eb6a5dccc1c1b *tests/data/fate/mov-colr-reserved-color-tags.m #dimensions 0: 160x120 #sar 0: 0/1 0, 0, 0, 1, 57600, 0x3718ad00 -color_space=reserved -color_transfer=reserved -color_primaries=reserved +color_space=unknown +color_transfer=unknown +color_primaries=unknown diff --git a/tests/ref/fate/prores-unknown-color-tags b/tests/ref/fate/prores-unknown-color-tags index 01b819917e..b63888f8ed 100644 --- a/tests/ref/fate/prores-unknown-color-tags +++ b/tests/ref/fate/prores-unknown-color-tags @@ -7,6 +7,6 @@ c496c29c4d3d52445f70e8973885ffcd *tests/data/fate/prores-unknown-color-tags.mov #sar 0: 0/1 0, 0, 0, 1, 8294400, 0x007ba770 0, 1, 1, 1, 8294400, 0x007ba770 -color_space=gbr -color_primaries=reserved -color_transfer=reserved +color_space=unknown +color_primaries=unknown +color_transfer=unknown -- 2.54.0 >From a19e0a64f84d55dfd73df44a61160725e12d31ff Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Fri, 16 Oct 2026 19:01:08 +0200 Subject: [PATCH 3/5] avcodec/mpeg12dec: report reserved colour tags as unspecified The sequence display extension colour description is copied into the codec context as it is, so a reserved value reaches the decoded frames. The swscale frame checks reject reserved values, so scaling such a stream fails with ENOTSUP. h2645_vui.c reports them as unspecified since c80002aa81 ("avcodec/h2645_vui: Ensure color primaries/trc/space isn't reserved value"), do the same here. Valid values are untouched. ffprobe now prints unknown for these fields instead of reserved. --- libavcodec/mpeg12dec.c | 14 ++++++++++++++ tests/ref/fate/mpeg2-reserved-color-tags | 4 ++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index e30fa843cc..f1ced4fb56 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -35,6 +35,7 @@ #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/mem_internal.h" +#include "libavutil/pixdesc.h" #include "libavutil/reverse.h" #include "libavutil/stereo3d.h" #include "libavutil/timecode.h" @@ -1081,6 +1082,19 @@ static void mpeg_decode_sequence_display_extension(Mpeg1Context *const s1, s->avctx->color_primaries = get_bits(gb, 8); s->avctx->color_trc = get_bits(gb, 8); s->avctx->colorspace = get_bits(gb, 8); + + // Reserved and unassigned values carry no colour information + if (s->avctx->color_primaries == AVCOL_PRI_RESERVED0 || + s->avctx->color_primaries == AVCOL_PRI_RESERVED || + !av_color_primaries_name(s->avctx->color_primaries)) + s->avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + if (s->avctx->color_trc == AVCOL_TRC_RESERVED0 || + s->avctx->color_trc == AVCOL_TRC_RESERVED || + !av_color_transfer_name(s->avctx->color_trc)) + s->avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + if (s->avctx->colorspace == AVCOL_SPC_RESERVED || + !av_color_space_name(s->avctx->colorspace)) + s->avctx->colorspace = AVCOL_SPC_UNSPECIFIED; } w = get_bits(gb, 14); skip_bits(gb, 1); // marker diff --git a/tests/ref/fate/mpeg2-reserved-color-tags b/tests/ref/fate/mpeg2-reserved-color-tags index 838f79528b..f65ce919b7 100644 --- a/tests/ref/fate/mpeg2-reserved-color-tags +++ b/tests/ref/fate/mpeg2-reserved-color-tags @@ -9,5 +9,5 @@ 0, 1, 1, 1, 518400, 0xf3177385 0, 2, 2, 1, 518400, 0xee9adfdf color_space=unknown -color_primaries=reserved -color_transfer=reserved +color_primaries=unknown +color_transfer=unknown -- 2.54.0 >From b970c1996dcd9bbe41366d9854518646950756c5 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Fri, 16 Oct 2026 19:01:08 +0200 Subject: [PATCH 4/5] avcodec/mpeg4videodec: report reserved colour tags as unspecified The VOL colour description is copied into the codec context as it is, so a reserved value reaches the decoded frames. The swscale frame checks reject reserved values, so scaling such a stream fails with ENOTSUP. h2645_vui.c reports them as unspecified since c80002aa81 ("avcodec/h2645_vui: Ensure color primaries/trc/space isn't reserved value"), do the same here. Valid values are untouched. --- libavcodec/mpeg4videodec.c | 14 ++++++++++++++ tests/ref/fate/mpeg4-reserved-color-tags | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index e080c83f9d..03b145379d 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -26,6 +26,7 @@ #include "libavutil/avassert.h" #include "libavutil/internal.h" +#include "libavutil/pixdesc.h" #include "libavutil/opt.h" #include "libavutil/thread.h" #include "codec_internal.h" @@ -2462,6 +2463,19 @@ static int mpeg4_decode_visual_object(MpegEncContext *s, GetBitContext *gb) s->avctx->color_primaries = get_bits(gb, 8); s->avctx->color_trc = get_bits(gb, 8); s->avctx->colorspace = get_bits(gb, 8); + + // Reserved and unassigned values carry no colour information + if (s->avctx->color_primaries == AVCOL_PRI_RESERVED0 || + s->avctx->color_primaries == AVCOL_PRI_RESERVED || + !av_color_primaries_name(s->avctx->color_primaries)) + s->avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; + if (s->avctx->color_trc == AVCOL_TRC_RESERVED0 || + s->avctx->color_trc == AVCOL_TRC_RESERVED || + !av_color_transfer_name(s->avctx->color_trc)) + s->avctx->color_trc = AVCOL_TRC_UNSPECIFIED; + if (s->avctx->colorspace == AVCOL_SPC_RESERVED || + !av_color_space_name(s->avctx->colorspace)) + s->avctx->colorspace = AVCOL_SPC_UNSPECIFIED; } } } diff --git a/tests/ref/fate/mpeg4-reserved-color-tags b/tests/ref/fate/mpeg4-reserved-color-tags index 55c9df3bad..b86330d693 100644 --- a/tests/ref/fate/mpeg4-reserved-color-tags +++ b/tests/ref/fate/mpeg4-reserved-color-tags @@ -1,3 +1,3 @@ -color_space=reserved -color_primaries=reserved -color_transfer=reserved +color_space=unknown +color_primaries=unknown +color_transfer=unknown -- 2.54.0 >From 53439cdfe22f60b9028848707c17a90be24448d1 Mon Sep 17 00:00:00 2001 From: Romain Beauxis <[email protected]> Date: Fri, 16 Oct 2026 19:01:08 +0200 Subject: [PATCH 5/5] avformat/mov: report reserved vpcC colour tags as unspecified The vpcC colour primaries, transfer characteristics and matrix were only checked for having a name, and 0 and 3 have one ("reserved"). The swscale frame checks reject reserved values, so scaling such a stream fails with ENOTSUP. h2645_vui.c reports them as unspecified since c80002aa81 ("avcodec/h2645_vui: Ensure color primaries/trc/space isn't reserved value"), do the same here. Valid values are untouched. --- libavformat/mov.c | 12 +++++++++--- tests/ref/fate/mov-vpcc-reserved-color-tags | 6 +++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 9d3f8df7c1..9682b7a4f7 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6907,11 +6907,17 @@ static int mov_read_vpcc(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (avio_rb16(pb)) /* codecIntializationDataSize */ return AVERROR_INVALIDDATA; - if (!av_color_primaries_name(color_primaries)) + // Reserved and unassigned values carry no colour information + if (color_primaries == AVCOL_PRI_RESERVED0 || + color_primaries == AVCOL_PRI_RESERVED || + !av_color_primaries_name(color_primaries)) color_primaries = AVCOL_PRI_UNSPECIFIED; - if (!av_color_transfer_name(color_trc)) + if (color_trc == AVCOL_TRC_RESERVED0 || + color_trc == AVCOL_TRC_RESERVED || + !av_color_transfer_name(color_trc)) color_trc = AVCOL_TRC_UNSPECIFIED; - if (!av_color_space_name(color_space)) + if (color_space == AVCOL_SPC_RESERVED || + !av_color_space_name(color_space)) color_space = AVCOL_SPC_UNSPECIFIED; st->codecpar->color_range = (color_range & 1) ? AVCOL_RANGE_JPEG : AVCOL_RANGE_MPEG; diff --git a/tests/ref/fate/mov-vpcc-reserved-color-tags b/tests/ref/fate/mov-vpcc-reserved-color-tags index b9422ea102..8e06c4bec5 100644 --- a/tests/ref/fate/mov-vpcc-reserved-color-tags +++ b/tests/ref/fate/mov-vpcc-reserved-color-tags @@ -1,3 +1,3 @@ -color_space=reserved -color_transfer=reserved -color_primaries=reserved +color_space=unknown +color_transfer=unknown +color_primaries=unknown -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
