From a965185dee339da89f833b10cc2e5ac1108381b2 Mon Sep 17 00:00:00 2001 From: Alex Ashley Date: Tue, 18 Jun 2013 13:27:20 +0100 Subject: [PATCH] qtdemux: Add support for the avc3 sample entry format of the AVC file format Amendment 2 of ISO/IEC 14496-15 (AVC file format) is defining a new structure for fragmented MP4 called "avc3". The principal difference between AVC1 and AVC3 is the location of the codec initialisation data (e.g. SPS, PPS). In AVC1 this data is placed in the initial MOOV box (moov.trak.mdia.minf.stbl.stsd.avc1) but in AVC3 this data goes in the first sample of every fragment (i.e. the first sample in each mdat box). The principal reason for avc3 is to make it easier for client implementations, because it removes the requirement to insert the SPS+PPS in to the decoder pipeline every time there is a representation change. This commit adds support for the "avc3" atom, which is almost identical to the "avc1" atom, except it does not contain any SPS or PPS data. https://bugzilla.gnome.org/show_bug.cgi?id=702004 --- gst/isomp4/atoms.c | 3 ++- gst/isomp4/fourcc.h | 1 + gst/isomp4/ftypcc.h | 2 +- gst/isomp4/gstrtpxqtdepay.c | 2 ++ gst/isomp4/qtdemux.c | 13 +++++++++++++ gst/isomp4/qtdemux_fourcc.h | 1 + gst/isomp4/qtdemux_types.c | 3 +++ 7 files changed, 23 insertions(+), 2 deletions(-) diff --git a/gst/isomp4/atoms.c b/gst/isomp4/atoms.c index 7b9af627ea..f6df24af1a 100644 --- a/gst/isomp4/atoms.c +++ b/gst/isomp4/atoms.c @@ -3320,7 +3320,8 @@ atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context, ste = atom_trak_add_video_entry (trak, context, entry->fourcc); trak->is_video = TRUE; - trak->is_h264 = (entry->fourcc == FOURCC_avc1); + trak->is_h264 = (entry->fourcc == FOURCC_avc1 + || entry->fourcc == FOURCC_avc3); ste->version = entry->version; ste->width = entry->width; diff --git a/gst/isomp4/fourcc.h b/gst/isomp4/fourcc.h index bcb182e528..1769c7b45a 100644 --- a/gst/isomp4/fourcc.h +++ b/gst/isomp4/fourcc.h @@ -143,6 +143,7 @@ G_BEGIN_DECLS #define FOURCC_qtim GST_MAKE_FOURCC('q','t','i','m') #define FOURCC_drms GST_MAKE_FOURCC('d','r','m','s') #define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1') +#define FOURCC_avc3 GST_MAKE_FOURCC('a','v','c','3') #define FOURCC_h263 GST_MAKE_FOURCC('h','2','6','3') #define FOURCC_s263 GST_MAKE_FOURCC('s','2','6','3') #define FOURCC_avcC GST_MAKE_FOURCC('a','v','c','C') diff --git a/gst/isomp4/ftypcc.h b/gst/isomp4/ftypcc.h index b8b2c5e67e..6da9a09062 100644 --- a/gst/isomp4/ftypcc.h +++ b/gst/isomp4/ftypcc.h @@ -59,10 +59,10 @@ G_BEGIN_DECLS #define FOURCC_3gr6 GST_MAKE_FOURCC('3','g','r','6') #define FOURCC_3gg7 GST_MAKE_FOURCC('3','g','g','7') #define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1') +#define FOURCC_avc3 GST_MAKE_FOURCC('a','v','c','3') #define FOURCC_qt__ GST_MAKE_FOURCC('q','t',' ',' ') #define FOURCC_isml GST_MAKE_FOURCC('i','s','m','l') #define FOURCC_piff GST_MAKE_FOURCC('p','i','f','f') G_END_DECLS - #endif /* __FTYP_CC_H__ */ diff --git a/gst/isomp4/gstrtpxqtdepay.c b/gst/isomp4/gstrtpxqtdepay.c index 54baf09ad2..3bce461bc6 100644 --- a/gst/isomp4/gstrtpxqtdepay.c +++ b/gst/isomp4/gstrtpxqtdepay.c @@ -58,6 +58,7 @@ #define QT_UINT64(a) ((((guint64)QT_UINT32(a))<<32)|QT_UINT32(((guint8 *)a)+4)) #define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1') +#define FOURCC_avc3 GST_MAKE_FOURCC('a','v','c','3') #define FOURCC_avcC GST_MAKE_FOURCC('a','v','c','C') GST_DEBUG_CATEGORY_STATIC (rtpxqtdepay_debug); @@ -179,6 +180,7 @@ gst_rtp_quicktime_parse_sd (GstRtpXQTDepay * rtpxqtdepay, guint8 * data, switch (fourcc) { case FOURCC_avc1: + case FOURCC_avc3: { guint32 chlen; diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index 36b6fbe774..3ac4182461 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -5400,6 +5400,12 @@ qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer, qtdemux_parse_container (qtdemux, node, buffer + 0x56, end); break; } + case FOURCC_avc3: + { + GST_MEMDUMP_OBJECT (qtdemux, "avc3", buffer, end - buffer); + qtdemux_parse_container (qtdemux, node, buffer + 0x56, end); + break; + } case FOURCC_mjp2: { qtdemux_parse_container (qtdemux, node, buffer + 86, end); @@ -7315,6 +7321,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) switch (fourcc) { case FOURCC_H264: case FOURCC_avc1: + case FOURCC_avc3: { gint len = QT_UINT32 (stsd_data) - 0x66; const guint8 *avc_data = stsd_data + 0x66; @@ -10345,6 +10352,12 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, "stream-format", G_TYPE_STRING, "avc", "alignment", G_TYPE_STRING, "au", NULL); break; + case GST_MAKE_FOURCC ('a', 'v', 'c', '3'): + _codec ("H.264 / AVC"); + caps = gst_caps_new_simple ("video/x-h264", + "stream-format", G_TYPE_STRING, "avc3", + "alignment", G_TYPE_STRING, "au", NULL); + break; case GST_MAKE_FOURCC ('r', 'l', 'e', ' '): _codec ("Run-length encoding"); caps = gst_caps_new_simple ("video/x-rle", diff --git a/gst/isomp4/qtdemux_fourcc.h b/gst/isomp4/qtdemux_fourcc.h index d3a972bb22..6b8bd062ef 100644 --- a/gst/isomp4/qtdemux_fourcc.h +++ b/gst/isomp4/qtdemux_fourcc.h @@ -142,6 +142,7 @@ G_BEGIN_DECLS #define FOURCC_H264 GST_MAKE_FOURCC('H','2','6','4') #define FOURCC_strf GST_MAKE_FOURCC('s','t','r','f') #define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1') +#define FOURCC_avc3 GST_MAKE_FOURCC('a','v','c','3') #define FOURCC_avcC GST_MAKE_FOURCC('a','v','c','C') #define FOURCC_btrt GST_MAKE_FOURCC('b','t','r','t') #define FOURCC_VP31 GST_MAKE_FOURCC('V','P','3','1') diff --git a/gst/isomp4/qtdemux_types.c b/gst/isomp4/qtdemux_types.c index 92e1814ee5..e9f32cc5b6 100644 --- a/gst/isomp4/qtdemux_types.c +++ b/gst/isomp4/qtdemux_types.c @@ -171,6 +171,9 @@ static const QtNodeType qt_node_types[] = { qtdemux_dump_mehd}, {FOURCC_ovc1, "ovc1", 0}, {FOURCC_owma, "owma", 0}, + {FOURCC_avcC, "AV codec configuration container", 0}, + {FOURCC_avc1, "AV codec configuration v1", 0}, + {FOURCC_avc3, "AV codec configuration v3", 0}, {FOURCC_tfdt, "Track fragment decode time", 0, qtdemux_dump_tfdt}, {FOURCC_chap, "Chapter Reference"}, {0, "unknown", 0,},