diff mbox

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

Message ID 20190328155036.7738-1-baptiste.coudurier@gmail.com
State New
Headers show

Commit Message

Baptiste Coudurier March 28, 2019, 3:50 p.m. UTC
---
 libavformat/mxf.h    |   1 +
 libavformat/mxfenc.c | 194 ++++++++++++++++++++++++++++++++-----------
 2 files changed, 145 insertions(+), 50 deletions(-)

Comments

Michael Niedermayer March 28, 2019, 6:08 p.m. UTC | #1
On Thu, Mar 28, 2019 at 08:50:36AM -0700, Baptiste Coudurier wrote:
> ---
>  libavformat/mxf.h    |   1 +
>  libavformat/mxfenc.c | 194 ++++++++++++++++++++++++++++++++-----------
>  2 files changed, 145 insertions(+), 50 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..b2e818a8a5 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,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,  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,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 = ff_h2645_packet_split(&hpkt, pkt->data, pkt->size, (AVCodecContext*)s, 0, 2, AV_CODEC_ID_H264, 1);

this needs to be updated due to

992532ee3122d7938a7581988eea401b57de8189

otherwise it fails to build

CC	libavformat/mxfenc.o
libavformat/mxfenc.c: In function ‘mxf_parse_h264_frame’:
libavformat/mxfenc.c:2236:5: error: too few arguments to function ‘ff_h2645_packet_split’
     ret = ff_h2645_packet_split(&hpkt, pkt->data, pkt->size, (AVCodecContext*)s, 0, 2, AV_CODEC_ID_H264, 1);
     ^
In file included from ./libavcodec/h264dec.h:40:0,
                 from ./libavcodec/h264data.h:24,
                 from libavformat/mxfenc.c:53:
./libavcodec/h2645_parse.h:103:5: note: declared here
 int ff_h2645_packet_split(H2645Packet *pkt, const uint8_t *buf, int length,
     ^
make: *** [libavformat/mxfenc.o] Error 1
make: Target `all' not remade because of errors.

[...]
Tomas Härdin March 29, 2019, 9:41 a.m. UTC | #2
tor 2019-03-28 klockan 08:50 -0700 skrev Baptiste Coudurier:
> ---
>  libavformat/mxf.h    |   1 +
>  libavformat/mxfenc.c | 194 ++++++++++++++++++++++++++++++++-----------
>  2 files changed, 145 insertions(+), 50 deletions(-)
> 
> diff --git a/libavformat/mxf.h b/libavformat/mxf.h
> index 4394450dea..f32124f772 100644
> --- a/libavformat/mxf.h
> +++ b/libavformat/mxf.h
> @@ -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);
> +    }

Should this always be written for long gop AVC? Not just XAVC? Same
goes for mxf_write_avc_subdesc() I think, unless I'm reading this incorrectly..

>  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

Any particular reason for inverting this logic? Leaving it as is would
make the patch smaller..

/Tomas
Baptiste Coudurier March 29, 2019, 3:30 p.m. UTC | #3
Hey Tomas, I hope you are doing well

> On Mar 29, 2019, at 2:41 AM, Tomas Härdin <tjoppen@acc.umu.se> wrote:
> 
> tor 2019-03-28 klockan 08:50 -0700 skrev Baptiste Coudurier:
>> ---
>>  libavformat/mxf.h    |   1 +
>>  libavformat/mxfenc.c | 194 ++++++++++++++++++++++++++++++++-----------
>>  2 files changed, 145 insertions(+), 50 deletions(-)
>> 
>> diff --git a/libavformat/mxf.h b/libavformat/mxf.h
>> index 4394450dea..f32124f772 100644
>> --- a/libavformat/mxf.h
>> +++ b/libavformat/mxf.h
>> @@ -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);
>> +    }
> 
> Should this always be written for long gop AVC? Not just XAVC? Same
> goes for mxf_write_avc_subdesc() I think, unless I'm reading this incorrectly..

The code will write always write it for AV_CODEC_ID_H264 except if it is avc_intra (it uses the legacy mpegvideo desc),
so it will always be written for long gop as well. There is no check for XAVC technically.

>>  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
> 
> Any particular reason for inverting this logic? Leaving it as is would
> make the patch smaller..
> 
> /Tomas

Checking long gop looks weird to me since the specs don’t make that distinction, they do however make the explicit distinction for intra only
profile, so it feels more intuitive to mark them intra only. No strong opinion though.

Thanks a lot!

—
Baptiste Coudurier
Thomas Mundt March 29, 2019, 8:11 p.m. UTC | #4
Am Do., 28. März 2019 um 16:51 Uhr schrieb Baptiste Coudurier <
baptiste.coudurier@gmail.com>:

> ---
>  libavformat/mxf.h    |   1 +
>  libavformat/mxfenc.c | 194 ++++++++++++++++++++++++++++++++-----------
>  2 files changed, 145 insertions(+), 50 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..b2e818a8a5 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,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,  0 }, // AVC High 10 Intra
>

AVC High 10 Intra is not changed to intra_only.


> -    {{
> 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,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
>

Maybe i miss something, but doesn´t the setting of the profile for all AVC
Intra codec ULs make the for-loop to always select the last AVC Intra
codec UL (720/50p) for AVC High 422 Intra?

-    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].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
>          }
>      }
>

Regards,
Thomas
Baptiste Coudurier March 30, 2019, 4:52 p.m. UTC | #5
Hi Thomas,

> On Mar 29, 2019, at 1:11 PM, Thomas Mundt <tmundt75@gmail.com> wrote:
> 
>
> […]
>
>> 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
>> 
> 
> Maybe i miss something, but doesn´t the setting of the profile for all AVC
> Intra codec ULs make the for-loop to always select the last AVC Intra
> codec UL (720/50p) for AVC High 422 Intra?

The frame size check prevents that.

—
Baptiste Coudurier
Tomas Härdin April 1, 2019, 9:26 a.m. UTC | #6
fre 2019-03-29 klockan 08:30 -0700 skrev Baptiste Coudurier:
> Hey Tomas, I hope you are doing well
> 
> > > > On Mar 29, 2019, at 2:41 AM, Tomas Härdin <tjoppen@acc.umu.se> wrote:
> > 
> > tor 2019-03-28 klockan 08:50 -0700 skrev Baptiste Coudurier:
> > > ---
> > >  libavformat/mxf.h    |   1 +
> > >  libavformat/mxfenc.c | 194 ++++++++++++++++++++++++++++++++-----------
> > >  2 files changed, 145 insertions(+), 50 deletions(-)
> > > 
> > > diff --git a/libavformat/mxf.h b/libavformat/mxf.h
> > > index 4394450dea..f32124f772 100644
> > > --- a/libavformat/mxf.h
> > > +++ b/libavformat/mxf.h
> > > @@ -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);
> > > +    }
> > 
> > Should this always be written for long gop AVC? Not just XAVC? Same
> > goes for mxf_write_avc_subdesc() I think, unless I'm reading this incorrectly..
> 
> The code will write always write it for AV_CODEC_ID_H264 except if it is avc_intra (it uses the legacy mpegvideo desc),
> so it will always be written for long gop as well. There is no check for XAVC technically.
> 
> > >  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
> > 
> > Any particular reason for inverting this logic? Leaving it as is would
> > make the patch smaller..
> > 
> > /Tomas
> 
> Checking long gop looks weird to me since the specs don’t make that distinction, they do however make the explicit distinction for intra only
> profile, so it feels more intuitive to mark them intra only. No strong opinion though.

I guess that's fair. If I were feeling super-nitpicky I'd suggest
putting the flip in a separate patch

/Tomas
Thomas Mundt April 1, 2019, 11:10 p.m. UTC | #7
Am Sa., 30. März 2019 um 17:52 Uhr schrieb Baptiste Coudurier <
baptiste.coudurier@gmail.com>:

> Hi Thomas,
>
> > On Mar 29, 2019, at 1:11 PM, Thomas Mundt <tmundt75@gmail.com> wrote:
> >
> >
> > […]
> >
> >>
> 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
> >>
> >
> > Maybe i miss something, but doesn´t the setting of the profile for all
> AVC
> > Intra codec ULs make the for-loop to always select the last AVC Intra
> > codec UL (720/50p) for AVC High 422 Intra?
>
> The frame size check prevents that.
>

The frame size check in the first condition of the for-loop works for fixed
frame size RP2027. However, with free frame size AVC High 422 Intra, the
second condition in the for-loop only checks for profile and intra-only.
Since the second condition doesn´t break the for-loop, the last UL with
matching profile and intra-only flag is set.

I wanted to test this behavior, so I applied this patch to
cf81284b1c14ef28d3f94e6d28c46188ba4e82f2, which is the last one that can be
compiled.
Unfortunately I was not able to produce any h264 mxf with this patch.
E.g. the following command works perfect without this patch:
ffmpeg -f lavfi -i testsrc=size=3840x2160:rate=50 -c:v libx264 -pix_fmt
yuv422p10 -x264-params keyint=1 -t 1 avc.mxf
With this patch I get errors: h264 profile not supported, could not get
h264 profile.
Same with other formats or long gop.
RP2027 Class 100 1080/50i shows the following error: frame size does not
match index unit size, 568832 != 0

Regards,
Thomas
Baptiste Coudurier April 3, 2019, 9:24 a.m. UTC | #8
Hi Thomas,

> On Apr 1, 2019, at 4:10 PM, Thomas Mundt <tmundt75@gmail.com> wrote:
> 
> Am Sa., 30. März 2019 um 17:52 Uhr schrieb Baptiste Coudurier <
> baptiste.coudurier@gmail.com <mailto:baptiste.coudurier@gmail.com>>:
> 
>> Hi Thomas,
>> 
>>> On Mar 29, 2019, at 1:11 PM, Thomas Mundt <tmundt75@gmail.com> wrote:
>>> 
>>> 
>>> […]
>>> 
>>>> 
>> 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
>>>> 
>>> 
>>> Maybe i miss something, but doesn´t the setting of the profile for all
>> AVC
>>> Intra codec ULs make the for-loop to always select the last AVC Intra
>>> codec UL (720/50p) for AVC High 422 Intra?
>> 
>> The frame size check prevents that.
>> 
> 
> The frame size check in the first condition of the for-loop works for fixed
> frame size RP2027. However, with free frame size AVC High 422 Intra, the
> second condition in the for-loop only checks for profile and intra-only.
> Since the second condition doesn´t break the for-loop, the last UL with
> matching profile and intra-only flag is set.
> 
> I wanted to test this behavior, so I applied this patch to
> cf81284b1c14ef28d3f94e6d28c46188ba4e82f2, which is the last one that can be
> compiled.
> Unfortunately I was not able to produce any h264 mxf with this patch.
> E.g. the following command works perfect without this patch:
> ffmpeg -f lavfi -i testsrc=size=3840x2160:rate=50 -c:v libx264 -pix_fmt
> yuv422p10 -x264-params keyint=1 -t 1 avc.mxf
> With this patch I get errors: h264 profile not supported, could not get
> h264 profile.
> Same with other formats or long gop.
> RP2027 Class 100 1080/50i shows the following error: frame size does not
> match index unit size, 568832 != 0


Right, a few things have changed in the muxer in the mean time. I updated the patch and sent it.

Thanks a lot!

—
Baptiste
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..b2e818a8a5 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,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,  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,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 = ff_h2645_packet_split(&hpkt, pkt->data, pkt->size, (AVCodecContext*)s, 0, 2, AV_CODEC_ID_H264, 1);
+    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 (sc->aspect_ratio.den != 0)
+                break;
+
+            ret = ff_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 (ff_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,32 @@  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].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;
     }