summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--ext/gsm/gstgsmdec.c124
-rw-r--r--ext/gsm/gstgsmdec.h5
-rw-r--r--ext/gsm/gstgsmenc.c40
4 files changed, 154 insertions, 26 deletions
diff --git a/ChangeLog b/ChangeLog
index 05a5ae43..7cf6851c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2006-03-29 Wim Taymans <wim@fluendo.com>
+ * ext/gsm/gstgsmdec.c: (gst_gsmdec_class_init), (gst_gsmdec_init),
+ (gst_gsmdec_finalize), (gst_gsmdec_sink_event), (gst_gsmdec_chain):
+ * ext/gsm/gstgsmdec.h:
+ * ext/gsm/gstgsmenc.c: (gst_gsmenc_class_init), (gst_gsmenc_init),
+ (gst_gsmenc_finalize), (gst_gsmenc_chain):
+ Cleanups, fix leaks.
+ Handle events and DISCONT.
+ Use adapter in the decoder.
+
+2006-03-29 Wim Taymans <wim@fluendo.com>
+
Patch by: Renato Araujo Oliveira Filho <renatox at gmail dot com>
* configure.ac:
diff --git a/ext/gsm/gstgsmdec.c b/ext/gsm/gstgsmdec.c
index 6475a779..a3ec28ed 100644
--- a/ext/gsm/gstgsmdec.c
+++ b/ext/gsm/gstgsmdec.c
@@ -54,7 +54,9 @@ enum
static void gst_gsmdec_base_init (gpointer g_class);
static void gst_gsmdec_class_init (GstGSMDec * klass);
static void gst_gsmdec_init (GstGSMDec * gsmdec);
+static void gst_gsmdec_finalize (GObject * object);
+static gboolean gst_gsmdec_sink_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_gsmdec_chain (GstPad * pad, GstBuffer * buf);
static GstElementClass *parent_class = NULL;
@@ -118,11 +120,15 @@ gst_gsmdec_base_init (gpointer g_class)
static void
gst_gsmdec_class_init (GstGSMDec * klass)
{
+ GObjectClass *gobject_class;
GstElementClass *gstelement_class;
+ gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gst_gsmdec_finalize;
GST_DEBUG_CATEGORY_INIT (gsmdec_debug, "gsmdec", 0, "GSM Decoder");
}
@@ -130,10 +136,13 @@ gst_gsmdec_class_init (GstGSMDec * klass)
static void
gst_gsmdec_init (GstGSMDec * gsmdec)
{
+ gint use_wav49;
+
/* create the sink and src pads */
gsmdec->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get
(&gsmdec_sink_template), "sink");
+ gst_pad_set_event_function (gsmdec->sinkpad, gst_gsmdec_sink_event);
gst_pad_set_chain_function (gsmdec->sinkpad, gst_gsmdec_chain);
gst_element_add_pad (GST_ELEMENT (gsmdec), gsmdec->sinkpad);
@@ -143,59 +152,138 @@ gst_gsmdec_init (GstGSMDec * gsmdec)
gst_element_add_pad (GST_ELEMENT (gsmdec), gsmdec->srcpad);
gsmdec->state = gsm_create ();
- // turn on WAN49 handling
- gint use_wav49 = 0;
+ /* turn on WAV49 handling */
+ use_wav49 = 0;
gsm_option (gsmdec->state, GSM_OPT_WAV49, &use_wav49);
+ gsmdec->adapter = gst_adapter_new ();
gsmdec->next_of = 0;
gsmdec->next_ts = 0;
}
+static void
+gst_gsmdec_finalize (GObject * object)
+{
+ GstGSMDec *gsmdec;
+
+ gsmdec = GST_GSMDEC (object);
+
+ g_object_unref (gsmdec->adapter);
+ gsm_destroy (gsmdec->state);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_gsmdec_sink_event (GstPad * pad, GstEvent * event)
+{
+ gboolean res;
+ GstGSMDec *gsmdec;
+
+ gsmdec = GST_GSMDEC (gst_pad_get_parent (pad));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_START:
+ res = gst_pad_push_event (gsmdec->srcpad, event);
+ break;
+ case GST_EVENT_FLUSH_STOP:
+ gst_segment_init (&gsmdec->segment, GST_FORMAT_UNDEFINED);
+ res = gst_pad_push_event (gsmdec->srcpad, event);
+ break;
+ case GST_EVENT_NEWSEGMENT:
+ {
+ gboolean update;
+ GstFormat format;
+ gdouble rate;
+ gint64 start, stop, time;
+
+ gst_event_parse_new_segment (event, &update, &rate, &format, &start,
+ &stop, &time);
+
+ /* now configure the values */
+ gst_segment_set_newsegment (&gsmdec->segment, update,
+ rate, format, start, stop, time);
+
+ /* and forward */
+ res = gst_pad_push_event (gsmdec->srcpad, event);
+ break;
+ }
+ case GST_EVENT_EOS:
+ default:
+ res = gst_pad_push_event (gsmdec->srcpad, event);
+ break;
+ }
+
+ gst_object_unref (gsmdec);
+
+ return res;
+}
+
static GstFlowReturn
gst_gsmdec_chain (GstPad * pad, GstBuffer * buf)
{
GstGSMDec *gsmdec;
gsm_byte *data;
GstFlowReturn ret = GST_FLOW_OK;
+ GstClockTime timestamp;
gsmdec = GST_GSMDEC (gst_pad_get_parent (pad));
- // do we have enough bytes to read a header
- if (GST_BUFFER_SIZE (buf) >= 33) {
+ timestamp = GST_BUFFER_TIMESTAMP (buf);
+
+ if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
+ gst_adapter_clear (gsmdec->adapter);
+ }
+ gst_adapter_push (gsmdec->adapter, buf);
+
+ /* do we have enough bytes to read a header */
+ while (gst_adapter_available (gsmdec->adapter) >= 33) {
GstBuffer *outbuf;
outbuf = gst_buffer_new_and_alloc (160 * sizeof (gsm_signal));
- // TODO take new segment in consideration, if not given restart
- // timestamps at 0
- if (GST_BUFFER_TIMESTAMP (buf) == GST_CLOCK_TIME_NONE) {
+
+ /* TODO take new segment in consideration, if not given restart
+ * timestamps at 0 */
+ if (timestamp == GST_CLOCK_TIME_NONE) {
/* If we are not given any timestamp */
GST_BUFFER_TIMESTAMP (outbuf) = gsmdec->next_ts;
- gsmdec->next_ts += 20 * GST_MSECOND;
+ if (gsmdec->next_ts != GST_CLOCK_TIME_NONE)
+ gsmdec->next_ts += 20 * GST_MSECOND;
}
else {
- /* But if you insist on giving us a timestamp, you are welcome. */
- GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
+ /* upstream gave a timestamp, use it. */
+ GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
+ gsmdec->next_ts = timestamp + 20 * GST_MSECOND;
+ /* and make sure we interpollate in the next run */
+ timestamp = GST_CLOCK_TIME_NONE;
}
GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND;
GST_BUFFER_OFFSET (outbuf) = gsmdec->next_of;
- GST_BUFFER_OFFSET_END (outbuf) = gsmdec->next_of + 160 - 1;
- gst_buffer_set_caps (outbuf, gst_pad_get_caps (gsmdec->srcpad));
gsmdec->next_of += 160;
+ GST_BUFFER_OFFSET_END (outbuf) = gsmdec->next_of;
- data = (gsm_byte *) GST_BUFFER_DATA (buf);
- gsm_decode (gsmdec->state, data, (gsm_signal *) GST_BUFFER_DATA (outbuf));
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmdec->srcpad));
- GST_DEBUG ("Pushing buffer of size %d ts %" GST_TIME_FORMAT,
+ /* now encode frame into the output buffer */
+ data = (gsm_byte *) gst_adapter_peek (gsmdec->adapter, 33);
+ if (gsm_decode (gsmdec->state, data,
+ (gsm_signal *) GST_BUFFER_DATA (outbuf)) < 0) {
+ /* invalid frame */
+ GST_WARNING_OBJECT (gsmdec, "tried to decode an invalid frame, skipping");
+ }
+ gst_adapter_flush (gsmdec->adapter, 33);
+
+ GST_DEBUG_OBJECT (gsmdec, "Pushing buffer of size %d ts %" GST_TIME_FORMAT,
GST_BUFFER_SIZE (outbuf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
- //gst_util_dump_mem (GST_BUFFER_DATA(outbuf), GST_BUFFER_SIZE (outbuf));
+
+ /* push */
ret = gst_pad_push (gsmdec->srcpad, outbuf);
}
- gst_buffer_unref (buf);
gst_object_unref (gsmdec);
return ret;
diff --git a/ext/gsm/gstgsmdec.h b/ext/gsm/gstgsmdec.h
index 1718e74b..7e73cccf 100644
--- a/ext/gsm/gstgsmdec.h
+++ b/ext/gsm/gstgsmdec.h
@@ -21,6 +21,7 @@
#define __GST_GSMDEC_H__
#include <gst/gst.h>
+#include <gst/base/gstadapter.h>
#ifdef GSM_HEADER_IN_SUBDIR
#include <gsm/gsm.h>
@@ -54,6 +55,10 @@ struct _GstGSMDec
gsm state;
gint64 next_of;
GstClockTime next_ts;
+
+ GstAdapter *adapter;
+
+ GstSegment segment;
};
struct _GstGSMDecClass
diff --git a/ext/gsm/gstgsmenc.c b/ext/gsm/gstgsmenc.c
index 2ecbefc7..4c69d1e6 100644
--- a/ext/gsm/gstgsmenc.c
+++ b/ext/gsm/gstgsmenc.c
@@ -54,6 +54,7 @@ enum
static void gst_gsmenc_base_init (gpointer g_class);
static void gst_gsmenc_class_init (GstGSMEnc * klass);
static void gst_gsmenc_init (GstGSMEnc * gsmenc);
+static void gst_gsmenc_finalize (GObject * object);
static GstFlowReturn gst_gsmenc_chain (GstPad * pad, GstBuffer * buf);
@@ -122,7 +123,9 @@ gst_gsmenc_class_init (GstGSMEnc * klass)
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
- parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+ parent_class = g_type_class_peek_parent (klass);
+
+ gobject_class->finalize = gst_gsmenc_finalize;
GST_DEBUG_CATEGORY_INIT (gsmenc_debug, "gsmenc", 0, "GSM Encoder");
}
@@ -130,6 +133,8 @@ gst_gsmenc_class_init (GstGSMEnc * klass)
static void
gst_gsmenc_init (GstGSMEnc * gsmenc)
{
+ gint use_wav49;
+
/* create the sink and src pads */
gsmenc->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get
@@ -143,16 +148,28 @@ gst_gsmenc_init (GstGSMEnc * gsmenc)
gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->srcpad);
gsmenc->state = gsm_create ();
- // turn on WAN49 handling
- gint use_wav49 = 0;
+ /* turn on WAV49 handling */
+ use_wav49 = 0;
gsm_option (gsmenc->state, GSM_OPT_WAV49, &use_wav49);
gsmenc->adapter = gst_adapter_new ();
-
gsmenc->next_ts = 0;
}
+static void
+gst_gsmenc_finalize (GObject * object)
+{
+ GstGSMEnc *gsmenc;
+
+ gsmenc = GST_GSMENC (object);
+
+ g_object_unref (gsmenc->adapter);
+ gsm_destroy (gsmenc->state);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
static GstFlowReturn
gst_gsmenc_chain (GstPad * pad, GstBuffer * buf)
{
@@ -161,24 +178,31 @@ gst_gsmenc_chain (GstPad * pad, GstBuffer * buf)
GstFlowReturn ret = GST_FLOW_OK;
gsmenc = GST_GSMENC (gst_pad_get_parent (pad));
+
+ if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
+ gst_adapter_clear (gsmenc->adapter);
+ }
gst_adapter_push (gsmenc->adapter, buf);
while (gst_adapter_available (gsmenc->adapter) >= 320) {
GstBuffer *outbuf;
outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte));
+
GST_BUFFER_TIMESTAMP (outbuf) = gsmenc->next_ts;
GST_BUFFER_DURATION (outbuf) = 20 * GST_MSECOND;
gsmenc->next_ts += 20 * GST_MSECOND;
- // encode 160 16-bit samples into 33 bytes
+ /* encode 160 16-bit samples into 33 bytes */
data = (gsm_signal *) gst_adapter_peek (gsmenc->adapter, 320);
gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf));
gst_adapter_flush (gsmenc->adapter, 320);
- gst_buffer_set_caps (outbuf, gst_pad_get_caps (gsmenc->srcpad));
- GST_DEBUG ("Pushing buffer of size %d", GST_BUFFER_SIZE (outbuf));
- //gst_util_dump_mem (GST_BUFFER_DATA(outbuf), GST_BUFFER_SIZE (outbuf));
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmenc->srcpad));
+
+ GST_DEBUG_OBJECT (gsmenc, "Pushing buffer of size %d",
+ GST_BUFFER_SIZE (outbuf));
+
ret = gst_pad_push (gsmenc->srcpad, outbuf);
}