capsfilter: Send caps before segment
authorNicolas Dufresne <nicolas.dufresne@collabora.co.uk>
Thu, 9 May 2013 01:45:08 +0000 (21:45 -0400)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Thu, 9 May 2013 07:14:49 +0000 (09:14 +0200)
In the case the source has no caps, caps must be sent before segment. This
fixes few unit tests that where failing due to the new misordering warning.

https://bugzilla.gnome.org/show_bug.cgi?id=699968

plugins/elements/gstcapsfilter.c
plugins/elements/gstcapsfilter.h

index 5ec1e30..b09b085 100644 (file)
@@ -83,6 +83,8 @@ static GstFlowReturn gst_capsfilter_transform_ip (GstBaseTransform * base,
     GstBuffer * buf);
 static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans,
     GstBuffer * input, GstBuffer ** buf);
+static gboolean gst_capsfilter_sink_event (GstBaseTransform * trans,
+    GstEvent * event);
 
 static void
 gst_capsfilter_class_init (GstCapsFilterClass * klass)
@@ -121,6 +123,7 @@ gst_capsfilter_class_init (GstCapsFilterClass * klass)
   trans_class->accept_caps = GST_DEBUG_FUNCPTR (gst_capsfilter_accept_caps);
   trans_class->prepare_output_buffer =
       GST_DEBUG_FUNCPTR (gst_capsfilter_prepare_buf);
+  trans_class->sink_event = GST_DEBUG_FUNCPTR (gst_capsfilter_sink_event);
 }
 
 static void
@@ -193,6 +196,7 @@ gst_capsfilter_dispose (GObject * object)
   GstCapsFilter *filter = GST_CAPSFILTER (object);
 
   gst_caps_replace (&filter->filter_caps, NULL);
+  gst_event_replace (&filter->pending_segment, NULL);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -268,11 +272,11 @@ gst_capsfilter_transform_ip (GstBaseTransform * base, GstBuffer * buf)
   return GST_FLOW_OK;
 }
 
-/* Output buffer preparation... if the buffer has no caps, and
- * our allowed output caps is fixed, then give the caps to the
- * buffer.
- * This ensures that outgoing buffers have caps if we can, so
- * that pipelines like:
+/* Ouput buffer preparation ... if the buffer has no caps, and our allowed
+ * output caps is fixed, then send the caps downstream, making sure caps are
+ * sent before segment event.
+ *
+ * This ensures that caps event is sent if we can, so that pipelines like:
  *   gst-launch filesrc location=rawsamples.raw !
  *       audio/x-raw,format=S16LE,rate=48000,channels=2 ! alsasink
  * will work.
@@ -287,11 +291,17 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
   *buf = input;
 
   if (!gst_pad_has_current_caps (trans->sinkpad)) {
-    /* Buffer has no caps. See if the output pad only supports fixed caps */
+    /* No caps. See if the output pad only supports fixed caps */
+    GstCapsFilter *filter = GST_CAPSFILTER (trans);
     GstCaps *out_caps;
+    GstEvent *pending_segment = filter->pending_segment;
 
     GST_LOG_OBJECT (trans, "Input pad does not have caps");
 
+    filter->pending_segment = NULL;
+    g_return_val_if_fail (pending_segment != NULL || trans->have_segment,
+        GST_FLOW_ERROR);
+
     out_caps = gst_pad_get_current_caps (trans->srcpad);
     if (out_caps == NULL) {
       out_caps = gst_pad_get_allowed_caps (trans->srcpad);
@@ -307,6 +317,11 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
       if (!gst_pad_has_current_caps (trans->srcpad))
         if (!gst_pad_set_caps (trans->srcpad, out_caps))
           ret = GST_FLOW_NOT_NEGOTIATED;
+
+      if (pending_segment)
+        GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans,
+            pending_segment);
+
       gst_caps_unref (out_caps);
     } else {
       gchar *caps_str = gst_caps_to_string (out_caps);
@@ -315,13 +330,33 @@ gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input,
           GST_PTR_FORMAT, out_caps);
       gst_caps_unref (out_caps);
 
-      ret = GST_FLOW_ERROR;
       GST_ELEMENT_ERROR (trans, STREAM, FORMAT,
           ("Filter caps do not completely specify the output format"),
           ("Output caps are unfixed: %s", caps_str));
+
       g_free (caps_str);
+      gst_event_unref (pending_segment);
+
+      ret = GST_FLOW_ERROR;
     }
   }
 
   return ret;
 }
+
+/* Queue the segment event if there was no caps event */
+static gboolean
+gst_capsfilter_sink_event (GstBaseTransform * trans, GstEvent * event)
+{
+  if (GST_EVENT_TYPE (event) != GST_EVENT_SEGMENT)
+    goto done;
+
+  if (!gst_pad_has_current_caps (trans->sinkpad)) {
+    GST_LOG_OBJECT (trans, "Got segment without caps, queue segment event");
+    gst_event_replace (&GST_CAPSFILTER (trans)->pending_segment, event);
+    return TRUE;
+  }
+
+done:
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event);
+}
index a620541..e3f5853 100644 (file)
@@ -53,6 +53,7 @@ struct _GstCapsFilter {
   GstBaseTransform trans;
 
   GstCaps *filter_caps;
+  GstEvent *pending_segment;
 };
 
 struct _GstCapsFilterClass {