ac3parse: add support for "audio/x-private1-ac3"
authorAndoni Morales Alastruey <ylatuya@gmail.com>
Thu, 2 May 2013 12:56:02 +0000 (14:56 +0200)
committerAndoni Morales Alastruey <ylatuya@gmail.com>
Fri, 3 May 2013 11:44:23 +0000 (13:44 +0200)
gst/audioparsers/gstac3parse.c
gst/audioparsers/gstac3parse.h

index 853ffc5..533a675 100644 (file)
@@ -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;
+}
index 59f6e19..0800dca 100644 (file)
@@ -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;
 };
 
 /**