From 0acfa3cc1e6b5e3f6bc40ad8637df20f1b8f65d7 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 17 Jan 2012 18:32:23 +0100 Subject: [PATCH] gsmenc: port to audioencoder --- ext/gsm/gstgsmenc.c | 174 ++++++++++++++++++-------------------------- ext/gsm/gstgsmenc.h | 12 +-- 2 files changed, 74 insertions(+), 112 deletions(-) diff --git a/ext/gsm/gstgsmenc.c b/ext/gsm/gstgsmenc.c index 52d0b55b22..ea8c43c288 100644 --- a/ext/gsm/gstgsmenc.c +++ b/ext/gsm/gstgsmenc.c @@ -43,39 +43,12 @@ enum ARG_0 }; -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 gboolean gst_gsmenc_setcaps (GstPad * pad, GstCaps * caps); -static GstFlowReturn gst_gsmenc_chain (GstPad * pad, GstBuffer * buf); - -static GstElementClass *parent_class = NULL; - -GType -gst_gsmenc_get_type (void) -{ - static GType gsmenc_type = 0; - - if (!gsmenc_type) { - static const GTypeInfo gsmenc_info = { - sizeof (GstGSMEncClass), - gst_gsmenc_base_init, - NULL, - (GClassInitFunc) gst_gsmenc_class_init, - NULL, - NULL, - sizeof (GstGSMEnc), - 0, - (GInstanceInitFunc) gst_gsmenc_init, - }; - - gsmenc_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstGSMEnc", &gsmenc_info, 0); - } - return gsmenc_type; -} +static gboolean gst_gsmenc_start (GstAudioEncoder * enc); +static gboolean gst_gsmenc_stop (GstAudioEncoder * enc); +static gboolean gst_gsmenc_set_format (GstAudioEncoder * enc, + GstAudioInfo * info); +static GstFlowReturn gst_gsmenc_handle_frame (GstAudioEncoder * enc, + GstBuffer * in_buf); static GstStaticPadTemplate gsmenc_src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -95,6 +68,9 @@ GST_STATIC_PAD_TEMPLATE ("sink", "depth = (int) 16, " "rate = (int) 8000, " "channels = (int) 1") ); +GST_BOILERPLATE (GstGSMEnc, gst_gsmenc, GstAudioEncoder, + GST_TYPE_AUDIO_ENCODER); + static void gst_gsmenc_base_init (gpointer g_class) { @@ -110,34 +86,32 @@ gst_gsmenc_base_init (gpointer g_class) } static void -gst_gsmenc_class_init (GstGSMEnc * klass) +gst_gsmenc_class_init (GstGSMEncClass * klass) { - GObjectClass *gobject_class; + GstAudioEncoderClass *base_class; - gobject_class = (GObjectClass *) klass; + base_class = (GstAudioEncoderClass *) klass; - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_gsmenc_finalize; + base_class->start = GST_DEBUG_FUNCPTR (gst_gsmenc_start); + base_class->stop = GST_DEBUG_FUNCPTR (gst_gsmenc_stop); + base_class->set_format = GST_DEBUG_FUNCPTR (gst_gsmenc_set_format); + base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_gsmenc_handle_frame); GST_DEBUG_CATEGORY_INIT (gsmenc_debug, "gsmenc", 0, "GSM Encoder"); } static void -gst_gsmenc_init (GstGSMEnc * gsmenc) +gst_gsmenc_init (GstGSMEnc * gsmenc, GstGSMEncClass * klass) { +} + +static gboolean +gst_gsmenc_start (GstAudioEncoder * enc) +{ + GstGSMEnc *gsmenc = GST_GSMENC (enc); gint use_wav49; - /* create the sink and src pads */ - gsmenc->sinkpad = - gst_pad_new_from_static_template (&gsmenc_sink_template, "sink"); - gst_pad_set_chain_function (gsmenc->sinkpad, gst_gsmenc_chain); - gst_pad_set_setcaps_function (gsmenc->sinkpad, gst_gsmenc_setcaps); - gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->sinkpad); - - gsmenc->srcpad = - gst_pad_new_from_static_template (&gsmenc_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (gsmenc), gsmenc->srcpad); + GST_DEBUG_OBJECT (enc, "start"); gsmenc->state = gsm_create (); @@ -145,78 +119,72 @@ gst_gsmenc_init (GstGSMEnc * gsmenc) 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); + return TRUE; } static gboolean -gst_gsmenc_setcaps (GstPad * pad, GstCaps * caps) +gst_gsmenc_stop (GstAudioEncoder * enc) { - GstGSMEnc *gsmenc; - GstCaps *srccaps; + GstGSMEnc *gsmenc = GST_GSMENC (enc); - gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); - - srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template); - - gst_pad_set_caps (gsmenc->srcpad, srccaps); - - gst_object_unref (gsmenc); + GST_DEBUG_OBJECT (enc, "stop"); + gsm_destroy (gsmenc->state); return TRUE; } +static gboolean +gst_gsmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info) +{ + GstGSMEnc *gsmenc; + GstCaps *srccaps; + + gsmenc = GST_GSMENC (benc); + + srccaps = gst_static_pad_template_get_caps (&gsmenc_src_template); + gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (benc), srccaps); + + /* report needs to base class */ + gst_audio_encoder_set_frame_samples_min (benc, 160); + gst_audio_encoder_set_frame_samples_max (benc, 160); + gst_audio_encoder_set_frame_max (benc, 1); + + return TRUE; +} static GstFlowReturn -gst_gsmenc_chain (GstPad * pad, GstBuffer * buf) +gst_gsmenc_handle_frame (GstAudioEncoder * benc, GstBuffer * buffer) { GstGSMEnc *gsmenc; gsm_signal *data; GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf; - gsmenc = GST_GSMENC (gst_pad_get_parent (pad)); + gsmenc = GST_GSMENC (benc); - 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 */ - 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_CAPS (gsmenc->srcpad)); - - GST_DEBUG_OBJECT (gsmenc, "Pushing buffer of size %d", - GST_BUFFER_SIZE (outbuf)); - - ret = gst_pad_push (gsmenc->srcpad, outbuf); + /* we don't deal with squeezing remnants, so simply discard those */ + if (G_UNLIKELY (buffer == NULL)) { + GST_DEBUG_OBJECT (gsmenc, "no data"); + goto done; } - gst_object_unref (gsmenc); + if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 320)) { + GST_DEBUG_OBJECT (gsmenc, "discarding trailing data %d", + GST_BUFFER_SIZE (buffer)); + ret = gst_audio_encoder_finish_frame (benc, NULL, -1); + goto done; + } + outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte)); + + /* encode 160 16-bit samples into 33 bytes */ + data = (gsm_signal *) GST_BUFFER_DATA (buffer); + gsm_encode (gsmenc->state, data, (gsm_byte *) GST_BUFFER_DATA (outbuf)); + + GST_LOG_OBJECT (gsmenc, "encoded to %d bytes", GST_BUFFER_SIZE (outbuf)); + + ret = gst_audio_encoder_finish_frame (benc, outbuf, 160); + +done: return ret; } diff --git a/ext/gsm/gstgsmenc.h b/ext/gsm/gstgsmenc.h index ba3b089b7a..28b8e2e297 100644 --- a/ext/gsm/gstgsmenc.h +++ b/ext/gsm/gstgsmenc.h @@ -21,7 +21,7 @@ #define __GST_GSMENC_H__ #include -#include +#include #ifdef GSM_HEADER_IN_SUBDIR #include @@ -47,20 +47,14 @@ typedef struct _GstGSMEncClass GstGSMEncClass; struct _GstGSMEnc { - GstElement element; - - /* pads */ - GstPad *sinkpad, *srcpad; - GstAdapter *adapter; + GstAudioEncoder element; gsm state; - GstClockTime next_ts; - gboolean firstBuf; }; struct _GstGSMEncClass { - GstElementClass parent_class; + GstAudioEncoderClass parent_class; }; GType gst_gsmenc_get_type (void);