]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blobdiff - ext/amrnb/amrnbenc.c
add test for amrnbenc, enable test infrastructure, and fix a leak
[glsdk/gst-plugins-ugly0-10.git] / ext / amrnb / amrnbenc.c
index 6266fe70a335b522c356b7892dedd10835c03af8..3145f79f4c19524ee3b67a00104e89191d062eb6 100644 (file)
@@ -37,8 +37,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("audio/x-amr-nb, "
-        "rate = (int) 8000, " "channels = (int) 1")
+    GST_STATIC_CAPS ("audio/AMR, " "rate = (int) 8000, " "channels = (int) 1")
     );
 
 static void gst_amrnbenc_base_init (GstAmrnbEncClass * klass);
@@ -48,7 +47,8 @@ static void gst_amrnbenc_finalize (GObject * object);
 
 static GstFlowReturn gst_amrnbenc_chain (GstPad * pad, GstBuffer * buffer);
 static gboolean gst_amrnbenc_setcaps (GstPad * pad, GstCaps * caps);
-static GstElementStateReturn gst_amrnbenc_state_change (GstElement * element);
+static GstStateChangeReturn gst_amrnbenc_state_change (GstElement * element,
+    GstStateChange transition);
 
 static GstElementClass *parent_class = NULL;
 
@@ -82,8 +82,8 @@ gst_amrnbenc_base_init (GstAmrnbEncClass * klass)
 {
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
   GstElementDetails gst_amrnbenc_details = {
-    "AMR-NB decoder",
-    "Codec/Decoder/Audio",
+    "AMR-NB encoder",
+    "Codec/Encoder/Audio",
     "Adaptive Multi-Rate Narrow-Band audio encoder",
     "Ronald Bultje <rbultje@ronald.bitfreak.net>, "
         "Wim Taymans <wim@fluendo.com>"
@@ -103,7 +103,7 @@ gst_amrnbenc_class_init (GstAmrnbEncClass * klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
-  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
+  parent_class = g_type_class_peek_parent (klass);
 
   object_class->finalize = gst_amrnbenc_finalize;
 
@@ -114,17 +114,13 @@ static void
 gst_amrnbenc_init (GstAmrnbEnc * amrnbenc)
 {
   /* create the sink pad */
-  amrnbenc->sinkpad =
-      gst_pad_new_from_template (gst_static_pad_template_get (&sink_template),
-      "sink");
+  amrnbenc->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
   gst_pad_set_setcaps_function (amrnbenc->sinkpad, gst_amrnbenc_setcaps);
   gst_pad_set_chain_function (amrnbenc->sinkpad, gst_amrnbenc_chain);
   gst_element_add_pad (GST_ELEMENT (amrnbenc), amrnbenc->sinkpad);
 
   /* create the src pad */
-  amrnbenc->srcpad =
-      gst_pad_new_from_template (gst_static_pad_template_get (&src_template),
-      "src");
+  amrnbenc->srcpad = gst_pad_new_from_static_template (&src_template, "src");
   gst_pad_use_fixed_caps (amrnbenc->srcpad);
   gst_element_add_pad (GST_ELEMENT (amrnbenc), amrnbenc->srcpad);
 
@@ -132,9 +128,6 @@ gst_amrnbenc_init (GstAmrnbEnc * amrnbenc)
 
   /* init rest */
   amrnbenc->handle = NULL;
-  amrnbenc->channels = 0;
-  amrnbenc->rate = 0;
-  amrnbenc->ts = 0;
 }
 
 static void
@@ -174,10 +167,14 @@ gst_amrnbenc_setcaps (GstPad * pad, GstCaps * caps)
   }
 
   /* create reverse caps */
-  copy = gst_caps_new_simple ("audio/x-amr-nb",
+  copy = gst_caps_new_simple ("audio/AMR",
       "channels", G_TYPE_INT, amrnbenc->channels,
       "rate", G_TYPE_INT, amrnbenc->rate, NULL);
 
+  /* precalc duration as it's constant now */
+  amrnbenc->duration = gst_util_uint64_scale_int (160, GST_SECOND,
+      amrnbenc->rate * amrnbenc->channels);
+
   gst_pad_set_caps (amrnbenc->srcpad, copy);
   gst_caps_unref (copy);
 
@@ -192,9 +189,20 @@ gst_amrnbenc_chain (GstPad * pad, GstBuffer * buffer)
 
   amrnbenc = GST_AMRNBENC (GST_PAD_PARENT (pad));
 
+  g_return_val_if_fail (amrnbenc->handle, GST_FLOW_WRONG_STATE);
+
   if (amrnbenc->rate == 0 || amrnbenc->channels == 0)
     goto not_negotiated;
 
+  /* discontinuity clears adapter, FIXME, maybe we can set some
+   * encoder flag to mask the discont. */
+  if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
+    gst_adapter_clear (amrnbenc->adapter);
+    amrnbenc->ts = 0;
+  }
+
+  /* take latest timestamp, FIXME timestamp is the one of the
+   * first buffer in the adapter. */
   if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
     amrnbenc->ts = GST_BUFFER_TIMESTAMP (buffer);
 
@@ -207,52 +215,56 @@ gst_amrnbenc_chain (GstPad * pad, GstBuffer * buffer)
     guint8 *data;
     gint outsize;
 
-    /* get output,  max size is 32 */
+    /* get output, max size is 32 */
     out = gst_buffer_new_and_alloc (32);
-    GST_BUFFER_DURATION (out) = GST_SECOND * 160 /
-        (amrnbenc->rate * amrnbenc->channels);
+    GST_BUFFER_DURATION (out) = amrnbenc->duration;
     GST_BUFFER_TIMESTAMP (out) = amrnbenc->ts;
-    amrnbenc->ts += GST_BUFFER_DURATION (out);
-    gst_buffer_set_caps (out, gst_pad_get_caps (amrnbenc->srcpad));
+    if (amrnbenc->ts != -1)
+      amrnbenc->ts += amrnbenc->duration;
+    gst_buffer_set_caps (out, GST_PAD_CAPS (amrnbenc->srcpad));
 
-    data = (guint8 *) gst_adapter_peek (amrnbenc->adapter, 320);
+    /* The AMR encoder actually writes into the source data buffers it gets */
+    data = gst_adapter_take (amrnbenc->adapter, 320);
 
-    /* decode */
+    /* encode */
     outsize = Encoder_Interface_Encode (amrnbenc->handle, MR122, (short *) data,
         (guint8 *) GST_BUFFER_DATA (out), 0);
 
-    gst_adapter_flush (amrnbenc->adapter, 320);
+    g_free (data);
 
     GST_BUFFER_SIZE (out) = outsize;
 
     /* play */
-    ret = gst_pad_push (amrnbenc->srcpad, out);
+    if ((ret = gst_pad_push (amrnbenc->srcpad, out)) != GST_FLOW_OK)
+      break;
   }
-
   return ret;
 
+  /* ERRORS */
 not_negotiated:
   {
+    GST_ELEMENT_ERROR (amrnbenc, STREAM, TYPE_NOT_FOUND,
+        (NULL), ("unknown type"));
     return GST_FLOW_NOT_NEGOTIATED;
   }
 }
 
-static GstElementStateReturn
-gst_amrnbenc_state_change (GstElement * element)
+static GstStateChangeReturn
+gst_amrnbenc_state_change (GstElement * element, GstStateChange transition)
 {
   GstAmrnbEnc *amrnbenc;
-  GstElementStateReturn ret;
-  gint transition;
+  GstStateChangeReturn ret;
 
   amrnbenc = GST_AMRNBENC (element);
-  transition = GST_STATE_TRANSITION (element);
 
   switch (transition) {
-    case GST_STATE_NULL_TO_READY:
+    case GST_STATE_CHANGE_NULL_TO_READY:
       if (!(amrnbenc->handle = Encoder_Interface_init (0)))
-        return GST_STATE_FAILURE;
+        return GST_STATE_CHANGE_FAILURE;
       break;
-    case GST_STATE_READY_TO_PAUSED:
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      amrnbenc->rate = 0;
+      amrnbenc->channels = 0;
       amrnbenc->ts = 0;
       gst_adapter_clear (amrnbenc->adapter);
       break;
@@ -260,10 +272,10 @@ gst_amrnbenc_state_change (GstElement * element)
       break;
   }
 
-  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
   switch (transition) {
-    case GST_STATE_READY_TO_NULL:
+    case GST_STATE_CHANGE_READY_TO_NULL:
       Encoder_Interface_exit (amrnbenc->handle);
       break;
     default: