>From 2a657145a9b6bbbbbc2c1beb450100fe2d4d80ee Mon Sep 17 00:00:00 2001
From: "Axel Technology" <development@axeltechnology.com>
Date: Mon, 23 Oct 2017 18:02:58 +0200
Subject: [PATCH] Sony XDCAM Fix

Signed-off-by: Axel Technology <development@axeltechnology.com>
---
 libavformat/mxfenc.c | 112 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 66 insertions(+), 46 deletions(-)

diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index 7733ef8..aba3850 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -86,11 +86,16 @@ typedef struct MXFStreamContext {
     int component_depth;
     int color_siting;
     int signal_standard;
+    int v_chroma_sub_sample;
     int h_chroma_sub_sample;
     int temporal_reordering;
     AVRational aspect_ratio; ///< display aspect ratio
-    int closed_gop;          ///< gop is closed, used in mpeg-2 frame parsing
     int video_bit_rate;
+    int seq_closed_gop;      ///< all gops in sequence are closed, used in mpeg-2 descriptor
+    int closed_gop;          ///< previous gop was closed, used in mpeg-2 frame parsing
+    int max_gop;             ///< maximum gop size, used by mpeg-2 descriptor
+    int b_picture_count;     ///< maximum number of consecutive b pictures, used in mpeg-2 descriptor
+    int low_delay;           ///< low delay, used in mpeg-2 descriptor
 } MXFStreamContext;
 
 typedef struct MXFContainerEssenceEntry {
@@ -352,7 +357,6 @@ static const uint8_t multiple_desc_ul[]     = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x
 
 /**
  * SMPTE RP210 http://www.smpte-ra.org/mdd/index.html
- *             https://smpte-ra.org/sites/default/files/Labels.xml
  */
 static const MXFLocalTagPair mxf_local_tag_batch[] = {
     // preface set
@@ -409,8 +413,12 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = {
     { 0x3002, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x06,0x01,0x02,0x00,0x00,0x00,0x00}}, /* ContainerDuration */
     { 0x3004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x02,0x00,0x00}}, /* Essence Container */
     // Generic Picture Essence Descriptor
+    { 0x320A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0D,0x00,0x00,0x00}}, /* DisplayXOffset */
+    { 0x320B, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x0E,0x00,0x00,0x00}}, /* DisplayYOffset */
     { 0x320C, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Frame Layout */
     { 0x320D, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x03,0x02,0x05,0x00,0x00,0x00}}, /* Video Line Map */
+    { 0x3205, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x08,0x00,0x00,0x00}}, /* Sampled Width */
+    { 0x3204, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x07,0x00,0x00,0x00}}, /* Sampled Height */
     { 0x3203, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x02,0x02,0x00,0x00,0x00}}, /* Stored Width */
     { 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 */
@@ -423,6 +431,7 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = {
     // CDCI Picture Essence Descriptor
     { 0x3301, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x05,0x03,0x0A,0x00,0x00,0x00}}, /* Component Depth */
     { 0x3302, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x05,0x00,0x00,0x00}}, /* Horizontal Subsampling */
+    { 0x3308, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x05,0x01,0x10,0x00,0x00,0x00}}, /* Vertical Subsampling */
     { 0x3303, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x01,0x06,0x00,0x00,0x00}}, /* Color Siting */
     // Generic Sound Essence Descriptor
     { 0x3D02, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x02,0x03,0x01,0x04,0x00,0x00,0x00}}, /* Locked/Unlocked */
@@ -439,9 +448,12 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = {
     { 0x3F08, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x04,0x04,0x01,0x01,0x00,0x00,0x00}}, /* Slice Count */
     { 0x3F09, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x04,0x04,0x01,0x06,0x00,0x00,0x00}}, /* Delta Entry Array */
     { 0x3F0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x04,0x04,0x02,0x05,0x00,0x00,0x00}}, /* Index Entry Array */
-    // MPEG video Descriptor
-    { 0x8000, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0B,0x00,0x00}}, /* BitRate */
-    { 0x8007, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0A,0x00,0x00}}, /* ProfileAndLevel */
+    { 0x8003, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x05,0x00,0x00}}, /* LowDelay */
+    { 0x8004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x06,0x00,0x00}}, /* ClosedGOP */
+    { 0x8006, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x08,0x00,0x00}}, /* MaxGOP */
+    { 0x8007, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x09,0x00,0x00}}, /* BPictureCount */
+    { 0x8008, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0A,0x00,0x00}}, /* ProfileAndLevel*/
+    { 0x8009, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x0B,0x00,0x00}}, /* BitRate */
     // Wave Audio Essence Descriptor
     { 0x3D09, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x03,0x05,0x00,0x00,0x00}}, /* Average Bytes Per Second */
     { 0x3D0A, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x02,0x01,0x00,0x00,0x00}}, /* Block Align */
@@ -483,27 +495,6 @@ static int klv_ber_length(uint64_t len)
         return (av_log2(len) >> 3) + 2;
 }
 
-static int klv_encode_ber_length(AVIOContext *pb, uint64_t len)
-{
-    // Determine the best BER size
-    int size;
-    if (len < 128) {
-        //short form
-        avio_w8(pb, len);
-        return 1;
-    }
-
-    size = (av_log2(len) >> 3) + 1;
-
-    // long form
-    avio_w8(pb, 0x80 + size);
-    while(size) {
-        size--;
-        avio_w8(pb, len >> 8 * size & 0xff);
-    }
-    return 0;
-}
-
 static void klv_encode_ber4_length(AVIOContext *pb, int len)
 {
     avio_w8(pb, 0x80 + 3);
@@ -538,7 +529,7 @@ static void mxf_write_primer_pack(AVFormatContext *s)
     local_tag_number += mxf->store_user_comments * FF_ARRAY_ELEMS(mxf_user_comments_local_tag);
 
     avio_write(pb, primer_pack_key, 16);
-    klv_encode_ber_length(pb, local_tag_number * 18 + 8);
+    klv_encode_ber4_length(pb, local_tag_number * 18 + 8);
 
     avio_wb32(pb, local_tag_number); // local_tag num
     avio_wb32(pb, 18); // item size, always 18 according to the specs
@@ -615,7 +606,7 @@ static void mxf_write_preface(AVFormatContext *s)
 
     mxf_write_metadata_key(pb, 0x012f00);
     PRINT_KEY(s, "preface key", pb->buf_ptr - 16);
-    klv_encode_ber_length(pb, 130 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
+    klv_encode_ber4_length(pb, 130 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
 
     // write preface set uid
     mxf_write_local_tag(pb, 16, 0x3C0A);
@@ -730,7 +721,7 @@ static void mxf_write_identification(AVFormatContext *s)
     length = 72 + mxf_utf16_local_tag_length(company) +
                   mxf_utf16_local_tag_length(product) +
                   mxf_utf16_local_tag_length(version);
-    klv_encode_ber_length(pb, length);
+    klv_encode_ber4_length(pb, length);
 
     // write uid
     mxf_write_local_tag(pb, 16, 0x3C0A);
@@ -759,7 +750,7 @@ static void mxf_write_content_storage(AVFormatContext *s)
 
     mxf_write_metadata_key(pb, 0x011800);
     PRINT_KEY(s, "content storage key", pb->buf_ptr - 16);
-    klv_encode_ber_length(pb, 92);
+    klv_encode_ber4_length(pb, 92);
 
     // write uid
     mxf_write_local_tag(pb, 16, 0x3C0A);
@@ -786,7 +777,7 @@ static void mxf_write_track(AVFormatContext *s, AVStream *st, enum MXFMetadataSe
 
     mxf_write_metadata_key(pb, 0x013b00);
     PRINT_KEY(s, "track key", pb->buf_ptr - 16);
-    klv_encode_ber_length(pb, 80);
+    klv_encode_ber4_length(pb, 80);
 
     // write track uid
     mxf_write_local_tag(pb, 16, 0x3C0A);
@@ -857,7 +848,7 @@ static void mxf_write_sequence(AVFormatContext *s, AVStream *st, enum MXFMetadat
 
     mxf_write_metadata_key(pb, 0x010f00);
     PRINT_KEY(s, "sequence key", pb->buf_ptr - 16);
-    klv_encode_ber_length(pb, 80);
+    klv_encode_ber4_length(pb, 80);
 
     mxf_write_local_tag(pb, 16, 0x3C0A);
     mxf_write_uuid(pb, type == MaterialPackage ? Sequence: Sequence + TypeBottom, st->index);
@@ -883,7 +874,7 @@ static void mxf_write_timecode_component(AVFormatContext *s, AVStream *st, enum
     AVIOContext *pb = s->pb;
 
     mxf_write_metadata_key(pb, 0x011400);
-    klv_encode_ber_length(pb, 75);
+    klv_encode_ber4_length(pb, 75);
 
     // UID
     mxf_write_local_tag(pb, 16, 0x3C0A);
@@ -912,7 +903,7 @@ static void mxf_write_structural_component(AVFormatContext *s, AVStream *st, enu
 
     mxf_write_metadata_key(pb, 0x011100);
     PRINT_KEY(s, "sturctural component key", pb->buf_ptr - 16);
-    klv_encode_ber_length(pb, 108);
+    klv_encode_ber4_length(pb, 108);
 
     // write uid
     mxf_write_local_tag(pb, 16, 0x3C0A);
@@ -950,7 +941,7 @@ static void mxf_write_multi_descriptor(AVFormatContext *s)
 
     mxf_write_metadata_key(pb, 0x014400);
     PRINT_KEY(s, "multiple descriptor key", pb->buf_ptr - 16);
-    klv_encode_ber_length(pb, 64 + 16LL * s->nb_streams);
+    klv_encode_ber4_length(pb, 64 + 16LL * s->nb_streams);
 
     mxf_write_local_tag(pb, 16, 0x3C0A);
     mxf_write_uuid(pb, MultipleDescriptor, 0);
@@ -1014,7 +1005,7 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
     int stored_height = (st->codecpar->height+15)/16*16;
     int display_height;
     int f1, f2;
-    unsigned desc_size = size+8+8+8+8+8+8+8+5+16+4+12+20+5;
+    unsigned desc_size = size+8+8+8+8+8+8+8+5+16+sc->interlaced*4+12+20+5;
     if (sc->interlaced && sc->field_dominance)
         desc_size += 5;
     if (sc->signal_standard)
@@ -1041,6 +1032,21 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
     mxf_write_local_tag(pb, 4, 0x3208);
     avio_wb32(pb, display_height>>sc->interlaced);
 
+    // signal standard +5 XDCAM
+    mxf_write_local_tag(pb, 1, 0x3215);
+    if (display_height == 1080) {
+        avio_w8(pb, 4); // SMPTE 274M
+    } else if (display_height == 720) {
+        avio_w8(pb, 5); // SMPTE 296M
+    } else if (st->codec->width == 720) {
+        if (sc->interlaced) {
+            avio_w8(pb, 1); // SMPTE 125M ITU-R BT.601
+        } else {
+            avio_w8(pb, 2); // SMPTE 293M ITU-R BT.1358
+        }
+    } else {
+        avio_w8(pb, 0); // unknown
+    }
     // presentation Y offset
     mxf_write_local_tag(pb, 4, 0x320B);
     avio_wb32(pb, (st->codecpar->height - display_height)>>sc->interlaced);
@@ -1049,6 +1055,10 @@ static void mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID ke
     mxf_write_local_tag(pb, 4, 0x3301);
     avio_wb32(pb, sc->component_depth);
 
+    // vertical subsampling
+    mxf_write_local_tag(pb, 4, 0x3308);
+    avio_wb32(pb, sc->v_chroma_sub_sample);
+
     // horizontal subsampling
     mxf_write_local_tag(pb, 4, 0x3302);
     avio_wb32(pb, sc->h_chroma_sub_sample);
@@ -1220,7 +1230,7 @@ static int mxf_write_tagged_value(AVFormatContext *s, const char* name, const ch
         return 1;
 
     mxf_write_metadata_key(pb, 0x013f00);
-    klv_encode_ber_length(pb, 24 + name_size + indirect_value_size);
+    klv_encode_ber4_length(pb, 24 + name_size + indirect_value_size);
 
     // write instance UID
     mxf_write_local_tag(pb, 16, 0x3C0A);
@@ -1269,11 +1279,11 @@ static void mxf_write_package(AVFormatContext *s, enum MXFMetadataSetType type,
             user_comment_count = mxf_write_user_comments(s, s->metadata);
         mxf_write_metadata_key(pb, 0x013600);
         PRINT_KEY(s, "Material Package key", pb->buf_ptr - 16);
-        klv_encode_ber_length(pb, 92 + name_size + (16*track_count) + (16*user_comment_count) + 12LL*mxf->store_user_comments);
+        klv_encode_ber4_length(pb, 92 + name_size + (16*track_count) + (16*user_comment_count) + 12LL*mxf->store_user_comments);
     } else {
         mxf_write_metadata_key(pb, 0x013700);
         PRINT_KEY(s, "Source Package key", pb->buf_ptr - 16);
-        klv_encode_ber_length(pb, 112 + name_size + (16*track_count) + 12LL*mxf->store_user_comments); // 20 bytes length for descriptor reference
+        klv_encode_ber4_length(pb, 112 + name_size + (16*track_count) + 12LL*mxf->store_user_comments); // 20 bytes length for descriptor reference
     }
 
     // write uid
@@ -1348,7 +1358,7 @@ static int mxf_write_essence_container_data(AVFormatContext *s)
     AVIOContext *pb = s->pb;
 
     mxf_write_metadata_key(pb, 0x012300);
-    klv_encode_ber_length(pb, 72);
+    klv_encode_ber4_length(pb, 72);
 
     mxf_write_local_tag(pb, 16, 0x3C0A); // Instance UID
     mxf_write_uuid(pb, EssenceContainerData, 0);
@@ -1413,6 +1423,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
     AVIOContext *pb = s->pb;
     int i, j, temporal_reordering = 0;
     int key_index = mxf->last_key_index;
+    int prev_non_b_picture = 0;
 
     av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count);
 
@@ -1422,9 +1433,9 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
     avio_write(pb, index_table_segment_key, 16);
 
     if (mxf->edit_unit_byte_count) {
-        klv_encode_ber_length(pb, 80);
+        klv_encode_ber4_length(pb, 80);
     } else {
-        klv_encode_ber_length(pb, 85 + 12+(s->nb_streams+1LL)*6 +
+        klv_encode_ber4_length(pb, 85 + 12+(s->nb_streams+1LL)*6 +
                               12+mxf->edit_units_count*(11+mxf->slice_count*4LL));
     }
 
@@ -1490,6 +1501,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
             }
         }
 
+        MXFStreamContext *sc = s->streams[0]->priv_data;
         mxf_write_local_tag(pb, 8 + mxf->edit_units_count*(11+mxf->slice_count*4), 0x3F0A);
         avio_wb32(pb, mxf->edit_units_count);  // num of entries
         avio_wb32(pb, 11+mxf->slice_count*4);  // size of one entry
@@ -1498,6 +1510,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
             int temporal_offset = 0;
 
             if (!(mxf->index_entries[i].flags & 0x33)) { // I-frame
+                sc->max_gop = FFMAX(sc->max_gop, i - mxf->last_key_index);
                 mxf->last_key_index = key_index;
                 key_index = i;
             }
@@ -1517,11 +1530,13 @@ static void mxf_write_index_table_segment(AVFormatContext *s)
             avio_w8(pb, temporal_offset);
 
             if ((mxf->index_entries[i].flags & 0x30) == 0x30) { // back and forward prediction
+                sc->b_picture_count = FFMAX(sc->b_picture_count, i - prev_non_b_picture);
                 avio_w8(pb, mxf->last_key_index - i);
             } else {
                 avio_w8(pb, key_index - i); // key frame offset
                 if ((mxf->index_entries[i].flags & 0x20) == 0x20) // only forward
                     mxf->last_key_index = key_index;
+                prev_non_b_picture = i;
             }
 
             if (!(mxf->index_entries[i].flags & 0x33) && // I-frame
@@ -1590,7 +1605,7 @@ static int mxf_write_partition(AVFormatContext *s, int bodysid,
     else
         avio_write(pb, body_partition_key, 16);
 
-    klv_encode_ber_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
+    klv_encode_ber4_length(pb, 88 + 16LL * DESCRIPTOR_COUNT(mxf->essence_container_count));
 
     // write partition value
     avio_wb16(pb, 1); // majorVersion
@@ -1823,7 +1838,6 @@ static const struct {
     int profile;
     uint8_t interlaced;
 } mxf_h264_codec_uls[] = {
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 },      0,  66, 0 }, // AVC Baseline, Unconstrained Coding
     {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 },      0, 110, 0 }, // AVC High 10 Intra
     {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960,   0, 1 }, // AVC Intra 50 1080i60
     {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088,   0, 1 }, // AVC Intra 50 1080i50
@@ -1953,6 +1967,7 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st,
             if ((pkt->data[i+1] & 0xf0) == 0x10) { // seq ext
                 st->codecpar->profile = pkt->data[i+1] & 0x07;
                 st->codecpar->level   = pkt->data[i+2] >> 4;
+                sc->low_delay = pkt->data[i+6] >> 7;
             } else if (i + 5 < pkt->size && (pkt->data[i+1] & 0xf0) == 0x80) { // pict coding ext
                 sc->interlaced = !(pkt->data[i+5] & 0x80); // progressive frame
                 if (sc->interlaced)
@@ -2076,7 +2091,11 @@ static int mxf_write_header(AVFormatContext *s)
             sc->component_depth = 8;
             sc->h_chroma_sub_sample = 2;
             sc->color_siting = 0xFF;
-
+            if (st->codec->pix_fmt == AV_PIX_FMT_YUV420P) {
+                sc->v_chroma_sub_sample = 2;
+            } else {
+                sc->v_chroma_sub_sample = 1;
+            }
             if (pix_desc) {
                 sc->component_depth     = pix_desc->comp[0].depth;
                 sc->h_chroma_sub_sample = 1 << pix_desc->log2_chroma_w;
@@ -2254,6 +2273,7 @@ static void mxf_write_system_item(AVFormatContext *s)
     avio_w8(pb, 0x00); // content package type
     avio_wb16(pb, 0x00); // channel handle
     avio_wb16(pb, (mxf->tc.start + frame) & 0xFFFF); // continuity count, supposed to overflow
+    avio_wb16(pb, mxf->last_indexed_edit_unit + mxf->edit_units_count); // continuity count
     if (mxf->essence_container_count > 1)
         avio_write(pb, multiple_desc_ul, 16);
     else {
@@ -2502,7 +2522,7 @@ static void mxf_write_random_index_pack(AVFormatContext *s)
     int i;
 
     avio_write(pb, random_index_pack_key, 16);
-    klv_encode_ber_length(pb, 28 + 12LL*mxf->body_partitions_count);
+    klv_encode_ber4_length(pb, 28 + 12LL*mxf->body_partitions_count);
 
     if (mxf->edit_unit_byte_count && s->oformat != &ff_mxf_opatom_muxer)
         avio_wb32(pb, 1); // BodySID of header partition
-- 
2.10.2.windows.1

