gsmenc: port to audioencoder
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Tue, 17 Jan 2012 17:32:23 +0000 (18:32 +0100)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Tue, 17 Jan 2012 17:34:43 +0000 (18:34 +0100)
ext/gsm/gstgsmenc.c
ext/gsm/gstgsmenc.h

index 52d0b55..ea8c43c 100644 (file)
@@ -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)
 {
-  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 ();
 
@@ -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;
+  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;
 }
index ba3b089..28b8e2e 100644 (file)
@@ -21,7 +21,7 @@
 #define __GST_GSMENC_H__
 
 #include <gst/gst.h>
-#include <gst/base/gstadapter.h>
+#include <gst/audio/gstaudioencoder.h>
 
 #ifdef GSM_HEADER_IN_SUBDIR
 #include <gsm/gsm.h>
@@ -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);