gst/audioconvert/gstaudioconvert.c: Implement instant setup switching.
authorRonald S. Bultje <rbultje@ronald.bitfreak.net>
Mon, 23 May 2005 17:28:02 +0000 (17:28 +0000)
committerRonald S. Bultje <rbultje@ronald.bitfreak.net>
Mon, 23 May 2005 17:28:02 +0000 (17:28 +0000)
Original commit message from CVS:
* gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init),
(gst_audio_convert_chain), (gst_audio_convert_link_src),
(gst_audio_convert_setcaps):
Implement instant setup switching.

ChangeLog
gst/audioconvert/gstaudioconvert.c

index 89bd979..7baa485 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-05-23  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
+
+       * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init),
+       (gst_audio_convert_chain), (gst_audio_convert_link_src),
+       (gst_audio_convert_setcaps):
+         Implement instant setup switching.
+
 2005-05-19  Ronald S. Bultje  <rbultje@ronald.bitfreak.net>
 
        * gst/playback/gstplaybasebin.c: (probe_triggered):
index 7a1676f..4448c09 100644 (file)
@@ -61,6 +61,8 @@ static void gst_audio_convert_dispose (GObject * obj);
 
 /* gstreamer functions */
 static GstFlowReturn gst_audio_convert_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_audio_convert_link_src (GstAudioConvert * this,
+    GstCaps * sinkcaps, GstAudioConvertCaps * sink_ac_caps);
 static gboolean gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps);
 static GstCaps *gst_audio_convert_fixate (GstPad * pad, GstCaps * caps);
 static GstCaps *gst_audio_convert_getcaps (GstPad * pad);
@@ -195,7 +197,7 @@ gst_audio_convert_init (GstAudioConvert * this)
       gst_pad_new_from_template (gst_static_pad_template_get
       (&gst_audio_convert_src_template), "src");
   gst_pad_set_getcaps_function (this->src, gst_audio_convert_getcaps);
-  gst_pad_set_setcaps_function (this->src, gst_audio_convert_setcaps);
+  //gst_pad_set_setcaps_function (this->src, gst_audio_convert_setcaps);
   gst_pad_set_fixatecaps_function (this->src, gst_audio_convert_fixate);
   gst_element_add_pad (GST_ELEMENT (this), this->src);
 
@@ -235,22 +237,6 @@ gst_audio_convert_chain (GstPad * pad, GstBuffer * buf)
 
   this = GST_AUDIO_CONVERT (GST_OBJECT_PARENT (pad));
 
-  /* FIXME */
-
-#if 0
-  if (!GST_PAD_CAPS (this->sink)) {
-    GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL),
-        ("Sink pad (connected to %s:%s) not negotiated before chain function",
-            GST_DEBUG_PAD_NAME (gst_pad_get_peer (this->sink))));
-    gst_buffer_unref (buf);
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-  if (!GST_PAD_CAPS (this->src)) {
-    gst_buffer_unref (buf);
-    return GST_FLOW_NOT_NEGOTIATED;
-  }
-#endif
-
   /**
    * Theory of operation:
    * - convert the format (endianness, signedness, width, depth) to
@@ -260,6 +246,16 @@ gst_audio_convert_chain (GstPad * pad, GstBuffer * buf)
    */
   GST_STREAM_LOCK (pad);
 
+  if (!GST_RPAD_CAPS (this->sink)) {
+    goto not_negotiated;
+  } else if (!GST_RPAD_CAPS (this->src)) {
+    if (!gst_audio_convert_link_src (this,
+            GST_RPAD_CAPS (this->sink), &this->sinkcaps))
+      goto no_format;
+  } else if (!this->matrix) {
+    gst_audio_convert_setup_matrix (this);
+  }
+
   buf = gst_audio_convert_buffer_to_default_format (this, buf);
   buf = gst_audio_convert_channels (this, buf);
   buf = gst_audio_convert_buffer_from_default_format (this, buf);
@@ -269,6 +265,23 @@ gst_audio_convert_chain (GstPad * pad, GstBuffer * buf)
   GST_STREAM_UNLOCK (pad);
 
   return ret;
+
+not_negotiated:
+  {
+    GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL),
+        ("Pad not negotiated before chain function was called"));
+    gst_buffer_unref (buf);
+    GST_STREAM_UNLOCK (pad);
+    return GST_FLOW_NOT_NEGOTIATED;
+  }
+no_format:
+  {
+    GST_ELEMENT_ERROR (this, CORE, NEGOTIATION, (NULL),
+        ("Could not negotiate format"));
+    gst_buffer_unref (buf);
+    GST_STREAM_UNLOCK (pad);
+    return GST_FLOW_ERROR;
+  }
 }
 
 static GstCaps *
@@ -394,42 +407,23 @@ gst_audio_convert_parse_caps (const GstCaps * gst_caps,
 }
 
 static gboolean
-gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps)
+gst_audio_convert_link_src (GstAudioConvert * this,
+    GstCaps * sinkcaps, GstAudioConvertCaps * sink_ac_caps)
 {
-  GstAudioConvert *this;
-  GstPad *otherpad;
   GstAudioConvertCaps ac_caps = { 0 };
-  GstAudioConvertCaps other_ac_caps = { 0 };
-  GstCaps **other_prefered, **prefered;
-
-  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
-  g_return_val_if_fail (GST_IS_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)), FALSE);
-  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
 
-  this = GST_AUDIO_CONVERT (GST_OBJECT_PARENT (pad));
-
-  /* we'll need a new matrix after every new negotiation */
-  gst_audio_convert_unset_matrix (this);
-
-  ac_caps.pos = NULL;
-  if (!gst_audio_convert_parse_caps (caps, &ac_caps))
-    return FALSE;
-
-  otherpad = (pad == this->src ? this->sink : this->src);
-  prefered = (pad == this->src) ? &this->src_prefered : &this->sink_prefered;
-  other_prefered =
-      (pad == this->src) ? &this->sink_prefered : &this->src_prefered;
-
-  *prefered = caps;
-
-  /* check passthrough */
-  if (gst_pad_peer_accept_caps (otherpad, caps)) {
+  if (gst_pad_peer_accept_caps (this->src, sinkcaps)) {
     /* great, so that will be our suggestion then */
-    *other_prefered = gst_caps_ref (caps);
+    this->src_prefered = gst_caps_ref (sinkcaps);
+    gst_caps_replace (&GST_RPAD_CAPS (this->src), sinkcaps);
+    ac_caps = *sink_ac_caps;
+    if (ac_caps.pos) {
+      ac_caps.pos = g_memdup (ac_caps.pos, sizeof (gint) * ac_caps.channels);
+    }
   } else {
     /* nope, find something we can convert to and the peer can
      * accept. */
-    GstCaps *othercaps = gst_pad_peer_get_caps (otherpad);
+    GstCaps *othercaps = gst_pad_peer_get_caps (this->src);
 
     if (othercaps) {
       /* peel off first one */
@@ -439,12 +433,12 @@ gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps)
       gst_caps_unref (othercaps);
 
       /* set the rate on the caps, this has to work */
-      gst_structure_set (structure, "rate", G_TYPE_INT, ac_caps.rate, NULL);
-      gst_structure_set (structure, "channels", G_TYPE_INT, ac_caps.channels,
-          NULL);
+      gst_structure_set (structure,
+          "rate", G_TYPE_INT, sink_ac_caps->rate,
+          "channels", G_TYPE_INT, sink_ac_caps->channels, NULL);
 
       if (strcmp (gst_structure_get_name (structure), "audio/x-raw-float") == 0) {
-        if (!ac_caps.is_int) {
+        if (!sink_ac_caps->is_int) {
           /* copy over */
           gst_structure_set (structure, "buffer-frames", G_TYPE_INT,
               ac_caps.buffer_frames, NULL);
@@ -455,25 +449,48 @@ gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps)
       }
 
       /* this will be our suggestion */
-      *other_prefered = targetcaps;
-      if (!gst_audio_convert_parse_caps (targetcaps, &other_ac_caps))
+      this->src_prefered = targetcaps;
+      if (!gst_audio_convert_parse_caps (targetcaps, &ac_caps))
         return FALSE;
-      gst_caps_replace (&GST_RPAD_CAPS (otherpad), targetcaps);
+      gst_caps_replace (&GST_RPAD_CAPS (this->src), targetcaps);
     }
   }
-  if (this->sink == pad) {
-    g_free (this->srccaps.pos);
-    this->srccaps = other_ac_caps;
+  this->srccaps = ac_caps;
+
+  GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, sinkcaps);
+
+  return TRUE;
+}
+
+static gboolean
+gst_audio_convert_setcaps (GstPad * pad, GstCaps * caps)
+{
+  GstAudioConvert *this;
+  GstAudioConvertCaps ac_caps = { 0 };
+  gboolean res;
+
+  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);
+  g_return_val_if_fail (GST_IS_AUDIO_CONVERT (GST_OBJECT_PARENT (pad)), FALSE);
+  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
+
+  this = GST_AUDIO_CONVERT (GST_OBJECT_PARENT (pad));
+
+  /* we'll need a new matrix after every new negotiation */
+  gst_audio_convert_unset_matrix (this);
+
+  ac_caps.pos = NULL;
+  if (!gst_audio_convert_parse_caps (caps, &ac_caps))
+    return FALSE;
+
+  this->sink_prefered = caps;
+
+  if ((res = gst_audio_convert_link_src (this, caps, &ac_caps))) {
     this->sinkcaps = ac_caps;
-  } else {
-    g_free (this->sinkcaps.pos);
-    this->srccaps = ac_caps;
-    this->sinkcaps = other_ac_caps;
+
+    GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, caps);
   }
 
-  GST_DEBUG_OBJECT (this, "negotiated pad to %" GST_PTR_FORMAT, caps);
-  gst_audio_convert_setup_matrix (this);
-  return TRUE;
+  return res;
 }
 
 /* tries to fixate the given field of the given caps to the given int value */