@@ -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];
@@ -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);
@@ -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);
@@ -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)
Signed-off-by: Steven Robertson <steven@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(-)