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.
This commit is contained in:
Wim Taymans 2006-03-29 16:54:12 +00:00
parent 599af07ac7
commit de433bfdcb
4 changed files with 154 additions and 26 deletions

View file

@ -1,3 +1,14 @@
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>

View file

@ -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;

View file

@ -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

View file

@ -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);
}