Update for alloc_buffer changes.
[platform/upstream/gst-plugins-good.git] / gst / auparse / gstauparse.c
index da284d3..d39c239 100644 (file)
@@ -76,6 +76,7 @@ enum
 static void gst_auparse_base_init (gpointer g_class);
 static void gst_auparse_class_init (GstAuParseClass * klass);
 static void gst_auparse_init (GstAuParse * auparse);
+static void gst_auparse_dispose (GObject * object);
 
 static GstFlowReturn gst_auparse_chain (GstPad * pad, GstBuffer * buf);
 
@@ -128,12 +129,16 @@ gst_auparse_base_init (gpointer g_class)
 static void
 gst_auparse_class_init (GstAuParseClass * klass)
 {
+  GObjectClass *gobject_class;
   GstElementClass *gstelement_class;
 
+  gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
 
   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
 
+  gobject_class->dispose = gst_auparse_dispose;
+
   gstelement_class->change_state = gst_auparse_change_state;
 }
 
@@ -146,21 +151,32 @@ gst_auparse_init (GstAuParse * auparse)
   gst_element_add_pad (GST_ELEMENT (auparse), auparse->sinkpad);
   gst_pad_set_chain_function (auparse->sinkpad, gst_auparse_chain);
 
-  auparse->srcpad = NULL;
-#if 0                           /* FIXME: spider */
-  gst_pad_new_from_template (gst_static_pad_template_get
+  auparse->srcpad = gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_auparse_src_template), "src");
-  gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad);
   gst_pad_use_fixed_caps (auparse->srcpad);
-#endif
+  gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad);
 
   auparse->offset = 0;
+  auparse->buffer_offset = 0;
+  auparse->adapter = gst_adapter_new ();
   auparse->size = 0;
   auparse->encoding = 0;
   auparse->frequency = 0;
   auparse->channels = 0;
 }
 
+static void
+gst_auparse_dispose (GObject * object)
+{
+  GstAuParse *au = GST_AUPARSE (object);
+
+  if (au->adapter != NULL) {
+    gst_object_unref (au->adapter);
+    au->adapter = NULL;
+  }
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
 static GstFlowReturn
 gst_auparse_chain (GstPad * pad, GstBuffer * buf)
 {
@@ -171,13 +187,11 @@ gst_auparse_chain (GstPad * pad, GstBuffer * buf)
   GstCaps *tempcaps;
   gint law = 0, depth = 0, ieee = 0;
   gchar layout[7];
+  GstBuffer *subbuf;
+  GstEvent *event;
 
   layout[0] = 0;
 
-  g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR);
-  g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
-  g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-
   auparse = GST_AUPARSE (gst_pad_get_parent (pad));
 
   GST_DEBUG ("gst_auparse_chain: got buffer in '%s'",
@@ -188,7 +202,6 @@ gst_auparse_chain (GstPad * pad, GstBuffer * buf)
 
   /* if we haven't seen any data yet... */
   if (auparse->size == 0) {
-    GstBuffer *newbuf;
     guint32 *head = (guint32 *) data;
 
     /* normal format is big endian (au is a Sparc format) */
@@ -226,6 +239,8 @@ gst_auparse_chain (GstPad * pad, GstBuffer * buf)
 
     } else {
       GST_ELEMENT_ERROR (auparse, STREAM, WRONG_TYPE, (NULL), (NULL));
+      gst_buffer_unref (buf);
+      g_object_unref (auparse);
       return GST_FLOW_ERROR;
     }
 
@@ -311,33 +326,29 @@ Samples :
 
       default:
         GST_ELEMENT_ERROR (auparse, STREAM, FORMAT, (NULL), (NULL));
+        gst_buffer_unref (buf);
+        g_object_unref (auparse);
         return GST_FLOW_ERROR;
     }
 
-    auparse->srcpad =
-        gst_pad_new_from_template (gst_static_pad_template_get
-        (&gst_auparse_src_template), "src");
-
-    g_return_val_if_fail (auparse->srcpad != NULL, GST_FLOW_ERROR);
-
-
-    gst_pad_use_fixed_caps (auparse->srcpad);
-
     if (law) {
       tempcaps =
           gst_caps_new_simple ((law == 1) ? "audio/x-mulaw" : "audio/x-alaw",
           "rate", G_TYPE_INT, auparse->frequency,
           "channels", G_TYPE_INT, auparse->channels, NULL);
+      auparse->sample_size = auparse->channels;
     } else if (ieee) {
       tempcaps = gst_caps_new_simple ("audio/x-raw-float",
           "rate", G_TYPE_INT, auparse->frequency,
           "channels", G_TYPE_INT, auparse->channels,
           "endianness", G_TYPE_INT,
-          auparse->le ? G_LITTLE_ENDIAN : G_BIG_ENDIAN, "width", G_TYPE_INT,
-          depth, "buffer-frames", G_TYPE_INT, 0, NULL);
+          auparse->le ? G_LITTLE_ENDIAN : G_BIG_ENDIAN,
+          "width", G_TYPE_INT, depth, NULL);
+      auparse->sample_size = auparse->channels * depth / 8;
     } else if (layout[0]) {
       tempcaps = gst_caps_new_simple ("audio/x-adpcm",
           "layout", G_TYPE_STRING, layout, NULL);
+      auparse->sample_size = 0;
     } else {
       tempcaps = gst_caps_new_simple ("audio/x-raw-int",
           "rate", G_TYPE_INT, auparse->frequency,
@@ -346,51 +357,85 @@ Samples :
           auparse->le ? G_LITTLE_ENDIAN : G_BIG_ENDIAN, "depth", G_TYPE_INT,
           depth, "width", G_TYPE_INT, depth, "signed", G_TYPE_BOOLEAN, TRUE,
           NULL);
+      auparse->sample_size = auparse->channels * depth / 8;
     }
 
-    gst_pad_use_fixed_caps (auparse->srcpad);
     gst_pad_set_active (auparse->srcpad, TRUE);
     gst_pad_set_caps (auparse->srcpad, tempcaps);
-    gst_element_add_pad (GST_ELEMENT (auparse), auparse->srcpad);
 
-    if ((ret = gst_pad_alloc_buffer (auparse->srcpad, GST_BUFFER_OFFSET_NONE,
-                size - (auparse->offset),
-                GST_PAD_CAPS (auparse->srcpad), &newbuf)) != GST_FLOW_OK) {
-      printf ("failed gst_pad_alloc_buffer\n");
-      return ret;
-    }
-    ret = GST_FLOW_OK;
+    event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_DEFAULT,
+        0, GST_CLOCK_TIME_NONE, 0);
+
+    gst_pad_push_event (auparse->srcpad, event);
 
+    subbuf = gst_buffer_create_sub (buf, auparse->offset,
+        size - auparse->offset);
 
-    memcpy (GST_BUFFER_DATA (newbuf), data + (auparse->offset),
-        size - (auparse->offset));
-    GST_BUFFER_SIZE (newbuf) = size - (auparse->offset);
+    gst_buffer_unref (buf);
 
-    GstEvent *event;
+    gst_adapter_push (auparse->adapter, subbuf);
+  } else {
+    gst_adapter_push (auparse->adapter, buf);
+  }
 
-    event = NULL;
+  if (auparse->sample_size) {
+    /* Ensure we push a buffer that's a multiple of the frame size downstream */
+    int avail = gst_adapter_available (auparse->adapter);
 
-    event = gst_event_new_newsegment (1.0, GST_FORMAT_DEFAULT,
-        0, GST_CLOCK_TIME_NONE, 0);
+    avail -= avail % auparse->sample_size;
 
+    if (avail > 0) {
+      const guint8 *data = gst_adapter_peek (auparse->adapter, avail);
+      GstBuffer *newbuf;
 
-    gst_pad_push_event (auparse->srcpad, event);
+      if ((ret =
+              gst_pad_alloc_buffer_and_set_caps (auparse->srcpad,
+                  auparse->buffer_offset, avail, GST_PAD_CAPS (auparse->srcpad),
+                  &newbuf)) == GST_FLOW_OK) {
 
-    return gst_pad_push (auparse->srcpad, newbuf);
+        memcpy (GST_BUFFER_DATA (newbuf), data, avail);
+        gst_adapter_flush (auparse->adapter, avail);
 
+        auparse->buffer_offset += avail;
+
+        ret = gst_pad_push (auparse->srcpad, newbuf);
+      }
+    } else
+      ret = GST_FLOW_OK;
+  } else {
+    /* It's something non-trivial (such as ADPCM), we don't understand it, so
+     * just push downstream and assume this will know what to do with it */
+    ret = gst_pad_push (auparse->srcpad, buf);
   }
 
-  return gst_pad_push (auparse->srcpad, buf);
+  g_object_unref (auparse);
 
+  return ret;
 }
 
 static GstStateChangeReturn
 gst_auparse_change_state (GstElement * element, GstStateChange transition)
 {
+  GstAuParse *auparse = GST_AUPARSE (element);
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+
   if (parent_class->change_state)
-    return parent_class->change_state (element, transition);
+    ret = parent_class->change_state (element, transition);
+
+  switch (transition) {
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      gst_adapter_clear (auparse->adapter);
+      auparse->buffer_offset = 0;
+      auparse->offset = 0;
+      auparse->size = 0;
+      auparse->encoding = 0;
+      auparse->frequency = 0;
+      auparse->channels = 0;
+    default:
+      break;
+  }
 
-  return GST_STATE_CHANGE_SUCCESS;
+  return ret;
 }
 
 static gboolean
@@ -407,4 +452,5 @@ plugin_init (GstPlugin * plugin)
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
     GST_VERSION_MINOR,
     "auparse",
-    "parses au streams", plugin_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN)
+    "parses au streams", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
+    GST_PACKAGE_ORIGIN)