[FFmpeg-devel,02/12] avformat/mxfdec: add support for determining essence wrapping scheme

Submitted by Marton Balint on June 10, 2018, 10:36 a.m.

Details

Message ID 20180610103650.10155-2-cus@passwd.hu
State Accepted
Commit 7ec90b168b9ad5f6a2798c3df64eba65bd98910a
Headers show

Commit Message

Marton Balint June 10, 2018, 10:36 a.m.
Some code is based on bmxlib-libmxf/mxf/mxf_utils.c.

Signed-off-by: Marton Balint <cus@passwd.hu>
---
 libavformat/mxf.h    |  9 ++++++
 libavformat/mxfdec.c | 79 +++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 68 insertions(+), 20 deletions(-)

Comments

Tomas Härdin June 13, 2018, 2:46 p.m.
sön 2018-06-10 klockan 12:36 +0200 skrev Marton Balint:
> Some code is based on bmxlib-libmxf/mxf/mxf_utils.c.
> 
> > Signed-off-by: Marton Balint <cus@passwd.hu>
> ---
>  libavformat/mxf.h    |  9 ++++++
>  libavformat/mxfdec.c | 79 +++++++++++++++++++++++++++++++++++++++-------------
>  2 files changed, 68 insertions(+), 20 deletions(-)
> 
> diff --git a/libavformat/mxf.h b/libavformat/mxf.h
>  
> +static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul)
> +{
> +    int val;
> +    const MXFCodecUL *codec_ul;
> +
> +    codec_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul);
> +    if (!codec_ul->uid[0])
> +        codec_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
> +    if (!codec_ul->uid[0])
> +        codec_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul);
> +    if (!codec_ul->uid[0] || !codec_ul->wrapping_indicator_pos)
> +        return UnknownWrapped;
> +
> +    val = (*essence_container_ul)[codec_ul->wrapping_indicator_pos];

Maybe a check on wrapping_indicator_pos? Not really needed since the
value comes from a table, but I felt I should mention it at least.

Patch looks OK as far as I remember MXF wrapping working

/Tomas
Marton Balint June 13, 2018, 6:30 p.m.
On Wed, 13 Jun 2018, Tomas Härdin wrote:

> sön 2018-06-10 klockan 12:36 +0200 skrev Marton Balint:
>> Some code is based on bmxlib-libmxf/mxf/mxf_utils.c.
>> 
>> > Signed-off-by: Marton Balint <cus@passwd.hu>
>> ---
>>  libavformat/mxf.h    |  9 ++++++
>>  libavformat/mxfdec.c | 79 +++++++++++++++++++++++++++++++++++++++-------------
>>  2 files changed, 68 insertions(+), 20 deletions(-)
>> 
>> diff --git a/libavformat/mxf.h b/libavformat/mxf.h
>>  
>> +static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul)
>> +{
>> +    int val;
>> +    const MXFCodecUL *codec_ul;
>> +
>> +    codec_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul);
>> +    if (!codec_ul->uid[0])
>> +        codec_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
>> +    if (!codec_ul->uid[0])
>> +        codec_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul);
>> +    if (!codec_ul->uid[0] || !codec_ul->wrapping_indicator_pos)
>> +        return UnknownWrapped;
>> +
>> +    val = (*essence_container_ul)[codec_ul->wrapping_indicator_pos];
>
> Maybe a check on wrapping_indicator_pos? Not really needed since the
> value comes from a table, but I felt I should mention it at least.

matching_len also lacks such checks, so I don't think its necessary.

Regards,
Marton
Tomas Härdin June 13, 2018, 7 p.m.
ons 2018-06-13 klockan 20:30 +0200 skrev Marton Balint:
> 
> On Wed, 13 Jun 2018, Tomas Härdin wrote:
> 
> > sön 2018-06-10 klockan 12:36 +0200 skrev Marton Balint:
> > > Some code is based on bmxlib-libmxf/mxf/mxf_utils.c.
> > > 
> > > > Signed-off-by: Marton Balint <cus@passwd.hu>
> > > 
> > > ---
> > >  libavformat/mxf.h    |  9 ++++++
> > >  libavformat/mxfdec.c | 79
> > > +++++++++++++++++++++++++++++++++++++++-------------
> > >  2 files changed, 68 insertions(+), 20 deletions(-)
> > > 
> > > diff --git a/libavformat/mxf.h b/libavformat/mxf.h
> > >  
> > > +static MXFWrappingScheme mxf_get_wrapping_kind(UID
> > > *essence_container_ul)
> > > +{
> > > +    int val;
> > > +    const MXFCodecUL *codec_ul;
> > > +
> > > +    codec_ul =
> > > mxf_get_codec_ul(mxf_picture_essence_container_uls,
> > > essence_container_ul);
> > > +    if (!codec_ul->uid[0])
> > > +        codec_ul =
> > > mxf_get_codec_ul(mxf_sound_essence_container_uls,
> > > essence_container_ul);
> > > +    if (!codec_ul->uid[0])
> > > +        codec_ul =
> > > mxf_get_codec_ul(mxf_data_essence_container_uls,
> > > essence_container_ul);
> > > +    if (!codec_ul->uid[0] || !codec_ul->wrapping_indicator_pos)
> > > +        return UnknownWrapped;
> > > +
> > > +    val = (*essence_container_ul)[codec_ul-
> > > >wrapping_indicator_pos];
> > 
> > Maybe a check on wrapping_indicator_pos? Not really needed since
> > the
> > value comes from a table, but I felt I should mention it at least.
> 
> matching_len also lacks such checks, so I don't think its necessary.

Fair enough

/Tomas

Patch hide | download patch | download mbox

diff --git a/libavformat/mxf.h b/libavformat/mxf.h
index 93bc2cd075..f6e75919c5 100644
--- a/libavformat/mxf.h
+++ b/libavformat/mxf.h
@@ -65,11 +65,20 @@  typedef struct KLVPacket {
     int64_t next_klv;
 } KLVPacket;
 
+typedef enum {
+    NormalWrap = 0,
+    D10D11Wrap,
+    RawAWrap,
+    RawVWrap
+} MXFWrappingIndicatorType;
+
 typedef struct MXFCodecUL {
     UID uid;
     unsigned matching_len;
     int id;
     const char *desc;
+    unsigned wrapping_indicator_pos;
+    MXFWrappingIndicatorType wrapping_indicator_type;
 } MXFCodecUL;
 
 typedef struct {
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index a5c5fb3b8a..927653b515 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -76,6 +76,12 @@  typedef enum {
     OPSONYOpt,  /* FATE sample, violates the spec in places */
 } MXFOP;
 
+typedef enum {
+    UnknownWrapped = 0,
+    FrameWrapped,
+    ClipWrapped,
+} MXFWrappingScheme;
+
 typedef struct MXFPartition {
     int closed;
     int complete;
@@ -165,6 +171,7 @@  typedef struct {
     int64_t original_duration; /* st->duration in SampleRate/EditRate units */
     int index_sid;
     int body_sid;
+    MXFWrappingScheme wrapping;
 } MXFTrack;
 
 typedef struct MXFDescriptor {
@@ -281,11 +288,6 @@  typedef struct MXFContext {
     int edit_units_per_packet;      ///< how many edit units to read at a time (PCM, OPAtom)
 } MXFContext;
 
-enum MXFWrappingScheme {
-    Frame,
-    Clip,
-};
-
 /* NOTE: klv_offset is not set (-1) for local keys */
 typedef int MXFMetadataReadFunc(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset);
 
@@ -1233,16 +1235,16 @@  static void *mxf_resolve_strong_ref(MXFContext *mxf, UID *strong_ref, enum MXFMe
 
 static const MXFCodecUL mxf_picture_essence_container_uls[] = {
     // video essence container uls
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000 },
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x10,0x60,0x01 }, 14,       AV_CODEC_ID_H264 }, /* H.264 frame wrapped */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, 14,      AV_CODEC_ID_DNXHD }, /* VC-3 */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x12,0x01,0x00 }, 14,        AV_CODEC_ID_VC1 }, /* VC-1 frame wrapped */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x14,0x01,0x00 }, 14,       AV_CODEC_ID_TIFF }, /* TIFF */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x15,0x01,0x00 }, 14,      AV_CODEC_ID_DIRAC }, /* VC-2 */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MPEG-ES frame wrapped */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x04,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* Type D-10 mapping of 40Mbps 525/60-I */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14,    AV_CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14,   AV_CODEC_ID_RAWVIDEO }, /* uncompressed picture */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x0c,0x01,0x00 }, 14,   AV_CODEC_ID_JPEG2000, NULL, 14 },
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x10,0x60,0x01 }, 14,       AV_CODEC_ID_H264, NULL, 15 }, /* H.264 */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, 14,      AV_CODEC_ID_DNXHD, NULL, 14 }, /* VC-3 */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x12,0x01,0x00 }, 14,        AV_CODEC_ID_VC1, NULL, 14 }, /* VC-1 */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x14,0x01,0x00 }, 14,       AV_CODEC_ID_TIFF, NULL, 14 }, /* TIFF */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x15,0x01,0x00 }, 14,      AV_CODEC_ID_DIRAC, NULL, 14 }, /* VC-2 */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO, NULL, 15 }, /* MPEG-ES */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x04,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO, NULL, 15, D10D11Wrap }, /* SMPTE D-10 mapping */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x02,0x41,0x01 }, 14,    AV_CODEC_ID_DVVIDEO, NULL, 15 }, /* DV 625 25mbps */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x05,0x00,0x00 }, 14,   AV_CODEC_ID_RAWVIDEO, NULL, 15, RawVWrap }, /* uncompressed picture */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x01,0x01 }, 15,     AV_CODEC_ID_HQ_HQA },
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0a,0x0e,0x0f,0x03,0x01,0x02,0x20,0x02,0x01 }, 15,        AV_CODEC_ID_HQX },
     { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4f }, 14,   AV_CODEC_ID_RAWVIDEO }, /* Legacy ?? Uncompressed Picture */
@@ -1273,21 +1275,55 @@  static const MXFCodecUL mxf_intra_only_picture_coded_width[] = {
 
 static const MXFCodecUL mxf_sound_essence_container_uls[] = {
     // sound essence container uls
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, AV_CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14,       AV_CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream id */
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended Template */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x06,0x01,0x00 }, 14, AV_CODEC_ID_PCM_S16LE, NULL, 14, RawAWrap }, /* BWF */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x02,0x0d,0x01,0x03,0x01,0x02,0x04,0x40,0x01 }, 14,       AV_CODEC_ID_MP2, NULL, 15 }, /* MPEG-ES */
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x01,0x0d,0x01,0x03,0x01,0x02,0x01,0x01,0x01 }, 14, AV_CODEC_ID_PCM_S16LE, NULL, 13 }, /* D-10 Mapping 50Mbps PAL Extended Template */
     { { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0xff,0x4b,0x46,0x41,0x41,0x00,0x0d,0x4d,0x4F }, 14, AV_CODEC_ID_PCM_S16LE }, /* 0001GL00.MXF.A1.mxf_opatom.mxf */
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14,       AV_CODEC_ID_AAC }, /* MPEG-2 AAC ADTS (legacy) */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,      AV_CODEC_ID_NONE },
 };
 
 static const MXFCodecUL mxf_data_essence_container_uls[] = {
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0d,0x00,0x00 }, 16, AV_CODEC_ID_NONE,      "vbi_smpte_436M" },
-    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 }, 16, AV_CODEC_ID_NONE, "vbi_vanc_smpte_436M" },
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0d,0x00,0x00 }, 16, AV_CODEC_ID_NONE,      "vbi_smpte_436M", 11 },
+    { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 }, 16, AV_CODEC_ID_NONE, "vbi_vanc_smpte_436M", 11 },
     { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x09,0x0d,0x01,0x03,0x01,0x02,0x13,0x01,0x01 }, 16, AV_CODEC_ID_TTML },
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0, AV_CODEC_ID_NONE },
 };
 
+static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul)
+{
+    int val;
+    const MXFCodecUL *codec_ul;
+
+    codec_ul = mxf_get_codec_ul(mxf_picture_essence_container_uls, essence_container_ul);
+    if (!codec_ul->uid[0])
+        codec_ul = mxf_get_codec_ul(mxf_sound_essence_container_uls, essence_container_ul);
+    if (!codec_ul->uid[0])
+        codec_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul);
+    if (!codec_ul->uid[0] || !codec_ul->wrapping_indicator_pos)
+        return UnknownWrapped;
+
+    val = (*essence_container_ul)[codec_ul->wrapping_indicator_pos];
+    switch (codec_ul->wrapping_indicator_type) {
+        case RawVWrap:
+            val = val % 4;
+            break;
+        case RawAWrap:
+            if (val == 0x03 || val == 0x04)
+                val -= 0x02;
+            break;
+        case D10D11Wrap:
+            if (val == 0x02)
+                val = 0x01;
+            break;
+    }
+    if (val == 0x01)
+        return FrameWrapped;
+    if (val == 0x02)
+        return ClipWrapped;
+    return UnknownWrapped;
+}
+
 static int mxf_get_sorted_table_segments(MXFContext *mxf, int *nb_sorted_segments, MXFIndexTableSegment ***sorted_segments)
 {
     int i, j, nb_segments = 0;
@@ -2179,6 +2215,9 @@  static int mxf_parse_structural_metadata(MXFContext *mxf)
         PRINT_KEY(mxf->fc, "essence codec     ul", descriptor->essence_codec_ul);
         PRINT_KEY(mxf->fc, "essence container ul", descriptor->essence_container_ul);
         essence_container_ul = &descriptor->essence_container_ul;
+        source_track->wrapping = (mxf->op == OPAtom) ? ClipWrapped : mxf_get_wrapping_kind(essence_container_ul);
+        if (source_track->wrapping == UnknownWrapped)
+            av_log(mxf->fc, AV_LOG_INFO, "wrapping of stream %d is unknown\n", st->index);
         /* HACK: replacing the original key with mxf_encrypted_essence_container
          * is not allowed according to s429-6, try to find correct information anyway */
         if (IS_KLV_KEY(essence_container_ul, mxf_encrypted_essence_container)) {