mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 01:45:33 +00:00
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:
parent
599af07ac7
commit
de433bfdcb
4 changed files with 154 additions and 26 deletions
11
ChangeLog
11
ChangeLog
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue