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]

Reply via email to