From 4531381541d2e177b458794f9f9ec66d113a0923 Mon Sep 17 00:00:00 2001 From: Andoni Morales Alastruey Date: Thu, 2 May 2013 14:56:02 +0200 Subject: [PATCH] ac3parse: add support for "audio/x-private1-ac3" --- gst/audioparsers/gstac3parse.c | 62 ++++++++++++++++++++++++++++++++-- gst/audioparsers/gstac3parse.h | 11 +++--- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c index 853ffc5511..533a675870 100644 --- a/gst/audioparsers/gstac3parse.c +++ b/gst/audioparsers/gstac3parse.c @@ -35,7 +35,7 @@ */ /* TODO: - * - add support for audio/x-private1-ac3 as well + * - audio/ac3 to audio/x-private1-ac3 is not implemented (done in the muxer) * - should accept framed and unframed input (needs decodebin fixes first) */ @@ -153,7 +153,8 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-ac3; " "audio/x-eac3; " "audio/ac3")); + GST_STATIC_CAPS ("audio/x-ac3; " "audio/x-eac3; " "audio/ac3; " + "audio/x-private1-ac3")); static void gst_ac3_parse_finalize (GObject * object); @@ -165,6 +166,8 @@ static gboolean gst_ac3_parse_src_event (GstBaseParse * parse, GstEvent * event); static GstCaps *gst_ac3_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter); +static gboolean gst_ac3_parse_set_sink_caps (GstBaseParse * parse, + GstCaps * caps); #define gst_ac3_parse_parent_class parent_class G_DEFINE_TYPE (GstAc3Parse, gst_ac3_parse, GST_TYPE_BASE_PARSE); @@ -195,6 +198,7 @@ gst_ac3_parse_class_init (GstAc3ParseClass * klass) parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_handle_frame); parse_class->src_event = GST_DEBUG_FUNCPTR (gst_ac3_parse_src_event); parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_ac3_parse_get_sink_caps); + parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ac3_parse_set_sink_caps); } static void @@ -212,6 +216,8 @@ gst_ac3_parse_init (GstAc3Parse * ac3parse) { gst_base_parse_set_min_frame_size (GST_BASE_PARSE (ac3parse), 6); gst_ac3_parse_reset (ac3parse); + ac3parse->baseparse_chainfunc = + GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE (ac3parse))->chainfunc; } static void @@ -660,6 +666,43 @@ cleanup: return res; } + +/* + * MPEG-PS private1 streams add a 2 bytes "Audio Substream Headers" for each + * buffer (not each frame) with the offset of the next frame's start. + * + * Buffer 1: + * ------------------------------------------- + * |firstAccUnit|AC3SyncWord|xxxxxxxxxxxxxxxxx + * ------------------------------------------- + * Buffer 2: + * ------------------------------------------- + * |firstAccUnit|xxxxxx|AC3SyncWord|xxxxxxxxxx + * ------------------------------------------- + * + * These 2 bytes can be dropped safely as they do not include any timing + * information, only the offset to the start of the next frame. + * + * From http://stnsoft.com/DVD/ass-hdr.html: + * "FirstAccUnit offset to frame which corresponds to PTS value offset 0 is the + * last byte of FirstAccUnit, ie add the offset of byte 2 to get the AU's offset + * The value 0000 indicates there is no first access unit" + * */ + +static GstFlowReturn +gst_ac3_parse_chain_priv (GstPad * pad, GstObject * parent, GstBuffer * buffer) +{ + GstBuffer *newbuf; + GstFlowReturn ret; + GstAc3Parse *ac3parse = GST_AC3_PARSE (parent); + + newbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, + 2, gst_buffer_get_size (buffer) - 2); + ret = ac3parse->baseparse_chainfunc (pad, parent, newbuf); + gst_buffer_unref (buffer); + return ret; +} + static gboolean gst_ac3_parse_src_event (GstBaseParse * parse, GstEvent * event) { @@ -737,3 +780,18 @@ gst_ac3_parse_get_sink_caps (GstBaseParse * parse, GstCaps * filter) return res; } + +static gboolean +gst_ac3_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps) +{ + GstStructure *s; + GstAc3Parse *ac3parse = GST_AC3_PARSE (parse); + + s = gst_caps_get_structure (caps, 0); + if (gst_structure_has_name (s, "audio/x-private1-ac3")) { + gst_pad_set_chain_function (parse->sinkpad, gst_ac3_parse_chain_priv); + } else { + gst_pad_set_chain_function (parse->sinkpad, ac3parse->baseparse_chainfunc); + } + return TRUE; +} diff --git a/gst/audioparsers/gstac3parse.h b/gst/audioparsers/gstac3parse.h index 59f6e197d9..0800dca3c5 100644 --- a/gst/audioparsers/gstac3parse.h +++ b/gst/audioparsers/gstac3parse.h @@ -57,11 +57,12 @@ struct _GstAc3Parse { GstBaseParse baseparse; /*< private >*/ - gint sample_rate; - gint channels; - gint blocks; - gboolean eac; - volatile gint align; + gint sample_rate; + gint channels; + gint blocks; + gboolean eac; + volatile gint align; + GstPadChainFunction baseparse_chainfunc; }; /**