From: Baptiste Coudurier <baptiste.coudur...@gmail.com> Ported by michael from ffmbc to ffmpeg the code is under CONFIG_GPL as ffmbc is GPL
Signed-off-by: Michael Niedermayer <michae...@gmx.at> --- libavformat/mxfenc.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index 6a6b7c2..98f3479 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -40,6 +40,8 @@ #include "libavutil/avassert.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" @@ -95,6 +97,9 @@ static const struct { { AV_CODEC_ID_PCM_S16LE, 1 }, { AV_CODEC_ID_DVVIDEO, 15 }, { AV_CODEC_ID_DNXHD, 24 }, +#if CONFIG_GPL + { AV_CODEC_ID_H264, 34 }, +#endif { AV_CODEC_ID_NONE } }; @@ -266,6 +271,13 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { { 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,0x71,0x13,0x00,0x00 }, mxf_write_cdci_desc }, +#if CONFIG_GPL + // H.264 + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,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,0x03,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 }, + mxf_write_mpegvideo_desc }, +#endif // CONFIG_GPL { { 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 }, @@ -1564,6 +1576,130 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) return 1; } +#if CONFIG_GPL +static const UID mxf_h264_codec_uls[] = { + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x30,0x00,0x00 }, // AVC Video + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, // AVC Intra + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x20,0x00 }, // AVC High 10 Intra + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x01 }, // AVC High 10 Intra RP2027 Class 50 1080/59.94i + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x02 }, // AVC High 10 Intra RP2027 Class 50 1080/50i + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x03 }, // AVC High 10 Intra RP2027 Class 50 1080/29.97p + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x04 }, // AVC High 10 Intra RP2027 Class 50 1080/25p + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x08 }, // AVC High 10 Intra RP2027 Class 50 720/59.94p + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x21,0x09 }, // AVC High 10 Intra RP2027 Class 50 720/50p + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x30,0x00 }, // AVC High 422 Intra + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x01 }, // AVC High 422 Intra RP2027 Class 100 1080/59.94i + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x02 }, // AVC High 422 Intra RP2027 Class 100 1080/50i + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x03 }, // AVC High 422 Intra RP2027 Class 100 1080/29.97p + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x04 }, // AVC High 422 Intra RP2027 Class 100 1080/25p + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x08 }, // AVC High 422 Intra RP2027 Class 100 720/59.94p + { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x32,0x31,0x09 }, // AVC High 422 Intra RP2027 Class 100 720/50p +}; + +static const UID *mxf_get_h264_codec_ul(AVCodecContext *avctx, SPS *sps) +{ + int long_gop = avctx->gop_size > 1 || avctx->has_b_frames; + + if ((sps->constraint_set_flags >> 3) & 1) { + if (sps->profile_idc == 110) + return &mxf_h264_codec_uls[2]; + else if (sps->profile_idc == 122) + return &mxf_h264_codec_uls[9]; + } + if (long_gop) + return &mxf_h264_codec_uls[0]; + else + return &mxf_h264_codec_uls[1]; +} + +static int mxf_parse_h264_frame(AVFormatContext *s, AVStream *st, + AVPacket *pkt, MXFIndexEntry *e) +{ + MXFStreamContext *sc = st->priv_data; + H264Context h; + const uint8_t *buf = pkt->data; + const uint8_t *buf_end = pkt->data + pkt->size; + uint32_t state = -1; + AVRational sar = {1, 1}; + + if (pkt->size < 5 || AV_RB32(pkt->data) != 0x0000001) { + av_log(s, AV_LOG_ERROR, "h264 bitstream malformated, " + "no startcode found, use -vbsf h264_mp4toannexb\n"); + return 0; + } + + memset(&h, 0, sizeof(h)); + h.avctx = st->codec; + h.thread_context[0] = &h; + h.prev_frame_num = -1; + + for (;;) { + int src_length, dst_length, consumed; + const uint8_t *ptr; + + buf = avpriv_find_start_code(buf, buf_end, &state); + if (buf >= buf_end) + break; + --buf; + src_length = buf_end - buf; + switch (state & 0x1f) { + case NAL_SLICE: + case NAL_IDR_SLICE: + // Do not walk the whole buffer just to decode slice header + if (src_length > 20) + src_length = 20; + break; + } + + ptr = ff_h264_decode_nal(&h, buf, &dst_length, &consumed, src_length); + if (!ptr || dst_length < 0) + break; + + init_get_bits(&h.gb, ptr, 8*dst_length); + //av_log(avctx, AV_LOG_DEBUG, "nal_unit_type:%d\n", h.nal_unit_type); + switch (h.nal_unit_type) { + case NAL_SPS: + ff_h264_decode_seq_parameter_set(&h); + if (h.sps.sar.num > 0 && h.sps.sar.den > 0) { + sar.num = st->codec->width * h.sps.sar.num; + sar.den = st->codec->height * h.sps.sar.den; + } + sc->aspect_ratio.num = st->codec->width * sar.num; + sc->aspect_ratio.den = st->codec->height * sar.den; + av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, + sar.num, sar.den, 1024*1024); + + sc->interlaced = !h.sps.frame_mbs_only_flag; + sc->component_depth = h.sps.bit_depth_luma; + + sc->codec_ul = mxf_get_h264_codec_ul(st->codec, &h.sps); + e->flags |= 0x40; + break; + case NAL_PPS: + ff_h264_decode_picture_parameter_set(&h, h.gb.size_in_bits); + if (h.sps.timing_info_present_flag) { + if (st->codec->time_base.num != h.sps.num_units_in_tick || + st->codec->time_base.den*2 != h.sps.time_scale) { + av_log(s, AV_LOG_ERROR, "framerate does not match bitstream values: %d/%d != %d/%d\n", + h.sps.num_units_in_tick, h.sps.time_scale, st->codec->time_base.num, st->codec->time_base.den*2); + return 0; + } + } + if (e->flags & 0x40) // sequence header present + e->flags |= 0x80; // random access + break; + case NAL_IDR_SLICE: + break; + case NAL_SLICE: + av_log(s, AV_LOG_ERROR, "mxf muxer only supports AVC Intra currently\n"); + return 0; + } + } + + return !!sc->codec_ul; +} +#endif // CONFIG_GPL + 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 @@ -1969,6 +2105,13 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "could not get dv profile\n"); return -1; } +#if CONFIG_GPL + } 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 and level\n"); + return -1; + } +#endif // CONFIG_GPL } if (!mxf->header_written) { -- 1.7.9.5 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel