[FFmpeg-cvslog] avformat/mxfenc: AVC Intra support

Thomas Mundt git at videolan.org
Wed Oct 29 12:26:07 CET 2014


ffmpeg | branch: master | Thomas Mundt <loudmax-at-yahoo.de at ffmpeg.org> | Tue Oct 28 22:38:22 2014 +0000| [2114e8843256f6c1d5a3c450f8ed19cd8fbdcdd5] | committer: Michael Niedermayer

avformat/mxfenc: AVC Intra support

To keep h264 parsing simple and fast, I used the framesize for selecting the right Panasonic codec label. The framesize is fixed for Panasonic AVC Intra.

This patch only supports AVCI50/100. But in all flavours, i.e. with no SPS/PPS in header.

Reviewed-by: tomas.hardin at codemill.se
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=2114e8843256f6c1d5a3c450f8ed19cd8fbdcdd5
---

 libavformat/mxfenc.c |  106 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)

diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index ac05677..d05b696 100644
--- 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 @@ static const struct {
     { 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 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
       { 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,6 +997,7 @@ static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
     MXFStreamContext *sc = st->priv_data;
     int profile_and_level = (st->codec->profile<<4) | st->codec->level;
 
+    if (st->codec->codec_id != AV_CODEC_ID_H264) {
     mxf_write_cdci_common(s, st, mxf_mpegvideo_descriptor_key, 8+5);
 
     // bit rate
@@ -1000,6 +1009,9 @@ static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
     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,95 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
     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,0x20,0x01 },      0, 110, 0 }, // AVC High 10 Intra
+    {{ 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,0x30,0x01 },      0, 122, 0 }, // AVC High 422 Intra
+    {{ 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
+};
+
+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;
+    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
+
+    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
+
+    uid_found = 0;
+    frame_size = pkt->size + extra_size;
+    for (i = 0; i < mxf_h264_num_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;
+            return 1;
+        } else if (st->codec->profile == mxf_h264_codec_uls[i].profile) {
+            sc->codec_ul = &mxf_h264_codec_uls[i].uid;
+            uid_found = 1;
+        }
+    }
+
+    if (!uid_found) {
+        av_log(s, AV_LOG_ERROR, "AVC Intra 50/100 supported only\n");
+        return 0;
+    }
+
+    return 1;
+}
+
 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
@@ -1978,6 +2079,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *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;
+        }
     }
 
     if (!mxf->header_written) {



More information about the ffmpeg-cvslog mailing list