@ Michael: Sorry, I`m subscribed now. CODEC_ID_H264 changed. @ Kieran: Maybe this would make sense as an option. But in a future step. :-)
@ Tomas:Thanks for your suggestions!The component_depth part was taken from Michael´s patch last month. But it also can be changed to 10 bit fixed for AVCI. Here is the new patch: --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -42,6 +42,8 @@ #include "libavutil/time_internal.h" #include "libavcodec/bytestream.h" #include "libavcodec/dnxhddata.h" +#include "libavcodec/h264.h" +#include "libavcodec/internal.h" #include "audiointerleave.h" #include "avformat.h" #include "avio_internal.h" @@ -98,6 +100,7 @@ { AV_CODEC_ID_DVVIDEO, 15 }, { AV_CODEC_ID_DNXHD, 24 }, { AV_CODEC_ID_JPEG2000, 34 }, + { AV_CODEC_ID_H264, 35 }, { AV_CODEC_ID_NONE } }; @@ -274,6 +277,11 @@ { 0x06,0x0e,0x2b,0x34,0x01,0x02,0x01,0x01,0x0d,0x01,0x03,0x01,0x15,0x01,0x08,0x00 }, { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, mxf_write_cdci_desc }, + // H.264 + { { 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 }, { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, @@ -989,17 +997,21 @@ MXFStreamContext *sc = st->priv_data; int profile_and_level = (st->codec->profile<<4) | st->codec->level; - mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5); + if (st->codec->codec_id != AV_CODEC_ID_H264) { + mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5); - // bit rate - mxf_write_local_tag(pb, 4, 0x8000); - avio_wb32(pb, sc->video_bit_rate); - - // profile and level - mxf_write_local_tag(pb, 1, 0x8007); - if (!st->codec->profile) - profile_and_level |= 0x80; // escape bit - avio_w8(pb, profile_and_level); + // bit rate + mxf_write_local_tag(pb, 4, 0x8000); + avio_wb32(pb, sc->video_bit_rate); + + // profile and level + mxf_write_local_tag(pb, 1, 0x8007); + if (!st->codec->profile) + profile_and_level |= 0x80; // escape bit + avio_w8(pb, profile_and_level); + } + else + mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 0); } static void mxf_write_generic_sound_common(AVFormatContext *s, AVStream *st, const UID key, unsigned size) @@ -1572,6 +1584,88 @@ return 1; } +static const struct { + UID uid; + int frame_size; + int profile; + uint8_t interlaced; +} mxf_h264_codec_uls[] = { + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, 232960, 0, 1 }, // AVC Intra 50 1080i60 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, 281088, 0, 1 }, // AVC Intra 50 1080i50 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, 232960, 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 }, // AVC Intra 50 1080p25 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, 116736, 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 }, // AVC Intra 50 720p50 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, 472576, 0, 1 }, // AVC Intra 100 1080i60 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, 568832, 0, 1 }, // AVC Intra 100 1080i50 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, 472576, 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 }, // AVC Intra 100 1080p25 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, 236544, 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 }, // AVC Intra 100 720p50 + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x01 }, 0, 110, 0 }, // AVC High 10 Intra + {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x01 }, 0, 122, 0 }, // AVC High 422 Intra +}; + +static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st, + AVPacket *pkt, MXFIndexEntry *e) +{ + MXFContext *mxf = s->priv_data; + MXFStreamContext *sc = st->priv_data; + 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; + uint32_t frame_size = pkt->size; + uint32_t extra_size = 512; // support AVC Intra files without SPS/PPS header + int i; + + if (pkt->size > extra_size) + buf_end -= pkt->size - extra_size; // no need to parse beyond SPS/PPS header + + for (;;) { + buf = avpriv_find_start_code(buf, buf_end, &state); + if (buf >= buf_end) + break; + --buf; + switch (state & 0x1f) { + case NAL_SPS: + st->codec->profile = buf[1]; + e->flags |= 0x40; + break; + case NAL_PPS: + if (e->flags & 0x40) { // sequence header present + e->flags |= 0x80; // random access + extra_size = 0; + buf = buf_end; + } + break; + default: + break; + } + } + + if (mxf->header_written) + return 1; + + sc->aspect_ratio = (AVRational){ 16, 9 }; // 16:9 is mandatory for broadcast HD + sc->component_depth = 10; // AVC Intra is always 10 Bit + sc->interlaced = st->codec->field_order != AV_FIELD_PROGRESSIVE ? 1 : 0; + if (sc->interlaced) + sc->field_dominance = 1; // top field first is mandatory for AVC Intra + + for (i = 0; i < mxf_h264_num_codec_uls; i++) { + if (((frame_size + extra_size) == mxf_h264_codec_uls[i].frame_size && + sc->interlaced == mxf_h264_codec_uls[i].interlaced) || + st->codec->profile == mxf_h264_codec_uls[i].profile) { + sc->codec_ul = &mxf_h264_codec_uls[i].uid; + return 1; + } + } + + av_log(s, AV_LOG_ERROR, "AVC Intra 50/100 supported only\n"); + return 0; +} + static const UID mxf_mpeg2_codec_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x10,0x00 }, // MP-ML I-Frame { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, // MP-ML Long GOP @@ -1976,6 +2070,11 @@ } else if (st->codec->codec_id == AV_CODEC_ID_DVVIDEO) { if (!mxf_parse_dv_frame(s, st, pkt)) { av_log(s, AV_LOG_ERROR, "could not get dv profile\n"); + return -1; + } + } else if (st->codec->codec_id == AV_CODEC_ID_H264) { + if (!mxf_parse_h264_frame(s, st, pkt, &ie)) { + av_log(s, AV_LOG_ERROR, "could not get h264 profile\n"); return -1; } } _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel