Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / ext / speex / gstspeexenc.c
index e4eda25..f427f08 100644 (file)
@@ -132,6 +132,8 @@ static GstFlowReturn gst_speex_enc_handle_frame (GstAudioEncoder * enc,
     GstBuffer * in_buf);
 static gboolean gst_speex_enc_sink_event (GstAudioEncoder * enc,
     GstEvent * event);
+static GstFlowReturn
+gst_speex_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer);
 
 #define gst_speex_enc_parent_class parent_class
 G_DEFINE_TYPE_WITH_CODE (GstSpeexEnc, gst_speex_enc, GST_TYPE_AUDIO_ENCODER,
@@ -158,6 +160,7 @@ gst_speex_enc_class_init (GstSpeexEncClass * klass)
   base_class->set_format = GST_DEBUG_FUNCPTR (gst_speex_enc_set_format);
   base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_speex_enc_handle_frame);
   base_class->event = GST_DEBUG_FUNCPTR (gst_speex_enc_sink_event);
+  base_class->pre_push = GST_DEBUG_FUNCPTR (gst_speex_enc_pre_push);
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_QUALITY,
       g_param_spec_float ("quality", "Quality", "Encoding quality",
@@ -244,7 +247,7 @@ gst_speex_enc_start (GstAudioEncoder * benc)
 
   GST_DEBUG_OBJECT (enc, "start");
   speex_bits_init (&enc->bits);
-  enc->tags = gst_tag_list_new ();
+  enc->tags = gst_tag_list_new_empty ();
   enc->header_sent = FALSE;
 
   return TRUE;
@@ -264,6 +267,10 @@ gst_speex_enc_stop (GstAudioEncoder * benc)
   speex_bits_destroy (&enc->bits);
   gst_tag_list_free (enc->tags);
   enc->tags = NULL;
+  g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
+  enc->headers = NULL;
+
+  gst_tag_setter_reset_tags (GST_TAG_SETTER (enc));
 
   return TRUE;
 }
@@ -336,7 +343,7 @@ gst_speex_enc_create_metadata_buffer (GstSpeexEnc * enc)
       gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc)));
 
   if (merged_tags == NULL)
-    merged_tags = gst_tag_list_new ();
+    merged_tags = gst_tag_list_new_empty ();
 
   GST_DEBUG_OBJECT (enc, "merged   tags = %" GST_PTR_FORMAT, merged_tags);
   comments = gst_tag_list_to_vorbiscomment_buffer (merged_tags, NULL,
@@ -525,7 +532,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
   gint frame_size = enc->frame_size;
   gint bytes = frame_size * 2 * enc->channels, samples;
   gint outsize, written, dtx_ret = 0;
-  guint8 *data, *bdata, *outdata;
+  guint8 *data, *data0 = NULL, *bdata, *outdata;
   gsize bsize, size;
   GstBuffer *outbuf;
   GstFlowReturn ret = GST_FLOW_OK;
@@ -537,7 +544,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
       GST_DEBUG_OBJECT (enc, "draining; adding silence samples");
 
       size = ((bsize / bytes) + 1) * bytes;
-      data = g_malloc0 (size);
+      data0 = data = g_malloc0 (size);
       memcpy (data, bdata, bsize);
       gst_buffer_unmap (buf, bdata, bsize);
       bdata = NULL;
@@ -601,6 +608,7 @@ gst_speex_enc_encode (GstSpeexEnc * enc, GstBuffer * buf)
       outbuf, samples);
 
 done:
+  g_free (data0);
   return ret;
 }
 
@@ -698,18 +706,16 @@ gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
     /* negotiate with these caps */
     GST_DEBUG_OBJECT (enc, "here are the caps: %" GST_PTR_FORMAT, caps);
 
-    /* push out buffers */
-    ret = gst_speex_enc_push_buffer (enc, buf1);
-
-    if (ret != GST_FLOW_OK) {
-      gst_buffer_unref (buf2);
-      goto done;
-    }
-
-    ret = gst_speex_enc_push_buffer (enc, buf2);
+    gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (enc), caps);
+    gst_caps_unref (caps);
 
-    if (ret != GST_FLOW_OK)
-      goto done;
+    /* push out buffers */
+    /* store buffers for later pre_push sending */
+    g_slist_foreach (enc->headers, (GFunc) gst_buffer_unref, NULL);
+    enc->headers = NULL;
+    GST_DEBUG_OBJECT (enc, "storing header buffers");
+    enc->headers = g_slist_prepend (enc->headers, buf2);
+    enc->headers = g_slist_prepend (enc->headers, buf1);
 
     enc->header_sent = TRUE;
   }
@@ -719,10 +725,38 @@ gst_speex_enc_handle_frame (GstAudioEncoder * benc, GstBuffer * buf)
 
   ret = gst_speex_enc_encode (enc, buf);
 
-done:
   return ret;
 }
 
+static GstFlowReturn
+gst_speex_enc_pre_push (GstAudioEncoder * benc, GstBuffer ** buffer)
+{
+  GstSpeexEnc *enc;
+  GstFlowReturn ret = GST_FLOW_OK;
+
+  enc = GST_SPEEX_ENC (benc);
+
+  /* FIXME 0.11 ? get rid of this special ogg stuff and have it
+   * put and use 'codec data' in caps like anything else,
+   * with all the usual out-of-band advantage etc */
+  if (G_UNLIKELY (enc->headers)) {
+    GSList *header = enc->headers;
+
+    /* try to push all of these, if we lose one, might as well lose all */
+    while (header) {
+      if (ret == GST_FLOW_OK)
+        ret = gst_speex_enc_push_buffer (enc, header->data);
+      else
+        gst_speex_enc_push_buffer (enc, header->data);
+      header = g_slist_next (header);
+    }
+
+    g_slist_free (enc->headers);
+    enc->headers = NULL;
+  }
+
+  return ret;
+}
 
 static void
 gst_speex_enc_get_property (GObject * object, guint prop_id, GValue * value,