diff mbox

[FFmpeg-devel,2/2] avformat/mxfenc: support XAVC long gop

Message ID 20190403092202.31392-2-baptiste.coudurier@gmail.com
State Superseded
Headers show

Commit Message

Baptiste Coudurier April 3, 2019, 9:22 a.m. UTC
---
 libavformat/mxf.h    |   1 +
 libavformat/mxfenc.c | 197 ++++++++++++++++++++++++++++++++-----------
 2 files changed, 147 insertions(+), 51 deletions(-)

Comments

Thomas Mundt April 4, 2019, 2:27 p.m. UTC | #1
Hi Baptiste,

Am Mi., 3. Apr. 2019 um 11:23 Uhr schrieb Baptiste Coudurier <
baptiste.coudurier@gmail.com>:

> ---
>  libavformat/mxf.h    |   1 +
>  libavformat/mxfenc.c | 197 ++++++++++++++++++++++++++++++++-----------
>  2 files changed, 147 insertions(+), 51 deletions(-)
>
> diff --git a/libavformat/mxf.h b/libavformat/mxf.h
> index 4394450dea..f32124f772 100644
> --- a/libavformat/mxf.h
> +++ b/libavformat/mxf.h
> @@ -48,6 +48,7 @@ enum MXFMetadataSetType {
>      EssenceGroup,
>      TaggedValue,
>      TapeDescriptor,
> +    AVCSubDescriptor,
>  };
>
>  enum MXFFrameLayout {
> diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
> index 8c6db94865..1f865a0ad1 100644
> --- a/libavformat/mxfenc.c
> +++ b/libavformat/mxfenc.c
> @@ -49,7 +49,10 @@
>  #include "libavcodec/bytestream.h"
>  #include "libavcodec/dnxhddata.h"
>  #include "libavcodec/dv_profile.h"
> -#include "libavcodec/h264.h"
> +#include "libavcodec/golomb.h"
> +#include "libavcodec/h264data.h"
> +#include "libavcodec/h264_ps.h"
> +#include "libavcodec/h2645_parse.h"
>  #include "libavcodec/internal.h"
>  #include "audiointerleave.h"
>  #include "avformat.h"
> @@ -99,6 +102,7 @@ typedef struct MXFStreamContext {
>      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
> +    int avc_intra;
>  } MXFStreamContext;
>
>  typedef struct MXFContainerEssenceEntry {
> @@ -167,6 +171,7 @@ static const struct {
>  static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st);
>  static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st);
>  static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st);
> +static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st);
>  static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
>  static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream
> *st);
>  static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st);
> @@ -310,7 +315,7 @@ static const MXFContainerEssenceEntry
> mxf_essence_container_uls[] = {
>      { {
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x10,0x60,0x01
> },
>        {
> 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00
> },
>        {
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00
> },
> -      mxf_write_mpegvideo_desc },
> +      mxf_write_h264_desc },
>      // S436M ANC
>      { {
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x0e,0x00,0x00
> },
>        {
> 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x17,0x01,0x02,0x00
> },
> @@ -498,6 +503,12 @@ static const MXFLocalTagPair mxf_local_tag_batch[] = {
>      { 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 */
> +    // Generic Descriptor
> +    { 0x8100,
> {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00}},
> /* SubDescriptors */
> +    // AVC SubDescriptor
> +    { 0x8200,
> {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0E,0x00,0x00}},
> /* AVC Decoding Delay */
> +    { 0x8201,
> {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0A,0x00,0x00}},
> /* AVC Profile */
> +    { 0x8202,
> {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0D,0x00,0x00}},
> /* AVC Level */
>      // 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 */
> @@ -1126,6 +1137,8 @@ static const UID mxf_aes3_descriptor_key      = {
> 0x06,0x0E,0x2B,0x34,0x02,0x53,
>  static const UID mxf_cdci_descriptor_key      = {
> 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x28,0x00
> };
>  static const UID mxf_generic_sound_descriptor_key = {
> 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x42,0x00
> };
>
> +static const UID mxf_avc_subdescriptor_key = {
> 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00
> };
> +
>  static int get_trc(UID ul, enum AVColorTransferCharacteristic trc)
>  {
>      switch (trc){
> @@ -1317,6 +1330,13 @@ static int64_t
> mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID
>          avio_w8(pb, sc->field_dominance);
>      }
>
> +    if (st->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) {
> +        // write avc sub descriptor ref
> +        mxf_write_local_tag(pb, 8 + 16, 0x8100);
> +        mxf_write_refs_count(pb, 1);
> +        mxf_write_uuid(pb, AVCSubDescriptor, 0);
> +    }
> +
>      return pos;
>  }
>
> @@ -1329,10 +1349,50 @@ static void mxf_update_klv_size(AVIOContext *pb,
> int64_t pos)
>      avio_seek(pb, cur_pos, SEEK_SET);
>  }
>
> +static void mxf_write_avc_subdesc(AVFormatContext *s, AVStream *st)
> +{
> +    AVIOContext *pb = s->pb;
> +    int64_t pos;
> +
> +    avio_write(pb, mxf_avc_subdescriptor_key, 16);
> +    klv_encode_ber4_length(pb, 0);
> +    pos = avio_tell(pb);
> +
> +    mxf_write_local_tag(pb, 16, 0x3C0A);
> +    mxf_write_uuid(pb, AVCSubDescriptor, 0);
> +
> +    mxf_write_local_tag(pb, 1, 0x8200);
> +    avio_w8(pb, 0xFF); // AVC Decoding Delay, unknown
> +
> +    mxf_write_local_tag(pb, 1, 0x8201);
> +    avio_w8(pb, st->codecpar->profile); // AVC Profile
> +
> +    mxf_write_local_tag(pb, 1, 0x8202);
> +    avio_w8(pb, st->codecpar->level); // AVC Level
> +
> +    mxf_update_klv_size(s->pb, pos);
> +}
> +
>  static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
>  {
>      int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key);
>      mxf_update_klv_size(s->pb, pos);
> +
> +    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
> +        mxf_write_avc_subdesc(s, st);
> +    }
> +}
> +
> +static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st)
> +{
> +    MXFStreamContext *sc = st->priv_data;
> +    if (sc->avc_intra) {
> +        mxf_write_mpegvideo_desc(s, st);
> +    } else {
> +        int64_t pos = mxf_write_cdci_common(s, st,
> mxf_cdci_descriptor_key);
> +        mxf_update_klv_size(s->pb, pos);
> +        mxf_write_avc_subdesc(s, st);
> +    }
>  }
>
>  static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st)
> @@ -2136,30 +2196,30 @@ static const struct {
>      int frame_size;
>      int profile;
>      uint8_t interlaced;
> -    int long_gop; // 1 or 0 when there are separate UIDs for Long GOP and
> Intra, -1 when Intra/LGOP detection can be ignored
> +    int intra_only; // 1 or 0 when there are separate UIDs for Long GOP
> and Intra, -1 when Intra/LGOP detection can be ignored
>  } mxf_h264_codec_uls[] = {
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01
> },      0,  66, 0, -1 }, // AVC Baseline, Unconstrained Coding
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01
> },      0,  66, 0, -1 }, // AVC Baseline
>      {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x20,0x01
> },      0,  77, 0, -1 }, // AVC Main
>      {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x30,0x01
> },      0,  88, 0, -1 }, // AVC Extended
>      {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x40,0x01
> },      0, 100, 0, -1 }, // AVC High
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x50,0x01
> },      0, 110, 0,  1 }, // AVC High 10
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x60,0x01
> },      0, 122, 0,  1 }, // AVC High 422
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x70,0x01
> },      0, 244, 0,  1 }, // AVC High 444
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01
> },      0, 110, 0,  0 }, // AVC High 10 Intra
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01
> }, 232960,   0, 1,  0 }, // AVC Intra 50 1080i60
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02
> }, 281088,   0, 1,  0 }, // AVC Intra 50 1080i50
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03
> }, 232960,   0, 0,  0 }, // AVC Intra 50 1080p30
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04
> }, 281088,   0, 0,  0 }, // AVC Intra 50 1080p25
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08
> }, 116736,   0, 0,  0 }, // AVC Intra 50 720p60
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09
> }, 140800,   0, 0,  0 }, // AVC Intra 50 720p50
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01
> },      0, 122, 0,  0 }, // AVC High 422 Intra
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01
> }, 472576,   0, 1,  0 }, // AVC Intra 100 1080i60
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02
> }, 568832,   0, 1,  0 }, // AVC Intra 100 1080i50
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03
> }, 472576,   0, 0,  0 }, // AVC Intra 100 1080p30
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04
> }, 568832,   0, 0,  0 }, // AVC Intra 100 1080p25
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08
> }, 236544,   0, 0,  0 }, // AVC Intra 100 720p60
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09
> }, 284672,   0, 0,  0 }, // AVC Intra 100 720p50
> -    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x40,0x01
> },      0, 244, 0,  0 }, // AVC High 444 Intra
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x50,0x01
> },      0, 110, 0,  0 }, // AVC High 10
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x60,0x01
> },      0, 122, 0,  0 }, // AVC High 422
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x70,0x01
> },      0, 244, 0,  0 }, // AVC High 444
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01
> },      0, 110, 0,  1 }, // AVC High 10 Intra
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01
> }, 232960, 110, 1,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/59.94i
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02
> }, 281088, 110, 1,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/50i
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03
> }, 232960, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/29.97p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04
> }, 281088, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/25p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08
> }, 116736, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 720/59.94p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09
> }, 140800, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 720/50p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01
> },      0, 122, 0,  1 }, // AVC High 422 Intra
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01
> }, 472576, 122, 1,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/59.94i
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02
> }, 568832, 122, 1,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/50i
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03
> }, 472576, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/29.97p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04
> }, 568832, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/25p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08
> }, 236544, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 720/59.94p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09
> }, 284672, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 720/50p
> +    {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x40,0x01
> },      0, 244, 0,  1 }, // AVC High 444 Intra
>      {{
> 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x50,0x01
> },      0,  44, 0, -1 }, // AVC CAVLC 444
>  };
>
> @@ -2168,37 +2228,66 @@ static int mxf_parse_h264_frame(AVFormatContext
> *s, AVStream *st,
>  {
>      MXFContext *mxf = s->priv_data;
>      MXFStreamContext *sc = st->priv_data;
> -    AVCodecParameters *par = st->codecpar;
> -    static const int mxf_h264_num_codec_uls = sizeof(mxf_h264_codec_uls)
> / sizeof(mxf_h264_codec_uls[0]);
> -    const uint8_t *buf = pkt->data;
> -    const uint8_t *buf_end = pkt->data + pkt->size;
> -    uint32_t state = -1;
> -    int long_gop = 0; // assume intra when there is no SPS header
> +    int i, j, frame_size, ret, slice_type, intra_only = 0;
> +    H2645Packet hpkt = { 0 };
> +    H264ParamSets ps = { { 0 } };
>      int extra_size = 512; // support AVC Intra files without SPS/PPS
> header
> -    int i, frame_size;
> -    uint8_t uid_found;
>
> -    if (pkt->size > extra_size)
> -        buf_end -= pkt->size - extra_size; // no need to parse beyond
> SPS/PPS header
> +    ret = avpriv_h2645_packet_split(&hpkt, pkt->data, pkt->size,
> (AVCodecContext*)s, 0, 2, AV_CODEC_ID_H264, 1, 0);
> +    if (ret < 0)
> +        return 0;
>
> -    for (;;) {
> -        buf = avpriv_find_start_code(buf, buf_end, &state);
> -        if (buf >= buf_end)
> -            break;
> -        --buf;
> -        switch (state & 0x1f) {
> +    for (i = 0; i < hpkt.nb_nals; i++) {
> +        H2645NAL *nal = &hpkt.nals[i];
> +        switch (nal->type) {
>          case H264_NAL_SPS:
> -            par->profile = buf[1];
> -            long_gop = buf[2] & 0x10 ? 0 : 1; // constraint_set3_flag
> signals intra
>              e->flags |= 0x40;
> +
> +            if (ps.sps != NULL)
> +                break;
> +
> +            ret = avpriv_h264_decode_seq_parameter_set(&nal->gb,
> (AVCodecContext*)s, &ps, 0);
> +            if (ret < 0)
> +                return ret;
> +            for (j = 0; j < MAX_SPS_COUNT; j++) {
> +                if (ps.sps_list[j] != NULL) {
> +                    ps.sps = (SPS*)ps.sps_list[j]->data;
> +                    break;
> +                }
> +            }
> +
> +            sc->aspect_ratio.num = st->codecpar->width * ps.sps->sar.num;
> +            sc->aspect_ratio.den = st->codecpar->height * ps.sps->sar.den;
> +            av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
> +                      sc->aspect_ratio.num, sc->aspect_ratio.den,
> 1024*1024);
> +            intra_only = (ps.sps->constraint_set_flags >> 3) & 1;
> +            sc->interlaced = !ps.sps->frame_mbs_only_flag;
> +            sc->component_depth = ps.sps->bit_depth_luma;
>              break;
>          case H264_NAL_PPS:
>              if (e->flags & 0x40) { // sequence header present
>                  e->flags |= 0x80; // random access
>                  extra_size = 0;
> -                buf = buf_end;
>              }
>              break;
> +        case H264_NAL_IDR_SLICE:
> +            e->flags |= 0x04; // IDR Picture
> +            break;
> +        case H264_NAL_SLICE:
> +            get_ue_golomb_long(&nal->gb); // skip first_mb_in_slice
> +            slice_type = get_ue_golomb_31(&nal->gb);
> +            switch (avpriv_h264_golomb_to_pict_type[slice_type % 5]) {
> +            case AV_PICTURE_TYPE_B:
> +                e->flags |= 0x30; // B Picture
> +                e->flags |= 0x03; // non-referenced B Picture
> +                break;
> +            case AV_PICTURE_TYPE_P:
> +                e->flags |= 0x20; // P Picture
> +                e->flags |= 0x06; // P Picture
> +                break;
> +            default:
> +                break;
> +            }
>          default:
>              break;
>          }
> @@ -2207,27 +2296,33 @@ static int mxf_parse_h264_frame(AVFormatContext
> *s, AVStream *st,
>      if (mxf->header_written)
>          return 1;
>
> -    sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for
> broadcast HD
> -    sc->interlaced = par->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
> -
> -    uid_found = 0;
> +    if (!ps.sps)
> +        sc->interlaced = st->codecpar->field_order !=
> AV_FIELD_PROGRESSIVE ? 1 : 0;
> +    sc->codec_ul = NULL;
>      frame_size = pkt->size + extra_size;
> -    for (i = 0; i < mxf_h264_num_codec_uls; i++) {
> +    for (i = 0; i < FF_ARRAY_ELEMS(mxf_h264_codec_uls); i++) {
>          if (frame_size == mxf_h264_codec_uls[i].frame_size &&
> sc->interlaced == mxf_h264_codec_uls[i].interlaced) {
>              sc->codec_ul = &mxf_h264_codec_uls[i].uid;
>              sc->component_depth = 10; // AVC Intra is always 10 Bit
> +            sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is
> mandatory for broadcast HD
> +            st->codecpar->profile = mxf_h264_codec_uls[i].profile;
> +            sc->avc_intra = 1;
>              if (sc->interlaced)
>                  sc->field_dominance = 1; // top field first is mandatory
> for AVC Intra
> +            mxf->cbr_index = 1;
>              return 1;
> -        } else if ((mxf_h264_codec_uls[i].profile == par->profile) &&
> -                   ((mxf_h264_codec_uls[i].long_gop < 0) ||
> -                   (mxf_h264_codec_uls[i].long_gop == long_gop))) {
> +        } else if (ps.sps && mxf_h264_codec_uls[i].frame_size == 0 &&
> +                   mxf_h264_codec_uls[i].profile == ps.sps->profile_idc &&
> +                   (mxf_h264_codec_uls[i].intra_only < 0 ||
> +                    mxf_h264_codec_uls[i].intra_only == intra_only)) {
>              sc->codec_ul = &mxf_h264_codec_uls[i].uid;
> -            uid_found = 1;
> +            st->codecpar->profile = ps.sps->profile_idc;
> +            st->codecpar->level = ps.sps->level_idc;
> +            // continue to check for avc intra
>          }
>      }
>
> -    if (!uid_found) {
> +    if (!sc->codec_ul) {
>          av_log(s, AV_LOG_ERROR, "h264 profile not supported\n");
>          return 0;
>      }
> --
> 2.20.1 (Apple Git-117)
>

For RP2027 Class 100 1080/50i I still get the error: frame size does not
match index unit size, 568832 != 0
I used the following command:
ffmpeg -f lavfi -i testsrc=size=1920x1080:rate=50 -vf interlace -c:v
libx264 -pix_fmt yuv422p10 -flags +ildct+ilme -avcintra-class 100
-color_primaries bt709 -color_trc bt709 -colorspace bt709 -x264-params
overscan="crop":videoformat="component":fps=25/1:interlaced=1:tff=1:force-cfr=1
-t 1 avci.mxf

Also I encoded AVC High 422 Intra with the following command:
ffmpeg lavfi -i testsrc=size=1920x1080:rate=50 -c:v libx264 -pix_fmt
yuv422p -x264-params keyint=1 -t 1 avc.mxf
Without your patch MediaInfo shows Format profile: High 4:2:2 Intra@L4.2.
With your patch MediaInfo shows Format profile: High 4:2:2@L4.2 and
Format_Profile_Original: High 4:2:2 Intra@L4.2.
According to the MediaInfo documentation, the additional
"Format_Profile_Original" is shown when two format profile infomations are
found that do not match.

Regards,
Thomas
Baptiste Coudurier April 9, 2019, 10:29 p.m. UTC | #2
Hi Thomas, I hope you are doing well

> On Apr 4, 2019, at 7:27 AM, Thomas Mundt <tmundt75@gmail.com> wrote:
> 
> Hi Baptiste,
> 
> […]
> For RP2027 Class 100 1080/50i I still get the error: frame size does not
> match index unit size, 568832 != 0
> I used the following command:
> ffmpeg -f lavfi -i testsrc=size=1920x1080:rate=50 -vf interlace -c:v
> libx264 -pix_fmt yuv422p10 -flags +ildct+ilme -avcintra-class 100
> -color_primaries bt709 -color_trc bt709 -colorspace bt709 -x264-params
> overscan="crop":videoformat="component":fps=25/1:interlaced=1:tff=1:force-cfr=1
> -t 1 avci.mxf

I see, that’s the switch to CBR index.

> Also I encoded AVC High 422 Intra with the following command:
> ffmpeg lavfi -i testsrc=size=1920x1080:rate=50 -c:v libx264 -pix_fmt
> yuv422p -x264-params keyint=1 -t 1 avc.mxf
> Without your patch MediaInfo shows Format profile: High 4:2:2 Intra@L4.2.
> With your patch MediaInfo shows Format profile: High 4:2:2@L4.2 and
> Format_Profile_Original: High 4:2:2 Intra@L4.2.
> According to the MediaInfo documentation, the additional
> "Format_Profile_Original" is shown when two format profile infomations are
> found that do not match.
> 

Muxer uses ….32.30.01 UID which is High 422 Intra according to specs:

urn:smpte:ul:060e2b34.0401010a.04010202.01323001	LEAF	H.264/MPEG-4 AVC High 422 Intra Profile Unconstrained Coding	Identifies H.264/MPEG-4 AVC High 422 Intra Profile Unconstrained Coding

So I’m not sure what media info is doing here.

— 
Baptiste
Thomas Mundt April 10, 2019, 5:42 p.m. UTC | #3
Hi Baptiste,

Am Mi., 10. Apr. 2019 um 00:29 Uhr schrieb Baptiste Coudurier <
baptiste.coudurier@gmail.com>:

> Hi Thomas, I hope you are doing well
>
> > On Apr 4, 2019, at 7:27 AM, Thomas Mundt <tmundt75@gmail.com> wrote:
> >
> > Hi Baptiste,
> >
> > […]
> > For RP2027 Class 100 1080/50i I still get the error: frame size does not
> > match index unit size, 568832 != 0
> > I used the following command:
> > ffmpeg -f lavfi -i testsrc=size=1920x1080:rate=50 -vf interlace -c:v
> > libx264 -pix_fmt yuv422p10 -flags +ildct+ilme -avcintra-class 100
> > -color_primaries bt709 -color_trc bt709 -colorspace bt709 -x264-params
> >
> overscan="crop":videoformat="component":fps=25/1:interlaced=1:tff=1:force-cfr=1
> > -t 1 avci.mxf
>
> I see, that’s the switch to CBR index.
>

Works with you latest patch.


> > Also I encoded AVC High 422 Intra with the following command:
> > ffmpeg lavfi -i testsrc=size=1920x1080:rate=50 -c:v libx264 -pix_fmt
> > yuv422p -x264-params keyint=1 -t 1 avc.mxf
> > Without your patch MediaInfo shows Format profile: High 4:2:2 Intra@L4.2.
> > With your patch MediaInfo shows Format profile: High 4:2:2@L4.2 and
> > Format_Profile_Original: High 4:2:2 Intra@L4.2.
> > According to the MediaInfo documentation, the additional
> > "Format_Profile_Original" is shown when two format profile infomations
> are
> > found that do not match.
> >
>
> Muxer uses ….32.30.01 UID which is High 422 Intra according to specs:
>
> urn:smpte:ul:060e2b34.0401010a.04010202.01323001        LEAF
> H.264/MPEG-4 AVC High 422 Intra Profile Unconstrained Coding    Identifies
> H.264/MPEG-4 AVC High 422 Intra Profile Unconstrained Coding
>
> So I’m not sure what media info is doing here.
>

I looked a little deeper into MediaInfo code. If the avc subdescriptor is
used, MediaInfo expects that in addition to profile and level, the profile
constraint is also set for intra coding.
Other MXF muxer, e.g. bmxlib, also set the profile constraint in the avc
subdescriptor.

Regards,
Thomas
diff mbox

Patch

diff --git a/libavformat/mxf.h b/libavformat/mxf.h
index 4394450dea..f32124f772 100644
--- a/libavformat/mxf.h
+++ b/libavformat/mxf.h
@@ -48,6 +48,7 @@  enum MXFMetadataSetType {
     EssenceGroup,
     TaggedValue,
     TapeDescriptor,
+    AVCSubDescriptor,
 };
 
 enum MXFFrameLayout {
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index 8c6db94865..1f865a0ad1 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -49,7 +49,10 @@ 
 #include "libavcodec/bytestream.h"
 #include "libavcodec/dnxhddata.h"
 #include "libavcodec/dv_profile.h"
-#include "libavcodec/h264.h"
+#include "libavcodec/golomb.h"
+#include "libavcodec/h264data.h"
+#include "libavcodec/h264_ps.h"
+#include "libavcodec/h2645_parse.h"
 #include "libavcodec/internal.h"
 #include "audiointerleave.h"
 #include "avformat.h"
@@ -99,6 +102,7 @@  typedef struct MXFStreamContext {
     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
+    int avc_intra;
 } MXFStreamContext;
 
 typedef struct MXFContainerEssenceEntry {
@@ -167,6 +171,7 @@  static const struct {
 static void mxf_write_wav_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st);
+static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st);
@@ -310,7 +315,7 @@  static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x10,0x60,0x01 },
       { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
       { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
-      mxf_write_mpegvideo_desc },
+      mxf_write_h264_desc },
     // S436M ANC
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 },
       { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x17,0x01,0x02,0x00 },
@@ -498,6 +503,12 @@  static const MXFLocalTagPair mxf_local_tag_batch[] = {
     { 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 */
+    // Generic Descriptor
+    { 0x8100, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00}}, /* SubDescriptors */
+    // AVC SubDescriptor
+    { 0x8200, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0E,0x00,0x00}}, /* AVC Decoding Delay */
+    { 0x8201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0A,0x00,0x00}}, /* AVC Profile */
+    { 0x8202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x0E,0x04,0x01,0x06,0x06,0x01,0x0D,0x00,0x00}}, /* AVC Level */
     // 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 */
@@ -1126,6 +1137,8 @@  static const UID mxf_aes3_descriptor_key      = { 0x06,0x0E,0x2B,0x34,0x02,0x53,
 static const UID mxf_cdci_descriptor_key      = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x28,0x00 };
 static const UID mxf_generic_sound_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0D,0x01,0x01,0x01,0x01,0x01,0x42,0x00 };
 
+static const UID mxf_avc_subdescriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6E,0x00 };
+
 static int get_trc(UID ul, enum AVColorTransferCharacteristic trc)
 {
     switch (trc){
@@ -1317,6 +1330,13 @@  static int64_t mxf_write_cdci_common(AVFormatContext *s, AVStream *st, const UID
         avio_w8(pb, sc->field_dominance);
     }
 
+    if (st->codecpar->codec_id == AV_CODEC_ID_H264 && !sc->avc_intra) {
+        // write avc sub descriptor ref
+        mxf_write_local_tag(pb, 8 + 16, 0x8100);
+        mxf_write_refs_count(pb, 1);
+        mxf_write_uuid(pb, AVCSubDescriptor, 0);
+    }
+
     return pos;
 }
 
@@ -1329,10 +1349,50 @@  static void mxf_update_klv_size(AVIOContext *pb, int64_t pos)
     avio_seek(pb, cur_pos, SEEK_SET);
 }
 
+static void mxf_write_avc_subdesc(AVFormatContext *s, AVStream *st)
+{
+    AVIOContext *pb = s->pb;
+    int64_t pos;
+
+    avio_write(pb, mxf_avc_subdescriptor_key, 16);
+    klv_encode_ber4_length(pb, 0);
+    pos = avio_tell(pb);
+
+    mxf_write_local_tag(pb, 16, 0x3C0A);
+    mxf_write_uuid(pb, AVCSubDescriptor, 0);
+
+    mxf_write_local_tag(pb, 1, 0x8200);
+    avio_w8(pb, 0xFF); // AVC Decoding Delay, unknown
+
+    mxf_write_local_tag(pb, 1, 0x8201);
+    avio_w8(pb, st->codecpar->profile); // AVC Profile
+
+    mxf_write_local_tag(pb, 1, 0x8202);
+    avio_w8(pb, st->codecpar->level); // AVC Level
+
+    mxf_update_klv_size(s->pb, pos);
+}
+
 static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
 {
     int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key);
     mxf_update_klv_size(s->pb, pos);
+
+    if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
+        mxf_write_avc_subdesc(s, st);
+    }
+}
+
+static void mxf_write_h264_desc(AVFormatContext *s, AVStream *st)
+{
+    MXFStreamContext *sc = st->priv_data;
+    if (sc->avc_intra) {
+        mxf_write_mpegvideo_desc(s, st);
+    } else {
+        int64_t pos = mxf_write_cdci_common(s, st, mxf_cdci_descriptor_key);
+        mxf_update_klv_size(s->pb, pos);
+        mxf_write_avc_subdesc(s, st);
+    }
 }
 
 static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st)
@@ -2136,30 +2196,30 @@  static const struct {
     int frame_size;
     int profile;
     uint8_t interlaced;
-    int long_gop; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored
+    int intra_only; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored
 } mxf_h264_codec_uls[] = {
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 },      0,  66, 0, -1 }, // AVC Baseline, Unconstrained Coding
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 },      0,  66, 0, -1 }, // AVC Baseline
     {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x20,0x01 },      0,  77, 0, -1 }, // AVC Main
     {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x30,0x01 },      0,  88, 0, -1 }, // AVC Extended
     {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x40,0x01 },      0, 100, 0, -1 }, // AVC High
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x50,0x01 },      0, 110, 0,  1 }, // AVC High 10
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x60,0x01 },      0, 122, 0,  1 }, // AVC High 422
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x70,0x01 },      0, 244, 0,  1 }, // AVC High 444
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 },      0, 110, 0,  0 }, // AVC High 10 Intra
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960,   0, 1,  0 }, // AVC Intra 50 1080i60
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088,   0, 1,  0 }, // AVC Intra 50 1080i50
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 232960,   0, 0,  0 }, // AVC Intra 50 1080p30
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, 281088,   0, 0,  0 }, // AVC Intra 50 1080p25
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, 116736,   0, 0,  0 }, // AVC Intra 50 720p60
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, 140800,   0, 0,  0 }, // AVC Intra 50 720p50
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01 },      0, 122, 0,  0 }, // AVC High 422 Intra
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, 472576,   0, 1,  0 }, // AVC Intra 100 1080i60
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, 568832,   0, 1,  0 }, // AVC Intra 100 1080i50
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, 472576,   0, 0,  0 }, // AVC Intra 100 1080p30
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, 568832,   0, 0,  0 }, // AVC Intra 100 1080p25
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, 236544,   0, 0,  0 }, // AVC Intra 100 720p60
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, 284672,   0, 0,  0 }, // AVC Intra 100 720p50
-    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x40,0x01 },      0, 244, 0,  0 }, // AVC High 444 Intra
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x50,0x01 },      0, 110, 0,  0 }, // AVC High 10
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x60,0x01 },      0, 122, 0,  0 }, // AVC High 422
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x70,0x01 },      0, 244, 0,  0 }, // AVC High 444
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 },      0, 110, 0,  1 }, // AVC High 10 Intra
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960, 110, 1,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/59.94i
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088, 110, 1,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/50i
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 232960, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/29.97p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, 281088, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 1080/25p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, 116736, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 720/59.94p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, 140800, 110, 0,  1 }, // AVC High 10 Intra RP2027 Class 50 720/50p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01 },      0, 122, 0,  1 }, // AVC High 422 Intra
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, 472576, 122, 1,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/59.94i
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, 568832, 122, 1,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/50i
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, 472576, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/29.97p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, 568832, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 1080/25p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, 236544, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 720/59.94p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, 284672, 122, 0,  1 }, // AVC High 422 Intra RP2027 Class 100 720/50p
+    {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x40,0x01 },      0, 244, 0,  1 }, // AVC High 444 Intra
     {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0d,0x04,0x01,0x02,0x02,0x01,0x32,0x50,0x01 },      0,  44, 0, -1 }, // AVC CAVLC 444
 };
 
@@ -2168,37 +2228,66 @@  static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
 {
     MXFContext *mxf = s->priv_data;
     MXFStreamContext *sc = st->priv_data;
-    AVCodecParameters *par = st->codecpar;
-    static const int mxf_h264_num_codec_uls = sizeof(mxf_h264_codec_uls) / sizeof(mxf_h264_codec_uls[0]);
-    const uint8_t *buf = pkt->data;
-    const uint8_t *buf_end = pkt->data + pkt->size;
-    uint32_t state = -1;
-    int long_gop = 0; // assume intra when there is no SPS header
+    int i, j, frame_size, ret, slice_type, intra_only = 0;
+    H2645Packet hpkt = { 0 };
+    H264ParamSets ps = { { 0 } };
     int extra_size = 512; // support AVC Intra files without SPS/PPS header
-    int i, frame_size;
-    uint8_t uid_found;
 
-    if (pkt->size > extra_size)
-        buf_end -= pkt->size - extra_size; // no need to parse beyond SPS/PPS header
+    ret = avpriv_h2645_packet_split(&hpkt, pkt->data, pkt->size, (AVCodecContext*)s, 0, 2, AV_CODEC_ID_H264, 1, 0);
+    if (ret < 0)
+        return 0;
 
-    for (;;) {
-        buf = avpriv_find_start_code(buf, buf_end, &state);
-        if (buf >= buf_end)
-            break;
-        --buf;
-        switch (state & 0x1f) {
+    for (i = 0; i < hpkt.nb_nals; i++) {
+        H2645NAL *nal = &hpkt.nals[i];
+        switch (nal->type) {
         case H264_NAL_SPS:
-            par->profile = buf[1];
-            long_gop = buf[2] & 0x10 ? 0 : 1; // constraint_set3_flag signals intra
             e->flags |= 0x40;
+
+            if (ps.sps != NULL)
+                break;
+
+            ret = avpriv_h264_decode_seq_parameter_set(&nal->gb, (AVCodecContext*)s, &ps, 0);
+            if (ret < 0)
+                return ret;
+            for (j = 0; j < MAX_SPS_COUNT; j++) {
+                if (ps.sps_list[j] != NULL) {
+                    ps.sps = (SPS*)ps.sps_list[j]->data;
+                    break;
+                }
+            }
+
+            sc->aspect_ratio.num = st->codecpar->width * ps.sps->sar.num;
+            sc->aspect_ratio.den = st->codecpar->height * ps.sps->sar.den;
+            av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den,
+                      sc->aspect_ratio.num, sc->aspect_ratio.den, 1024*1024);
+            intra_only = (ps.sps->constraint_set_flags >> 3) & 1;
+            sc->interlaced = !ps.sps->frame_mbs_only_flag;
+            sc->component_depth = ps.sps->bit_depth_luma;
             break;
         case H264_NAL_PPS:
             if (e->flags & 0x40) { // sequence header present
                 e->flags |= 0x80; // random access
                 extra_size = 0;
-                buf = buf_end;
             }
             break;
+        case H264_NAL_IDR_SLICE:
+            e->flags |= 0x04; // IDR Picture
+            break;
+        case H264_NAL_SLICE:
+            get_ue_golomb_long(&nal->gb); // skip first_mb_in_slice
+            slice_type = get_ue_golomb_31(&nal->gb);
+            switch (avpriv_h264_golomb_to_pict_type[slice_type % 5]) {
+            case AV_PICTURE_TYPE_B:
+                e->flags |= 0x30; // B Picture
+                e->flags |= 0x03; // non-referenced B Picture
+                break;
+            case AV_PICTURE_TYPE_P:
+                e->flags |= 0x20; // P Picture
+                e->flags |= 0x06; // P Picture
+                break;
+            default:
+                break;
+            }
         default:
             break;
         }
@@ -2207,27 +2296,33 @@  static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st,
     if (mxf->header_written)
         return 1;
 
-    sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD
-    sc->interlaced = par->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
-
-    uid_found = 0;
+    if (!ps.sps)
+        sc->interlaced = st->codecpar->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0;
+    sc->codec_ul = NULL;
     frame_size = pkt->size + extra_size;
-    for (i = 0; i < mxf_h264_num_codec_uls; i++) {
+    for (i = 0; i < FF_ARRAY_ELEMS(mxf_h264_codec_uls); i++) {
         if (frame_size == mxf_h264_codec_uls[i].frame_size && sc->interlaced == mxf_h264_codec_uls[i].interlaced) {
             sc->codec_ul = &mxf_h264_codec_uls[i].uid;
             sc->component_depth = 10; // AVC Intra is always 10 Bit
+            sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD
+            st->codecpar->profile = mxf_h264_codec_uls[i].profile;
+            sc->avc_intra = 1;
             if (sc->interlaced)
                 sc->field_dominance = 1; // top field first is mandatory for AVC Intra
+            mxf->cbr_index = 1;
             return 1;
-        } else if ((mxf_h264_codec_uls[i].profile == par->profile) &&
-                   ((mxf_h264_codec_uls[i].long_gop < 0) ||
-                   (mxf_h264_codec_uls[i].long_gop == long_gop))) {
+        } else if (ps.sps && mxf_h264_codec_uls[i].frame_size == 0 &&
+                   mxf_h264_codec_uls[i].profile == ps.sps->profile_idc &&
+                   (mxf_h264_codec_uls[i].intra_only < 0 ||
+                    mxf_h264_codec_uls[i].intra_only == intra_only)) {
             sc->codec_ul = &mxf_h264_codec_uls[i].uid;
-            uid_found = 1;
+            st->codecpar->profile = ps.sps->profile_idc;
+            st->codecpar->level = ps.sps->level_idc;
+            // continue to check for avc intra
         }
     }
 
-    if (!uid_found) {
+    if (!sc->codec_ul) {
         av_log(s, AV_LOG_ERROR, "h264 profile not supported\n");
         return 0;
     }