From ea55a11ced5ef73bc7173ae2d3e268e26b351350 Mon Sep 17 00:00:00 2001 From: Baptiste Coudurier Date: Wed, 21 Mar 2018 09:35:22 -0700 Subject: [PATCH] avformat/mxfenc: add mpeg-2 specific metadata, fix compatibility with sony content browser --- libavformat/mxfenc.c | 46 ++++++++++++++++++++++++++++++--- tests/ref/lavf/mxf | 6 ++--- tests/ref/lavf/mxf_d10 | 2 +- tests/ref/lavf/mxf_dv25 | 2 +- tests/ref/lavf/mxf_dvcpro50 | 2 +- tests/ref/lavf/mxf_opatom | 2 +- tests/ref/lavf/mxf_opatom_audio | 2 +- 7 files changed, 50 insertions(+), 12 deletions(-) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 39b7f80639..a62d2a3e94 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -95,6 +95,10 @@ typedef struct MXFStreamContext { int video_bit_rate; int slice_offset; int frame_size; ///< frame size in bytes + int seq_closed_gop; ///< all gops in sequence are closed, used in mpeg-2 descriptor + 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 { @@ -558,7 +562,11 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = { { 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 */ + { 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,0x0A,0x00,0x00}}, /* ProfileAndLevel */ + { 0x8008, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x01,0x06,0x02,0x01,0x09,0x00,0x00}}, /* BPictureCount */ // 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 */ @@ -1294,10 +1302,8 @@ static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID avio_wb32(pb, sc->h_chroma_sub_sample); // vertical subsampling - if (sc->v_chroma_sub_sample) { - mxf_write_local_tag(pb, 4, 0x3308); - avio_wb32(pb, sc->v_chroma_sub_sample); - } + mxf_write_local_tag(pb, 4, 0x3308); + avio_wb32(pb, sc->v_chroma_sub_sample); // color siting mxf_write_local_tag(pb, 1, 0x3303); @@ -1409,6 +1415,22 @@ static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st) if (!st->codecpar->profile) profile_and_level |= 0x80; // escape bit avio_w8(pb, profile_and_level); + + // low delay + mxf_write_local_tag(pb, 1, 0x8003); + avio_w8(pb, sc->low_delay); + + // closed gop + mxf_write_local_tag(pb, 1, 0x8004); + avio_w8(pb, sc->seq_closed_gop); + + // max gop + mxf_write_local_tag(pb, 2, 0x8006); + avio_wb16(pb, sc->max_gop); + + // b picture count + mxf_write_local_tag(pb, 2, 0x8008); + avio_wb16(pb, sc->b_picture_count); } mxf_update_klv_size(pb, pos); @@ -1729,6 +1751,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; int64_t pos; av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count); @@ -1807,6 +1830,7 @@ static void mxf_write_index_table_segment(AVFormatContext *s) } if (!mxf->edit_unit_byte_count) { + MXFStreamContext *sc = s->streams[0]->priv_data; mxf_write_local_tag(pb, 8 + mxf->edit_units_count*15, 0x3F0A); avio_wb32(pb, mxf->edit_units_count); // num of entries avio_wb32(pb, 15); // size of one entry @@ -1815,6 +1839,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; } @@ -1834,11 +1859,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 @@ -2285,6 +2312,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) @@ -2293,9 +2321,14 @@ static int mxf_parse_mpeg2_frame(AVFormatContext *s, AVStream *st, } } else if (c == 0x1b8) { // gop if (pkt->data[i+4]>>6 & 0x01) { // closed + if (sc->seq_closed_gop == -1) + sc->seq_closed_gop = 1; sc->closed_gop = 1; if (e->flags & 0x40) // sequence header present e->flags |= 0x80; // random access + } else { + sc->seq_closed_gop = 0; + sc->closed_gop = 0; } } else if (c == 0x1b3) { // seq e->flags |= 0x40; @@ -2407,6 +2440,7 @@ static int mxf_write_header(AVFormatContext *s) // Default component depth to 8 sc->component_depth = 8; sc->h_chroma_sub_sample = 2; + sc->v_chroma_sub_sample = 2; sc->color_siting = 0xFF; if (pix_desc) { @@ -2434,6 +2468,10 @@ static int mxf_write_header(AVFormatContext *s) if((ret = mxf_init_timecode(s, st, rate)) < 0) return ret; + if (st->codecpar->codec_id == AV_CODEC_ID_MPEG2VIDEO) { + sc->seq_closed_gop = -1; // unknown yet + } + sc->video_bit_rate = st->codecpar->bit_rate; if (s->oformat == &ff_mxf_d10_muxer || diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf index 99d500aec7..05deaa3a69 100644 --- a/tests/ref/lavf/mxf +++ b/tests/ref/lavf/mxf @@ -1,9 +1,9 @@ -96c0f82082eb420ecbddf7810f3b3943 *./tests/data/lavf/lavf.mxf +eea31259441d909fedb9a0e0eb9bbdb2 *./tests/data/lavf/lavf.mxf 526393 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0x8dddfaab -072d0f1f4a2859a3416535beb3d33531 *./tests/data/lavf/lavf.mxf +7524e7319a64b639d6ef49446d46320e *./tests/data/lavf/lavf.mxf 561721 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0x96ff1b48 -8376d69f7eccfc268041dffd82db1a61 *./tests/data/lavf/lavf.mxf +e547b44d71cd5871582522a31511ae9c *./tests/data/lavf/lavf.mxf 526393 ./tests/data/lavf/lavf.mxf ./tests/data/lavf/lavf.mxf CRC=0x8dddfaab diff --git a/tests/ref/lavf/mxf_d10 b/tests/ref/lavf/mxf_d10 index a40a42a2e2..0b9f49bb09 100644 --- a/tests/ref/lavf/mxf_d10 +++ b/tests/ref/lavf/mxf_d10 @@ -1,3 +1,3 @@ -ad3f0da2f77e5269e896b367f2a5b0b0 *./tests/data/lavf/lavf.mxf_d10 +9f299fd4da6a20ef93adad7fe6a9f481 *./tests/data/lavf/lavf.mxf_d10 5332013 ./tests/data/lavf/lavf.mxf_d10 ./tests/data/lavf/lavf.mxf_d10 CRC=0x6c74d488 diff --git a/tests/ref/lavf/mxf_dv25 b/tests/ref/lavf/mxf_dv25 index efec757218..200511e164 100644 --- a/tests/ref/lavf/mxf_dv25 +++ b/tests/ref/lavf/mxf_dv25 @@ -1,3 +1,3 @@ -cd1ea9497444b0b43d930b0dc56aecf7 *./tests/data/lavf/lavf.mxf_dv25 +358791c5468c39673239e038fb64a734 *./tests/data/lavf/lavf.mxf_dv25 3834413 ./tests/data/lavf/lavf.mxf_dv25 ./tests/data/lavf/lavf.mxf_dv25 CRC=0xbdaf7f52 diff --git a/tests/ref/lavf/mxf_dvcpro50 b/tests/ref/lavf/mxf_dvcpro50 index bbe4562ec4..f212c0321d 100644 --- a/tests/ref/lavf/mxf_dvcpro50 +++ b/tests/ref/lavf/mxf_dvcpro50 @@ -1,3 +1,3 @@ -ce601c92f0e2d7f07cbf6263a8a18ea5 *./tests/data/lavf/lavf.mxf_dvcpro50 +fac7c59ea81c752d769335ddaa818f90 *./tests/data/lavf/lavf.mxf_dvcpro50 7431213 ./tests/data/lavf/lavf.mxf_dvcpro50 ./tests/data/lavf/lavf.mxf_dvcpro50 CRC=0xe3bbe4b4 diff --git a/tests/ref/lavf/mxf_opatom b/tests/ref/lavf/mxf_opatom index bca8f65154..5ea47f4df6 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -76093fef1ac42587cc374012dc1945db *./tests/data/lavf/lavf.mxf_opatom +49b0b3dfeb6a9ec024b047fc627b66fd *./tests/data/lavf/lavf.mxf_opatom 4717625 ./tests/data/lavf/lavf.mxf_opatom ./tests/data/lavf/lavf.mxf_opatom CRC=0xf55aa22a diff --git a/tests/ref/lavf/mxf_opatom_audio b/tests/ref/lavf/mxf_opatom_audio index 380ce4f0a3..540f430cda 100644 --- a/tests/ref/lavf/mxf_opatom_audio +++ b/tests/ref/lavf/mxf_opatom_audio @@ -1,3 +1,3 @@ -8524f908a6fa8750a4755ab79cc1516c *./tests/data/lavf/lavf.mxf_opatom_audio +862dc5c9f2c94bd2c545ca64f923d1a1 *./tests/data/lavf/lavf.mxf_opatom_audio 102969 ./tests/data/lavf/lavf.mxf_opatom_audio ./tests/data/lavf/lavf.mxf_opatom_audio CRC=0xd155c6ff