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",
"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)
{
}
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)
{
- 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);
+static gboolean
+gst_gsmenc_start (GstAudioEncoder * enc)
+{
+ GstGSMEnc *gsmenc = GST_GSMENC (enc);
+ gint use_wav49;
- 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 ();
use_wav49 = 0;
gsm_option (gsmenc->state, GSM_OPT_WAV49, &use_wav49);
- gsmenc->adapter = gst_adapter_new ();
- gsmenc->next_ts = 0;
+ return TRUE;
}
-static void
-gst_gsmenc_finalize (GObject * object)
+static gboolean
+gst_gsmenc_stop (GstAudioEncoder * enc)
{
- GstGSMEnc *gsmenc;
+ GstGSMEnc *gsmenc = GST_GSMENC (enc);
- gsmenc = GST_GSMENC (object);
-
- g_object_unref (gsmenc->adapter);
+ GST_DEBUG_OBJECT (enc, "stop");
gsm_destroy (gsmenc->state);
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ return TRUE;
}
static gboolean
-gst_gsmenc_setcaps (GstPad * pad, GstCaps * caps)
+gst_gsmenc_set_format (GstAudioEncoder * benc, GstAudioInfo * info)
{
GstGSMEnc *gsmenc;
GstCaps *srccaps;
- gsmenc = GST_GSMENC (gst_pad_get_parent (pad));
+ 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);
- gst_pad_set_caps (gsmenc->srcpad, srccaps);
-
- gst_object_unref (gsmenc);
+ /* 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);
+ /* 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_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);
+ 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;
+ }
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (gsmenc->srcpad));
+ outbuf = gst_buffer_new_and_alloc (33 * sizeof (gsm_byte));
- GST_DEBUG_OBJECT (gsmenc, "Pushing buffer of size %d",
- GST_BUFFER_SIZE (outbuf));
+ /* 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));
- ret = gst_pad_push (gsmenc->srcpad, outbuf);
- }
+ GST_LOG_OBJECT (gsmenc, "encoded to %d bytes", GST_BUFFER_SIZE (outbuf));
- gst_object_unref (gsmenc);
+ ret = gst_audio_encoder_finish_frame (benc, outbuf, 160);
+done:
return ret;
}