decodebin2: Add a property to not expose/decode all streams
authorEdward Hervey <bilboed@bilboed.com>
Thu, 6 May 2010 16:50:51 +0000 (18:50 +0200)
committerEdward Hervey <bilboed@bilboed.com>
Fri, 7 May 2010 15:38:38 +0000 (17:38 +0200)
API : expose-all-streams

If disabled:
* only the streams that CAN be decoded and match the final caps will have a
  decoder plugged in and be exposed.
* the streams that COULD HAVE BEEN decoded but do not match the finals caps
  will not have a decoder plugged in and will not be exposed.

If no decoder is available to decode a certain stream, then the missing element
message will still be emitted regardless of the value of the property.

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

gst/playback/gstdecodebin2.c

index 4b6ea63..67d8523 100644 (file)
@@ -167,6 +167,8 @@ struct _GstDecodeBin
   GMutex *dyn_lock;             /* lock protecting pad blocking */
   gboolean shutdown;            /* if we are shutting down */
   GList *blocked_pads;          /* pads that have set to block */
+
+  gboolean expose_allstreams;   /* Whether to expose unknow type streams or not */
 };
 
 struct _GstDecodeBinClass
@@ -232,6 +234,7 @@ enum
 #define DEFAULT_MAX_SIZE_BUFFERS  0
 #define DEFAULT_MAX_SIZE_TIME     0
 #define DEFAULT_POST_STREAM_TOPOLOGY FALSE
+#define DEFAULT_EXPOSE_ALL_STREAMS  TRUE
 
 /* Properties */
 enum
@@ -247,6 +250,7 @@ enum
   PROP_MAX_SIZE_BUFFERS,
   PROP_MAX_SIZE_TIME,
   PROP_POST_STREAM_TOPOLOGY,
+  PROP_EXPOSE_ALL_STREAMS,
   PROP_LAST
 };
 
@@ -831,6 +835,24 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
           DEFAULT_POST_STREAM_TOPOLOGY,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstDecodeBin2::expose-all-streams
+   *
+   * Expose streams of unknown type.
+   *
+   * If set to %FALSE, then only the streams that can be decoded to the final
+   * caps (see 'caps' property) will have a pad exposed. Streams that do not
+   * match those caps but could have been decoded will not have decoder plugged
+   * in internally and will not have a pad exposed. 
+   *
+   * Since: 0.10.30
+   */
+  g_object_class_install_property (gobject_klass, PROP_EXPOSE_ALL_STREAMS,
+      g_param_spec_boolean ("expose-all-streams", "Expose All Streams",
+          "Expose all streams, including those of unknown type or that don't match the 'caps' property",
+          DEFAULT_EXPOSE_ALL_STREAMS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
 
 
   klass->autoplug_continue =
@@ -926,6 +948,8 @@ gst_decode_bin_init (GstDecodeBin * decode_bin)
   decode_bin->max_size_bytes = DEFAULT_MAX_SIZE_BYTES;
   decode_bin->max_size_buffers = DEFAULT_MAX_SIZE_BUFFERS;
   decode_bin->max_size_time = DEFAULT_MAX_SIZE_TIME;
+
+  decode_bin->expose_allstreams = DEFAULT_EXPOSE_ALL_STREAMS;
 }
 
 static void
@@ -1118,6 +1142,9 @@ gst_decode_bin_set_property (GObject * object, guint prop_id,
     case PROP_POST_STREAM_TOPOLOGY:
       dbin->post_stream_topology = g_value_get_boolean (value);
       break;
+    case PROP_EXPOSE_ALL_STREAMS:
+      dbin->expose_allstreams = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1162,6 +1189,9 @@ gst_decode_bin_get_property (GObject * object, guint prop_id,
     case PROP_POST_STREAM_TOPOLOGY:
       g_value_set_boolean (value, dbin->post_stream_topology);
       break;
+    case PROP_EXPOSE_ALL_STREAMS:
+      g_value_set_boolean (value, dbin->expose_allstreams);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1348,7 +1378,52 @@ analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
   g_value_array_free (factories);
   factories = result;
 
-  /* 1.e else continue autoplugging something from the list. */
+  /* At this point we have a potential decoder, but we might not need it
+   * if it doesn't match the output caps  */
+  if (!dbin->expose_allstreams) {
+    guint i;
+    GstCaps *rawcaps = gst_static_caps_get (&default_raw_caps);
+    const GList *tmps;
+    gboolean dontuse = FALSE;
+
+    GST_DEBUG ("Checking if we can abort early");
+
+    /* 1.e Do an early check to see if the candidates are potential decoders, but
+     * due to the fact that they decode to a mediatype that is not final we don't 
+     * need them */
+
+    for (i = 0; i < factories->n_values && !dontuse; i++) {
+      GstElementFactory *factory =
+          g_value_get_object (g_value_array_get_nth (factories, 0));
+      GstCaps *tcaps;
+
+      /* We are only interested in skipping decoders */
+      if (strstr (gst_element_factory_get_klass (factory), "Decoder")) {
+
+        GST_DEBUG ("Trying factory %s",
+            gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
+
+        /* Check the source pad template caps to see if they match raw caps but don't match
+         * our final caps*/
+        for (tmps = gst_element_factory_get_static_pad_templates (factory);
+            tmps && !dontuse; tmps = tmps->next) {
+          GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data;
+          if (st->direction != GST_PAD_SRC)
+            continue;
+          tcaps = gst_static_pad_template_get_caps (st);
+          if (!gst_caps_can_intersect (tcaps, dbin->caps))
+            dontuse = TRUE;
+          gst_caps_unref (tcaps);
+        }
+      }
+    }
+    gst_caps_unref (rawcaps);
+
+    if (dontuse)
+      goto discarded_type;
+  }
+
+  /* 1.f else continue autoplugging something from the list. */
   GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
   connect_pad (dbin, src, dpad, pad, caps, factories, chain);
 
@@ -1364,6 +1439,24 @@ expose_pad:
     gst_object_unref (dpad);
     return;
   }
+
+discarded_type:
+  {
+    GST_LOG_OBJECT (pad, "Known type, but discarded because not final caps");
+    chain->deadend = TRUE;
+    chain->endcaps = gst_caps_ref (caps);
+
+    /* Try to expose anything */
+    EXPOSE_LOCK (dbin);
+    if (gst_decode_chain_is_complete (dbin->decode_chain)) {
+      gst_decode_bin_expose (dbin);
+    }
+    EXPOSE_UNLOCK (dbin);
+    do_async_done (dbin);
+
+    return;
+  }
+
 unknown_type:
   {
     GST_LOG_OBJECT (pad, "Unknown type, posting message and firing signal");