gst/auparse/: Partially fix #161712. playbin still doesn't work on these files, ...
authorMichael Smith <msmith@xiph.org>
Mon, 21 Nov 2005 17:18:01 +0000 (17:18 +0000)
committerMichael Smith <msmith@xiph.org>
Mon, 21 Nov 2005 17:18:01 +0000 (17:18 +0000)
Original commit message from CVS:
* gst/auparse/Makefile.am:
* gst/auparse/gstauparse.c: (gst_auparse_class_init),
(gst_auparse_init), (gst_auparse_dispose), (gst_auparse_chain),
(gst_auparse_change_state):
* gst/auparse/gstauparse.h:
Partially fix #161712. playbin still doesn't work on these files,
(on the bug report, Andy says we aren't typefinding it for some
reason?) but at least auparse isn't totally busted like it was before.

ChangeLog
gst/auparse/gstauparse.c

index a7bc950..f8cb46a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2005-11-21  Michael Smith <msmith@fluendo.com>
+
+       * gst/auparse/Makefile.am:
+       * gst/auparse/gstauparse.c: (gst_auparse_class_init),
+       (gst_auparse_init), (gst_auparse_dispose), (gst_auparse_chain),
+       (gst_auparse_change_state):
+       * gst/auparse/gstauparse.h:
+         Partially fix #161712. playbin still doesn't work on these files,
+         (on the bug report, Andy says we aren't typefinding it for some
+         reason?) but at least auparse isn't totally busted like it was before.
+
 2005-11-21  Andy Wingo  <wingo@pobox.com>
 
        * *.h:
index 82abd60..57d0f41 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;
 }
 
@@ -152,12 +157,26 @@ gst_auparse_init (GstAuParse * auparse)
   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) {
+    g_object_unref (au->adapter);
+    au->adapter = NULL;
+  }
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
 static GstFlowReturn
 gst_auparse_chain (GstPad * pad, GstBuffer * buf)
 {
@@ -168,6 +187,8 @@ 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;
 
@@ -181,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) */
@@ -316,16 +336,19 @@ Samples :
           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,
@@ -334,44 +357,59 @@ 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_set_active (auparse->srcpad, TRUE);
     gst_pad_set_caps (auparse->srcpad, tempcaps);
 
-    if ((ret = gst_pad_alloc_buffer (auparse->srcpad, GST_BUFFER_OFFSET_NONE,
-                size - (auparse->offset),
-                GST_PAD_CAPS (auparse->srcpad), &newbuf)) != GST_FLOW_OK) {
-      gst_buffer_unref (buf);
-      g_object_unref (auparse);
-      return ret;
-    }
-    ret = GST_FLOW_OK;
+    event = gst_event_new_newsegment (FALSE, 1.0, GST_FORMAT_DEFAULT,
+        0, GST_CLOCK_TIME_NONE, 0);
 
+    gst_pad_push_event (auparse->srcpad, event);
 
-    memcpy (GST_BUFFER_DATA (newbuf), data + (auparse->offset),
-        size - (auparse->offset));
-    GST_BUFFER_SIZE (newbuf) = size - (auparse->offset);
+    subbuf = gst_buffer_create_sub (buf, auparse->offset,
+        size - auparse->offset);
 
-    GstEvent *event;
+    gst_buffer_unref (buf);
 
-    event = NULL;
+    gst_adapter_push (auparse->adapter, subbuf);
+  } else {
+    gst_adapter_push (auparse->adapter, buf);
+  }
 
-    event = gst_event_new_newsegment (FALSE, 1.0, GST_FORMAT_DEFAULT,
-        0, GST_CLOCK_TIME_NONE, 0);
+  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);
 
+    avail -= avail % auparse->sample_size;
 
-    gst_pad_push_event (auparse->srcpad, event);
+    if (avail > 0) {
+      const guint8 *data = gst_adapter_peek (auparse->adapter, avail);
+      GstBuffer *newbuf;
 
-    gst_buffer_unref (buf);
-    g_object_unref (auparse);
-    return gst_pad_push (auparse->srcpad, newbuf);
+      if ((ret = gst_pad_alloc_buffer (auparse->srcpad, auparse->buffer_offset,
+                  avail, GST_PAD_CAPS (auparse->srcpad),
+                  &newbuf)) == GST_FLOW_OK) {
+
+        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);
   }
 
   g_object_unref (auparse);
-  return gst_pad_push (auparse->srcpad, buf);
 
+  return ret;
 }
 
 static GstStateChangeReturn
@@ -385,6 +423,8 @@ gst_auparse_change_state (GstElement * element, GstStateChange 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;