summaryrefslogtreecommitdiffstats
path: root/ext/gsm/gstgsmdec.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2006-03-29 16:54:12 +0000
committerWim Taymans <wim.taymans@gmail.com>2006-03-29 16:54:12 +0000
commitde433bfdcb5ba523f6e0c5ec0589f5bd890cee35 (patch)
tree6e5b44428e407f1f471538c9dc2a1bcc8165b0a2 /ext/gsm/gstgsmdec.c
parent599af07ac788e98a83b580be91c73d5888b1c6f6 (diff)
downloadgst-plugins-bad-de433bfdcb5ba523f6e0c5ec0589f5bd890cee35.tar.gz
gst-plugins-bad-de433bfdcb5ba523f6e0c5ec0589f5bd890cee35.tar.bz2
gst-plugins-bad-de433bfdcb5ba523f6e0c5ec0589f5bd890cee35.zip
ext/gsm/: Cleanups, fix leaks.
Original commit message from CVS: * 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.
Diffstat (limited to 'ext/gsm/gstgsmdec.c')
-rw-r--r--ext/gsm/gstgsmdec.c124
1 files changed, 106 insertions, 18 deletions
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;