From b34a106764ac7fa66fda4bade7353e97c6f357cc Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 6 Feb 2006 15:55:28 +0000 Subject: [PATCH] ext/amrnb/amrnbdec.*: Fix amrnbdec, handle events, take copy from adapter since the decoder apparently writes in the ... Original commit message from CVS: * ext/amrnb/amrnbdec.c: (gst_amrnbdec_init), (gst_amrnbdec_setcaps), (gst_amrnbdec_event), (gst_amrnbdec_chain), (gst_amrnbdec_state_change): * ext/amrnb/amrnbdec.h: Fix amrnbdec, handle events, take copy from adapter since the decoder apparently writes in the source data. Use some _scale_int, and precalc duration. Fix some leaks, post ERROR messages. --- ChangeLog | 11 ++++++ common | 2 +- ext/amrnb/amrnbdec.c | 79 ++++++++++++++++++++++++++++++++++++-------- ext/amrnb/amrnbdec.h | 1 + 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 11db4a5f9d..c73086b196 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2006-02-06 Wim Taymans + + * ext/amrnb/amrnbdec.c: (gst_amrnbdec_init), + (gst_amrnbdec_setcaps), (gst_amrnbdec_event), (gst_amrnbdec_chain), + (gst_amrnbdec_state_change): + * ext/amrnb/amrnbdec.h: + Fix amrnbdec, handle events, take copy from adapter since the decoder + apparently writes in the source data. + Use some _scale_int, and precalc duration. + Fix some leaks, post ERROR messages. + 2006-02-04 Tim-Philipp Müller * gst/realmedia/rmdemux.c: (gst_rmdemux_add_stream): diff --git a/common b/common index 79d67fe009..58567e5519 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 79d67fe009b6120b82d51df860c78e8361f02aea +Subproject commit 58567e5519f2d00a4592491db1a6e8302993279e diff --git a/ext/amrnb/amrnbdec.c b/ext/amrnb/amrnbdec.c index 9980de1d39..b212934be6 100644 --- a/ext/amrnb/amrnbdec.c +++ b/ext/amrnb/amrnbdec.c @@ -48,6 +48,7 @@ static void gst_amrnbdec_base_init (GstAmrnbDecClass * klass); static void gst_amrnbdec_class_init (GstAmrnbDecClass * klass); static void gst_amrnbdec_init (GstAmrnbDec * amrnbdec); +static gboolean gst_amrnbdec_event (GstPad * pad, GstEvent * event); static GstFlowReturn gst_amrnbdec_chain (GstPad * pad, GstBuffer * buffer); static gboolean gst_amrnbdec_setcaps (GstPad * pad, GstCaps * caps); static GstStateChangeReturn gst_amrnbdec_state_change (GstElement * element, @@ -117,6 +118,7 @@ gst_amrnbdec_init (GstAmrnbDec * amrnbdec) gst_pad_new_from_template (gst_static_pad_template_get (&sink_template), "sink"); gst_pad_set_setcaps_function (amrnbdec->sinkpad, gst_amrnbdec_setcaps); + gst_pad_set_event_function (amrnbdec->sinkpad, gst_amrnbdec_event); gst_pad_set_chain_function (amrnbdec->sinkpad, gst_amrnbdec_chain); gst_element_add_pad (GST_ELEMENT (amrnbdec), amrnbdec->sinkpad); @@ -133,7 +135,8 @@ gst_amrnbdec_init (GstAmrnbDec * amrnbdec) amrnbdec->handle = NULL; amrnbdec->channels = 0; amrnbdec->rate = 0; - amrnbdec->ts = 0; + amrnbdec->duration = 0; + amrnbdec->ts = -1; } static gboolean @@ -143,7 +146,7 @@ gst_amrnbdec_setcaps (GstPad * pad, GstCaps * caps) GstAmrnbDec *amrnbdec; GstCaps *copy; - amrnbdec = GST_AMRNBDEC (GST_PAD_PARENT (pad)); + amrnbdec = GST_AMRNBDEC (gst_pad_get_parent (pad)); structure = gst_caps_get_structure (caps, 0); @@ -159,19 +162,54 @@ gst_amrnbdec_setcaps (GstPad * pad, GstCaps * caps) "endianness", G_TYPE_INT, G_BYTE_ORDER, "rate", G_TYPE_INT, amrnbdec->rate, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + amrnbdec->duration = gst_util_uint64_scale_int (GST_SECOND, 160, + amrnbdec->rate * amrnbdec->channels); + gst_pad_set_caps (amrnbdec->srcpad, copy); gst_caps_unref (copy); + gst_object_unref (amrnbdec); + return TRUE; } +static gboolean +gst_amrnbdec_event (GstPad * pad, GstEvent * event) +{ + GstAmrnbDec *amrnbdec; + gboolean ret = TRUE; + + amrnbdec = GST_AMRNBDEC (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + ret = gst_pad_push_event (amrnbdec->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + ret = gst_pad_push_event (amrnbdec->srcpad, event); + gst_adapter_clear (amrnbdec->adapter); + amrnbdec->ts = -1; + break; + case GST_EVENT_EOS: + gst_adapter_clear (amrnbdec->adapter); + ret = gst_pad_push_event (amrnbdec->srcpad, event); + break; + default: + ret = gst_pad_push_event (amrnbdec->srcpad, event); + break; + } + gst_object_unref (amrnbdec); + + return ret; +} + static GstFlowReturn gst_amrnbdec_chain (GstPad * pad, GstBuffer * buffer) { GstAmrnbDec *amrnbdec; GstFlowReturn ret; - amrnbdec = GST_AMRNBDEC (GST_PAD_PARENT (pad)); + amrnbdec = GST_AMRNBDEC (gst_pad_get_parent (pad)); if (amrnbdec->rate == 0 || amrnbdec->channels == 0) goto not_negotiated; @@ -198,30 +236,35 @@ gst_amrnbdec_chain (GstPad * pad, GstBuffer * buffer) if (gst_adapter_available (amrnbdec->adapter) < block) break; - data = (guint8 *) gst_adapter_peek (amrnbdec->adapter, block); + data = (guint8 *) gst_adapter_take (amrnbdec->adapter, block); /* get output */ out = gst_buffer_new_and_alloc (160 * 2); - GST_BUFFER_DURATION (out) = GST_SECOND * 160 / - (amrnbdec->rate * amrnbdec->channels); + GST_BUFFER_DURATION (out) = amrnbdec->duration; GST_BUFFER_TIMESTAMP (out) = amrnbdec->ts; - amrnbdec->ts += GST_BUFFER_DURATION (out); - gst_buffer_set_caps (out, gst_pad_get_caps (amrnbdec->srcpad)); + if (amrnbdec->ts != -1) + amrnbdec->ts += GST_BUFFER_DURATION (out); + gst_buffer_set_caps (out, GST_PAD_CAPS (amrnbdec->srcpad)); - /* decode */ + /* decode, the library seems to write into the source data, hence + * the copy. */ Decoder_Interface_Decode (amrnbdec->handle, data, (short *) GST_BUFFER_DATA (out), 0); - - gst_adapter_flush (amrnbdec->adapter, block); + g_free (data); /* play */ ret = gst_pad_push (amrnbdec->srcpad, out); } + gst_object_unref (amrnbdec); return ret; + /* ERRORS */ not_negotiated: { + GST_ELEMENT_ERROR (amrnbdec, STREAM, TYPE_NOT_FOUND, (NULL), + ("Decoder is not initialized")); + gst_object_unref (amrnbdec); return GST_FLOW_NOT_NEGOTIATED; } } @@ -237,11 +280,13 @@ gst_amrnbdec_state_change (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!(amrnbdec->handle = Decoder_Interface_init ())) - return GST_STATE_CHANGE_FAILURE; + goto init_failed; break; case GST_STATE_CHANGE_READY_TO_PAUSED: gst_adapter_clear (amrnbdec->adapter); - amrnbdec->ts = 0; + amrnbdec->rate = 0; + amrnbdec->channels = 0; + amrnbdec->ts = -1; break; default: break; @@ -258,4 +303,12 @@ gst_amrnbdec_state_change (GstElement * element, GstStateChange transition) } return ret; + + /* ERRORS */ +init_failed: + { + GST_ELEMENT_ERROR (amrnbdec, LIBRARY, INIT, (NULL), + ("Failed to open AMR Decoder")); + return GST_STATE_CHANGE_FAILURE; + } } diff --git a/ext/amrnb/amrnbdec.h b/ext/amrnb/amrnbdec.h index 826f22ae92..8f89a95e1c 100644 --- a/ext/amrnb/amrnbdec.h +++ b/ext/amrnb/amrnbdec.h @@ -54,6 +54,7 @@ struct _GstAmrnbDec { /* output settings */ gint channels, rate; + gint duration; }; struct _GstAmrnbDecClass {