diff mbox series

[FFmpeg-devel,v12,8/9] avformat/mxfdec: Workaround for RGB pc/video level detection.

Message ID 20241021195721.892544-10-ms+git@mur.at
State New
Headers show
Series DNxUncompressed decoder | expand

Commit Message

martin schitter Oct. 21, 2024, 7:57 p.m. UTC
In case of RGB content wrapped in MXF containers we can not use
CDCIDescriptor fields for the video level detection.

The corresponding information in RGBA Descriptors uses a significant
differnt structure. As a workaround we pick the first found channel
depth info value of the RGBALayout array and us it instead of the
more general CDCI component_depth.
---
 libavformat/mxfdec.c         | 51 +++++++++++++++++++++++++++++-------
 tests/ref/fate/mxf-probe-j2k |  2 +-
 2 files changed, 42 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 27e8e0c..eb51585 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -212,6 +212,9 @@  typedef struct MXFDescriptor {
     unsigned int component_depth;
     unsigned int black_ref_level;
     unsigned int white_ref_level;
+    uint32_t component_max_ref;
+    uint32_t component_min_ref;
+    uint8_t red_component_depth;
     unsigned int color_range;
     unsigned int horiz_subsampling;
     unsigned int vert_subsampling;
@@ -1316,6 +1319,9 @@  static void mxf_read_pixel_layout(AVIOContext *pb, MXFDescriptor *descriptor)
         value = avio_r8(pb);
         av_log(NULL, AV_LOG_TRACE, "pixel layout: code %#x\n", code);
 
+        if (code == 'R')
+            descriptor->red_component_depth = value;
+
         if (ofs <= 14) {
             layout[ofs++] = code;
             layout[ofs++] = value;
@@ -1424,6 +1430,12 @@  static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int
     case 0x3401:
         mxf_read_pixel_layout(pb, descriptor);
         break;
+    case 0x3406:
+        descriptor->component_max_ref = avio_rb32(pb);
+        break;
+    case 0x3407:
+        descriptor->component_min_ref = avio_rb32(pb);
+        break;
     default:
         /* Private uid used by SONY C0023S01.mxf */
         if (IS_KLV_KEY(uid, mxf_sony_mpeg4_extradata)) {
@@ -2511,19 +2523,38 @@  static int mxf_add_metadata_stream(MXFContext *mxf, MXFTrack *track)
 
 static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *descriptor)
 {
-    if (descriptor->black_ref_level || descriptor->white_ref_level || descriptor->color_range) {
+    unsigned int depth, black_ref_level, white_ref_level;
+
+    // The red channel component depth value of the
+    // RGBALayout array is used as  component_depth indicator
+    // for the pc/tv level detection in case of RGB content
+    // and their RGBA Descriptors instead of CDCI entries.
+
+    if (descriptor->red_component_depth) { // RGBA Descriptor
+        depth = descriptor->red_component_depth;
+        black_ref_level = descriptor->component_min_ref;
+        white_ref_level = descriptor->component_max_ref;
+    } else { // CDCI Descriptor
+        depth = descriptor->component_depth;
+        black_ref_level = descriptor->black_ref_level;
+        white_ref_level = descriptor->white_ref_level;
+    }
+
+    if (black_ref_level || white_ref_level) {
         /* CDCI range metadata */
-        if (!descriptor->component_depth)
+        if (!depth)
             return AVCOL_RANGE_UNSPECIFIED;
-        if (descriptor->black_ref_level == 0 && descriptor->component_depth < 31 &&
-            descriptor->white_ref_level == ((1<<descriptor->component_depth) - 1) &&
-            (descriptor->color_range    == (1<<descriptor->component_depth) ||
-             descriptor->color_range    == ((1<<descriptor->component_depth) - 1)))
+        if (black_ref_level == 0 && depth < 31 &&
+            white_ref_level == ((1 << depth) - 1) &&
+            (descriptor->red_component_depth ||
+             descriptor->color_range    == (1 << descriptor->component_depth) ||
+             descriptor->color_range    == ((1 << descriptor->component_depth) - 1)))
             return AVCOL_RANGE_JPEG;
-        if (descriptor->component_depth >= 8 && descriptor->component_depth < 31 &&
-            descriptor->black_ref_level == (1  <<(descriptor->component_depth - 4)) &&
-            descriptor->white_ref_level == (235<<(descriptor->component_depth - 8)) &&
-            descriptor->color_range     == ((14<<(descriptor->component_depth - 4)) + 1))
+        if (depth >= 8 && depth < 31 &&
+            black_ref_level == (1  << (depth - 4)) &&
+            white_ref_level == (235 << (depth - 8)) &&
+            ( descriptor->red_component_depth ||
+            descriptor->color_range     == ((14 << (descriptor->component_depth - 4))) + 1))
             return AVCOL_RANGE_MPEG;
         avpriv_request_sample(mxf->fc, "Unrecognized CDCI color range (color diff range %d, b %d, w %d, depth %d)",
                               descriptor->color_range, descriptor->black_ref_level,
diff --git a/tests/ref/fate/mxf-probe-j2k b/tests/ref/fate/mxf-probe-j2k
index f1dadf4..6287980 100644
--- a/tests/ref/fate/mxf-probe-j2k
+++ b/tests/ref/fate/mxf-probe-j2k
@@ -16,7 +16,7 @@  sample_aspect_ratio=1:1
 display_aspect_ratio=16:9
 pix_fmt=rgb48
 level=-99
-color_range=unknown
+color_range=pc
 color_space=unknown
 color_transfer=bt709
 color_primaries=bt709