[FFmpeg-devel] [PATCH 1/2] [avformat/mxf] Add core colorimetry support to MXF.

Steven Robertson steven at strobe.cc
Sat Sep 24 08:19:03 EEST 2016


Signed-off-by: Steven Robertson <steven at strobe.cc>
---
 libavformat/mxf.c    | 33 +++++++++++++++++++++++++++++++++
 libavformat/mxf.h    |  3 +++
 libavformat/mxfdec.c | 29 +++++++++++++++++++++++++++++
 libavformat/mxfenc.c | 36 +++++++++++++++++++++++++++++++-----
 4 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/libavformat/mxf.c b/libavformat/mxf.c
index e9c48e8..ea7c1db 100644
--- a/libavformat/mxf.c
+++ b/libavformat/mxf.c
@@ -84,6 +84,39 @@ const MXFCodecUL ff_mxf_codec_tag_uls[] = {
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,                         0 },
 };
 
+const MXFCodecUL ff_mxf_transfer_characteristics_uls[] = {
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x01,0x00,0x00 }, 14, AVCOL_TRC_GAMMA22 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x02,0x00,0x00 }, 14, AVCOL_TRC_BT709 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x03,0x00,0x00 }, 14, AVCOL_TRC_SMPTE240M },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x04,0x00,0x00 }, 14, AVCOL_TRC_BT709 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x05,0x00,0x00 }, 14, AVCOL_TRC_BT1361_ECG },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x01,0x06,0x00,0x00 }, 14, AVCOL_TRC_LINEAR },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x08,0x04,0x01,0x01,0x01,0x01,0x07,0x00,0x00 }, 14, AVCOL_TRC_SMPTEST428_1 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x08,0x00,0x00 }, 14, AVCOL_TRC_IEC61966_2_4 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0E,0x04,0x01,0x01,0x01,0x01,0x09,0x00,0x00 }, 14, AVCOL_TRC_BT2020_10 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x0A,0x00,0x00 }, 14, AVCOL_TRC_SMPTEST2084 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x01,0x0B,0x00,0x00 }, 14, AVCOL_TRC_ARIB_STD_B67 },
+    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0, AVCOL_TRC_RESERVED0 },
+};
+
+const MXFCodecUL ff_mxf_coding_equations_uls[] = {
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x02,0x01,0x00,0x00 }, 14, AVCOL_SPC_BT470BG },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x02,0x02,0x00,0x00 }, 14, AVCOL_SPC_BT709 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x02,0x03,0x00,0x00 }, 14, AVCOL_SPC_SMPTE240M },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x02,0x04,0x00,0x00 }, 14, AVCOL_SPC_YCOCG },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x02,0x05,0x00,0x00 }, 14, AVCOL_SPC_RGB },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x02,0x06,0x00,0x00 }, 14, AVCOL_SPC_BT2020_NCL },
+    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0, AVCOL_SPC_UNSPECIFIED },
+};
+
+const MXFCodecUL ff_mxf_color_primaries_uls[] = {
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x03,0x01,0x00,0x00 }, 14, AVCOL_PRI_SMPTE170M },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x03,0x02,0x00,0x00 }, 14, AVCOL_PRI_BT470M },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x06,0x04,0x01,0x01,0x01,0x03,0x03,0x00,0x00 }, 14, AVCOL_PRI_BT709 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0D,0x04,0x01,0x01,0x01,0x03,0x04,0x00,0x00 }, 14, AVCOL_PRI_BT2020 },
+    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0, AVCOL_PRI_RESERVED0 },
+};
+
 static const struct {
     enum AVPixelFormat pix_fmt;
     const char data[16];
diff --git a/libavformat/mxf.h b/libavformat/mxf.h
index f3db1f9..1c9ca2a 100644
--- a/libavformat/mxf.h
+++ b/libavformat/mxf.h
@@ -79,6 +79,9 @@ extern const MXFCodecUL ff_mxf_data_definition_uls[];
 extern const MXFCodecUL ff_mxf_codec_uls[];
 extern const MXFCodecUL ff_mxf_pixel_format_uls[];
 extern const MXFCodecUL ff_mxf_codec_tag_uls[];
+extern const MXFCodecUL ff_mxf_transfer_characteristics_uls[];
+extern const MXFCodecUL ff_mxf_coding_equations_uls[];
+extern const MXFCodecUL ff_mxf_color_primaries_uls[];
 
 int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *pix_fmt);
 const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, AVRational time_base);
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 1939761..d012e41 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -188,6 +188,9 @@ typedef struct MXFDescriptor {
     uint8_t *extradata;
     int extradata_size;
     enum AVPixelFormat pix_fmt;
+    UID color_trc_ul;
+    UID color_primaries_ul;
+    UID color_space_ul;
 } MXFDescriptor;
 
 typedef struct MXFIndexTableSegment {
@@ -1000,9 +1003,18 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int
         descriptor->aspect_ratio.num = avio_rb32(pb);
         descriptor->aspect_ratio.den = avio_rb32(pb);
         break;
+    case 0x3210:
+        avio_read(pb, descriptor->color_trc_ul, 16);
+        break;
     case 0x3212:
         descriptor->field_dominance = avio_r8(pb);
         break;
+    case 0x3219:
+        avio_read(pb, descriptor->color_primaries_ul, 16);
+        break;
+    case 0x321A:
+        avio_read(pb, descriptor->color_space_ul, 16);
+        break;
     case 0x3301:
         descriptor->component_depth = avio_rb32(pb);
         break;
@@ -1853,6 +1865,9 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
         const MXFCodecUL *codec_ul = NULL;
         const MXFCodecUL *container_ul = NULL;
         const MXFCodecUL *pix_fmt_ul = NULL;
+        const MXFCodecUL *color_trc_ul = NULL;
+        const MXFCodecUL *color_primaries_ul = NULL;
+        const MXFCodecUL *color_space_ul = NULL;
         AVStream *st;
         AVTimecode tc;
         int flags;
@@ -2085,6 +2100,20 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
                     }
                 }
             }
+
+            color_primaries_ul = mxf_get_codec_ul(ff_mxf_color_primaries_uls,
+                                                  &descriptor->color_primaries_ul);
+            if (color_primaries_ul->uid[0])
+              st->codecpar->color_primaries = color_primaries_ul->id;
+            color_space_ul = mxf_get_codec_ul(ff_mxf_coding_equations_uls,
+                                              &descriptor->color_space_ul);
+            if (color_space_ul->uid[0])
+              st->codecpar->color_space = color_space_ul->id;
+            color_trc_ul = mxf_get_codec_ul(ff_mxf_transfer_characteristics_uls,
+                                            &descriptor->color_trc_ul);
+            if (color_trc_ul->uid[0])
+              st->codecpar->color_trc = color_trc_ul->id;
+
             st->need_parsing = AVSTREAM_PARSE_HEADERS;
             if (material_track->sequence->origin) {
                 av_dict_set_int(&st->metadata, "material_track_origin", material_track->sequence->origin, 0);
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index 7733ef8..eb77f3a 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -415,9 +415,12 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = {
     { 0x3202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x02,0x01,0x00,0x00,0x00}}, /* Stored Height */
     { 0x3209, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0C,0x00,0x00,0x00}}, /* Display Width */
     { 0x3208, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0B,0x00,0x00,0x00}}, /* Display Height */
+    { 0x3210, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x02,0x01,0x01,0x01,0x02,0x00}}, /* Transfer Characteristic */
     { 0x320B, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0E,0x00,0x00,0x00}}, /* Presentation Y offset */
     { 0x320E, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x00,0x00,0x00}}, /* Aspect Ratio */
     { 0x3201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x06,0x01,0x00,0x00,0x00,0x00}}, /* Picture Essence Coding */
+    { 0x321A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x02,0x01,0x01,0x03,0x01,0x00}}, /* Coding Equations */
+    { 0x3219, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x04,0x01,0x02,0x01,0x01,0x06,0x01,0x00}}, /* Color Primaries */
     { 0x3212, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x01,0x06,0x00,0x00,0x00}}, /* Field Dominance (Opt) */
     { 0x3215, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x05,0x01,0x13,0x00,0x00,0x00,0x00}}, /* Signal Standard */
     // CDCI Picture Essence Descriptor
@@ -576,11 +579,10 @@ static void mxf_free(AVFormatContext *s)
     }
 }
 
-static const MXFCodecUL *mxf_get_data_definition_ul(int type)
+static const MXFCodecUL *mxf_get_ul_by_id(const MXFCodecUL *uls, int id)
 {
-    const MXFCodecUL *uls = ff_mxf_data_definition_uls;
     while (uls->uid[0]) {
-        if (type == uls->id)
+        if (id == uls->id)
             break;
         uls++;
     }
@@ -835,7 +837,7 @@ static void mxf_write_common_fields(AVFormatContext *s, AVStream *st)
     if (st == mxf->timecode_track)
         avio_write(pb, smpte_12m_timecode_track_data_ul, 16);
     else {
-        const MXFCodecUL *data_def_ul = mxf_get_data_definition_ul(st->codecpar->codec_type);
+        const MXFCodecUL *data_def_ul = mxf_get_ul_by_id(ff_mxf_data_definition_uls, st->codecpar->codec_type);
         avio_write(pb, data_def_ul->uid, 16);
     }
 
@@ -1011,6 +1013,9 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
 {
     MXFStreamContext *sc = st->priv_data;
     AVIOContext *pb = s->pb;
+    const MXFCodecUL* color_trc_ul;
+    const MXFCodecUL* color_primaries_ul;
+    const MXFCodecUL* color_space_ul;
     int stored_height = (st->codecpar->height+15)/16*16;
     int display_height;
     int f1, f2;
@@ -1020,6 +1025,16 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
     if (sc->signal_standard)
         desc_size += 5;
 
+    color_trc_ul = mxf_get_ul_by_id(ff_mxf_transfer_characteristics_uls, st->codecpar->color_trc);
+    if (color_trc_ul->uid[0])
+      desc_size += 20;
+    color_primaries_ul = mxf_get_ul_by_id(ff_mxf_color_primaries_uls, st->codecpar->color_primaries);
+    if (color_primaries_ul->uid[0])
+      desc_size += 20;
+    color_space_ul = mxf_get_ul_by_id(ff_mxf_coding_equations_uls, st->codecpar->color_space);
+    if (color_space_ul->uid[0])
+      desc_size += 20;
+
     mxf_write_generic_desc(s, st, key, desc_size);
 
     mxf_write_local_tag(pb, 4, 0x3203);
@@ -1082,7 +1097,6 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
         f1 *= 2;
     }
 
-
     mxf_write_local_tag(pb, 16, 0x320D);
     avio_wb32(pb, 2);
     avio_wb32(pb, 4);
@@ -1101,6 +1115,18 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
         avio_w8(pb, sc->field_dominance);
     }
 
+    if (color_trc_ul->uid[0]) {
+      mxf_write_local_tag(pb, 16, 0x3210);
+      avio_write(pb, color_trc_ul->uid, 16);
+    }
+    if (color_primaries_ul->uid[0]) {
+      mxf_write_local_tag(pb, 16, 0x3219);
+      avio_write(pb, color_primaries_ul->uid, 16);
+    }
+    if (color_space_ul->uid[0]) {
+      mxf_write_local_tag(pb, 16, 0x321A);
+      avio_write(pb, color_space_ul->uid, 16);
+    }
 }
 
 static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
-- 
2.8.0.rc3.226.g39d4020



More information about the ffmpeg-devel mailing list