[FFmpeg-devel] [PATCH 1/3] avformat/mxfenc: H.264 Intra support
Michael Niedermayer
michaelni at gmx.at
Sat Sep 13 12:36:04 CEST 2014
From: Baptiste Coudurier <baptiste.coudurier at gmail.com>
Ported by michael from ffmbc to ffmpeg
the code is under CONFIG_GPL as ffmbc is GPL
Signed-off-by: Michael Niedermayer <michaelni at 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
More information about the ffmpeg-devel
mailing list