summaryrefslogtreecommitdiffstats
path: root/gst/auparse/gstauparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/auparse/gstauparse.c')
-rw-r--r--gst/auparse/gstauparse.c86
1 files changed, 63 insertions, 23 deletions
diff --git a/gst/auparse/gstauparse.c b/gst/auparse/gstauparse.c
index 82abd601..57d0f418 100644
--- a/gst/auparse/gstauparse.c
+++ b/gst/auparse/gstauparse.c
@@ -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;