plugins/elements/gstinputselector.c: Add pad property to configure behaviour of the...
authorWim Taymans <wim.taymans@gmail.com>
Thu, 20 Mar 2008 17:07:07 +0000 (17:07 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Fri, 31 Dec 2010 00:53:17 +0000 (00:53 +0000)
Original commit message from CVS:
* plugins/elements/gstinputselector.c: (gst_selector_pad_class_init),
(gst_selector_pad_init), (gst_selector_pad_set_property),
(gst_selector_pad_get_property), (gst_selector_pad_event),
(gst_selector_pad_bufferalloc), (gst_selector_pad_chain),
(gst_input_selector_set_active_pad):
Add pad property to configure behaviour of the unselected pad, it can
return OK or NOT_LINKED, based on the use case.

plugins/elements/gstinputselector.c

index 8f6bee9..852a9be 100644 (file)
@@ -72,12 +72,15 @@ enum
   PROP_LAST
 };
 
+#define DEFAULT_PAD_ALWAYS_OK  TRUE
+
 enum
 {
   PROP_PAD_0,
   PROP_PAD_RUNNING_TIME,
   PROP_PAD_TAGS,
   PROP_PAD_ACTIVE,
+  PROP_PAD_ALWAYS_OK,
   PROP_PAD_LAST
 };
 
@@ -121,6 +124,7 @@ struct _GstSelectorPad
   gboolean active;              /* when buffer have passed the pad */
   gboolean eos;                 /* when EOS has been received */
   gboolean discont;             /* after switching we create a discont */
+  gboolean always_ok;
   GstSegment segment;           /* the current segment on the pad */
   GstTagList *tags;             /* last tags received on the pad */
 
@@ -137,6 +141,8 @@ static void gst_selector_pad_init (GstSelectorPad * pad);
 static void gst_selector_pad_finalize (GObject * object);
 static void gst_selector_pad_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
+static void gst_selector_pad_set_property (GObject * object,
+    guint prop_id, const GValue * value, GParamSpec * pspec);
 
 static GstPadClass *selector_pad_parent_class = NULL;
 
@@ -187,6 +193,8 @@ gst_selector_pad_class_init (GstSelectorPadClass * klass)
 
   gobject_class->get_property =
       GST_DEBUG_FUNCPTR (gst_selector_pad_get_property);
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_selector_pad_set_property);
 
   g_object_class_install_property (gobject_class, PROP_PAD_RUNNING_TIME,
       g_param_spec_int64 ("running-time", "Running time",
@@ -198,11 +206,16 @@ gst_selector_pad_class_init (GstSelectorPadClass * klass)
   g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE,
       g_param_spec_boolean ("active", "Active",
           "If the pad is currently active", FALSE, G_PARAM_READABLE));
+  g_object_class_install_property (gobject_class, PROP_PAD_ALWAYS_OK,
+      g_param_spec_boolean ("always-ok", "Always OK",
+          "Make an inactive pad return OK instead of NOT_LINKED",
+          DEFAULT_PAD_ALWAYS_OK, G_PARAM_READWRITE));
 }
 
 static void
 gst_selector_pad_init (GstSelectorPad * pad)
 {
+  pad->always_ok = DEFAULT_PAD_ALWAYS_OK;
   gst_selector_pad_reset (pad);
 }
 
@@ -220,6 +233,24 @@ gst_selector_pad_finalize (GObject * object)
 }
 
 static void
+gst_selector_pad_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object);
+
+  switch (prop_id) {
+    case PROP_PAD_ALWAYS_OK:
+      GST_OBJECT_LOCK (object);
+      spad->always_ok = g_value_get_boolean (value);
+      GST_OBJECT_UNLOCK (object);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
 gst_selector_pad_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec)
 {
@@ -244,6 +275,11 @@ gst_selector_pad_get_property (GObject * object, guint prop_id,
       gst_object_unref (sel);
       break;
     }
+    case PROP_PAD_ALWAYS_OK:
+      GST_OBJECT_LOCK (object);
+      g_value_set_boolean (value, spad->always_ok);
+      GST_OBJECT_UNLOCK (object);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -419,43 +455,46 @@ gst_selector_pad_bufferalloc (GstPad * pad, guint64 offset,
   GstInputSelector *sel;
   GstFlowReturn result;
   GstPad *active_sinkpad;
+  GstSelectorPad *selpad;
 
   sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
+  selpad = GST_SELECTOR_PAD_CAST (pad);
 
   GST_DEBUG_OBJECT (pad, "received alloc");
 
   GST_INPUT_SELECTOR_LOCK (sel);
   active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);
+
+  if (pad != active_sinkpad && !sel->select_all)
+    goto not_active;
+
   GST_INPUT_SELECTOR_UNLOCK (sel);
 
-  /* Fallback allocation for buffers from pads except the selected one */
-  if (pad != active_sinkpad && !sel->select_all) {
-    GST_DEBUG_OBJECT (sel,
-        "Pad %s:%s is not selected. Performing fallback allocation",
-        GST_DEBUG_PAD_NAME (pad));
+  result = gst_pad_alloc_buffer (sel->srcpad, offset, size, caps, buf);
 
-    *buf = NULL;
-    result = GST_FLOW_OK;
-  } else {
-    result = gst_pad_alloc_buffer (sel->srcpad, offset, size, caps, buf);
+done:
+  gst_object_unref (sel);
 
-    /* FIXME: HACK. If buffer alloc returns not-linked, perform a fallback
-     * allocation.  This should NOT be necessary, because playbin should
-     * properly block the source pad from running until it's finished hooking 
-     * everything up, but playbin needs refactoring first. */
-    if (result == GST_FLOW_NOT_LINKED) {
-      GST_DEBUG_OBJECT (sel,
-          "No peer pad yet - performing fallback allocation for pad %s:%s",
-          GST_DEBUG_PAD_NAME (pad));
+  return result;
 
+  /* ERRORS */
+not_active:
+  {
+    /* unselected pad, perform fallback alloc or return unlinked when
+     * asked */
+    GST_OBJECT_LOCK (selpad);
+    if (selpad->always_ok) {
+      GST_DEBUG_OBJECT (pad, "Not selected, performing fallback allocation");
       *buf = NULL;
       result = GST_FLOW_OK;
+    } else {
+      GST_DEBUG_OBJECT (pad, "Not selected, return NOT_LINKED");
+      result = GST_FLOW_NOT_LINKED;
     }
-  }
-
-  gst_object_unref (sel);
+    GST_OBJECT_UNLOCK (selpad);
 
-  return result;
+    goto done;
+  }
 }
 
 /* must be called with the SELECTOR_LOCK, will block while the pad is blocked 
@@ -577,7 +616,15 @@ ignore:
     selpad->discont = TRUE;
     GST_INPUT_SELECTOR_UNLOCK (sel);
     gst_buffer_unref (buf);
-    res = GST_FLOW_NOT_LINKED;
+
+    /* figure out what to return upstream */
+    GST_OBJECT_LOCK (selpad);
+    if (selpad->always_ok)
+      res = GST_FLOW_OK;
+    else
+      res = GST_FLOW_NOT_LINKED;
+    GST_OBJECT_UNLOCK (selpad);
+
     goto done;
   }
 flushing: