playbin2: handle GST_PLAY_FLAG_FORCE_SW_DECODERS
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Sun, 3 Nov 2019 14:37:44 +0000 (15:37 +0100)
committerVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Thu, 9 Jan 2020 12:28:32 +0000 (12:28 +0000)
Added `force-sw-decoders` boolean property in decodebin2 and
uridecodebin. By default the property is %FALSE and it bypass the new
code. Otherwise the factory list is filtered removing decoders
within 'Hardware' class.

uridecodebin sets the `force-sw-decoders` property in its internal
decodebin, and also filters out Hardware class in the
autoplug-factories default signal handler.

playbin2 adds by default GST_PLAY_FLAG_FORCE_SW_DECODERS it its flags
property, and depending on it playbin2 sets the `force-sw-decoders`
property on its internal uridecodebin, also filters out the Hardware
class decoding decoders at the autoplug-factories signal handler.

gst/playback/gstdecodebin2.c
gst/playback/gstplaybin2.c
gst/playback/gsturidecodebin.c

index 7c78465..46f9a7f 100644 (file)
@@ -149,6 +149,7 @@ struct _GstDecodeBin
   GstCaps *caps;                /* caps on which to stop decoding */
   gchar *encoding;              /* encoding of subtitles */
   gboolean use_buffering;       /* configure buffering on multiqueues */
+  gboolean force_sw_decoders;
   gint low_percent;
   gint high_percent;
   guint max_size_bytes;
@@ -253,6 +254,7 @@ enum
 
 #define DEFAULT_SUBTITLE_ENCODING NULL
 #define DEFAULT_USE_BUFFERING     FALSE
+#define DEFAULT_FORCE_SW_DECODERS FALSE
 #define DEFAULT_LOW_PERCENT       10
 #define DEFAULT_HIGH_PERCENT      99
 /* by default we use the automatic values above */
@@ -271,6 +273,7 @@ enum
   PROP_SUBTITLE_ENCODING,
   PROP_SINK_CAPS,
   PROP_USE_BUFFERING,
+  PROP_FORCE_SW_DECODERS,
   PROP_LOW_PERCENT,
   PROP_HIGH_PERCENT,
   PROP_MAX_SIZE_BYTES,
@@ -909,6 +912,20 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
           DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
+   * GstDecodeBin::force-sw-decoders:
+   *
+   * While auto-plugging, if set to %TRUE, those decoders within
+   * "Hardware" klass will be ignored. Otherwise they will be tried.
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_klass, PROP_FORCE_SW_DECODERS,
+      g_param_spec_boolean ("force-sw-decoders", "Software Docoders Only",
+          "Use only sofware decoders to process streams",
+          DEFAULT_FORCE_SW_DECODERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
    * GstDecodeBin:low-percent
    *
    * Low threshold percent for buffering to start.
@@ -1034,14 +1051,33 @@ static void
 gst_decode_bin_update_factories_list (GstDecodeBin * dbin)
 {
   guint cookie;
+  GList *factories, *tmp;
 
   cookie = gst_registry_get_feature_list_cookie (gst_registry_get ());
   if (!dbin->factories || dbin->factories_cookie != cookie) {
     if (dbin->factories)
       gst_plugin_feature_list_free (dbin->factories);
-    dbin->factories =
+    factories =
         gst_element_factory_list_get_elements
         (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL);
+
+    if (dbin->force_sw_decoders) {
+      /* filter out Hardware class elements */
+      dbin->factories = NULL;
+      for (tmp = factories; tmp; tmp = g_list_next (tmp)) {
+        GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
+        if (!gst_element_factory_list_is_type (factory,
+                GST_ELEMENT_FACTORY_TYPE_HARDWARE)) {
+          dbin->factories = g_list_prepend (dbin->factories, factory);
+        } else {
+          gst_object_unref (factory);
+        }
+      }
+      g_list_free (factories);
+    } else {
+      dbin->factories = factories;
+    }
+
     dbin->factories =
         g_list_sort (dbin->factories,
         gst_playback_utils_compare_factories_func);
@@ -1103,6 +1139,7 @@ gst_decode_bin_init (GstDecodeBin * decode_bin)
   decode_bin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
   decode_bin->caps = gst_static_caps_get (&default_raw_caps);
   decode_bin->use_buffering = DEFAULT_USE_BUFFERING;
+  decode_bin->force_sw_decoders = DEFAULT_FORCE_SW_DECODERS;
   decode_bin->low_percent = DEFAULT_LOW_PERCENT;
   decode_bin->high_percent = DEFAULT_HIGH_PERCENT;
 
@@ -1276,6 +1313,9 @@ gst_decode_bin_set_property (GObject * object, guint prop_id,
     case PROP_USE_BUFFERING:
       dbin->use_buffering = g_value_get_boolean (value);
       break;
+    case PROP_FORCE_SW_DECODERS:
+      dbin->force_sw_decoders = g_value_get_boolean (value);
+      break;
     case PROP_LOW_PERCENT:
       dbin->low_percent = g_value_get_int (value);
       break;
@@ -1328,6 +1368,9 @@ gst_decode_bin_get_property (GObject * object, guint prop_id,
     case PROP_USE_BUFFERING:
       g_value_set_boolean (value, dbin->use_buffering);
       break;
+    case PROP_FORCE_SW_DECODERS:
+      g_value_set_boolean (value, dbin->force_sw_decoders);
+      break;
     case PROP_LOW_PERCENT:
       g_value_set_int (value, dbin->low_percent);
       break;
index d28461b..abdacb6 100644 (file)
@@ -2404,8 +2404,11 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
       if (playbin->curr_group) {
         GST_SOURCE_GROUP_LOCK (playbin->curr_group);
         if (playbin->curr_group->uridecodebin) {
-          g_object_set (playbin->curr_group->uridecodebin, "download",
-              (g_value_get_flags (value) & GST_PLAY_FLAG_DOWNLOAD) != 0, NULL);
+          guint flags = g_value_get_flags (value);
+          g_object_set (playbin->curr_group->uridecodebin,
+              "download", (flags & GST_PLAY_FLAG_DOWNLOAD) != 0,
+              "force-sw-decoders",
+              (flags & GST_PLAY_FLAG_FORCE_SW_DECODERS) != 0, NULL);
         }
         GST_SOURCE_GROUP_UNLOCK (playbin->curr_group);
       }
@@ -4131,7 +4134,8 @@ avelement_iter_is_equal (GSequenceIter * iter, GstElementFactory * factory)
 }
 
 static GList *
-create_decoders_list (GList * factory_list, GSequence * avelements)
+create_decoders_list (GList * factory_list, GSequence * avelements,
+    GstPlayFlags flags)
 {
   GList *dec_list = NULL, *tmp;
   GList *ave_list = NULL;
@@ -4150,7 +4154,9 @@ create_decoders_list (GList * factory_list, GSequence * avelements)
         gst_element_factory_list_is_type (factory,
             GST_ELEMENT_FACTORY_TYPE_SINK)) {
       dec_list = g_list_prepend (dec_list, gst_object_ref (factory));
-    } else {
+    } else if (!(((flags & GST_PLAY_FLAG_FORCE_SW_DECODERS) != 0)
+            && gst_element_factory_list_is_type (factory,
+                GST_ELEMENT_FACTORY_TYPE_HARDWARE))) {
       GSequenceIter *seq_iter;
 
       seq_iter =
@@ -4272,14 +4278,18 @@ autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
 
   if (isaudiodeclist || isvideodeclist) {
     GSequence **ave_list;
+    GstPlayFlags flags;
+
     if (isaudiodeclist)
       ave_list = &playbin->aelements;
     else
       ave_list = &playbin->velements;
 
+    flags = gst_play_bin_get_flags (playbin);
+
     g_mutex_lock (&playbin->elements_lock);
     /* sort factory_list based on the GstAVElement list priority */
-    factory_list = create_decoders_list (factory_list, *ave_list);
+    factory_list = create_decoders_list (factory_list, *ave_list, flags);
     g_mutex_unlock (&playbin->elements_lock);
   }
 
@@ -5366,6 +5376,8 @@ activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target)
       "download", ((flags & GST_PLAY_FLAG_DOWNLOAD) != 0),
       /* configure buffering of demuxed/parsed data */
       "use-buffering", ((flags & GST_PLAY_FLAG_BUFFERING) != 0),
+      /* enable hardware-based elements */
+      "force-sw-decoders", ((flags & GST_PLAY_FLAG_FORCE_SW_DECODERS) != 0),
       /* configure buffering parameters */
       "buffer-duration", playbin->buffer_duration,
       "buffer-size", playbin->buffer_size,
index d5a6db6..6a85f71 100644 (file)
@@ -95,6 +95,7 @@ struct _GstURIDecodeBin
   guint buffer_size;            /* When buffering, buffer size (bytes) */
   gboolean download;
   gboolean use_buffering;
+  gboolean force_sw_decoders;
 
   GstElement *source;
   GstElement *queue;
@@ -180,6 +181,7 @@ enum
 #define DEFAULT_BUFFER_SIZE         -1
 #define DEFAULT_DOWNLOAD            FALSE
 #define DEFAULT_USE_BUFFERING       FALSE
+#define DEFAULT_FORCE_SW_DECODERS   FALSE
 #define DEFAULT_EXPOSE_ALL_STREAMS  TRUE
 #define DEFAULT_RING_BUFFER_MAX_SIZE 0
 
@@ -195,6 +197,7 @@ enum
   PROP_BUFFER_DURATION,
   PROP_DOWNLOAD,
   PROP_USE_BUFFERING,
+  PROP_FORCE_SW_DECODERS,
   PROP_EXPOSE_ALL_STREAMS,
   PROP_RING_BUFFER_MAX_SIZE
 };
@@ -311,14 +314,33 @@ static void
 gst_uri_decode_bin_update_factories_list (GstURIDecodeBin * dec)
 {
   guint32 cookie;
+  GList *factories, *tmp;
 
   cookie = gst_registry_get_feature_list_cookie (gst_registry_get ());
   if (!dec->factories || dec->factories_cookie != cookie) {
     if (dec->factories)
       gst_plugin_feature_list_free (dec->factories);
-    dec->factories =
+    factories =
         gst_element_factory_list_get_elements
         (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL);
+
+    if (dec->force_sw_decoders) {
+      /* filter out Hardware class elements */
+      dec->factories = NULL;
+      for (tmp = factories; tmp; tmp = g_list_next (tmp)) {
+        GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data);
+        if (!gst_element_factory_list_is_type (factory,
+                GST_ELEMENT_FACTORY_TYPE_HARDWARE)) {
+          dec->factories = g_list_prepend (dec->factories, factory);
+        } else {
+          gst_object_unref (factory);
+        }
+      }
+      g_list_free (factories);
+    } else {
+      dec->factories = factories;
+    }
+
     dec->factories =
         g_list_sort (dec->factories, gst_playback_utils_compare_factories_func);
     dec->factories_cookie = cookie;
@@ -462,6 +484,20 @@ gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
           DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   /**
+   * GstURIDecodeBin::force-sw-decoders:
+   *
+   * While auto-plugging, if set to %TRUE, those decoders within
+   * "Hardware" klass will be ignored. Otherwise they will be tried.
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_FORCE_SW_DECODERS,
+      g_param_spec_boolean ("force-sw-decoders", "Software Docoders Only",
+          "Use only sofware decoders to process streams",
+          DEFAULT_FORCE_SW_DECODERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
    * GstURIDecodeBin::expose-all-streams:
    *
    * Expose streams of unknown type.
@@ -713,6 +749,7 @@ gst_uri_decode_bin_init (GstURIDecodeBin * dec)
   dec->buffer_size = DEFAULT_BUFFER_SIZE;
   dec->download = DEFAULT_DOWNLOAD;
   dec->use_buffering = DEFAULT_USE_BUFFERING;
+  dec->force_sw_decoders = DEFAULT_FORCE_SW_DECODERS;
   dec->expose_allstreams = DEFAULT_EXPOSE_ALL_STREAMS;
   dec->ring_buffer_max_size = DEFAULT_RING_BUFFER_MAX_SIZE;
 
@@ -801,6 +838,9 @@ gst_uri_decode_bin_set_property (GObject * object, guint prop_id,
     case PROP_USE_BUFFERING:
       dec->use_buffering = g_value_get_boolean (value);
       break;
+    case PROP_FORCE_SW_DECODERS:
+      dec->force_sw_decoders = g_value_get_boolean (value);
+      break;
     case PROP_EXPOSE_ALL_STREAMS:
       dec->expose_allstreams = g_value_get_boolean (value);
       break;
@@ -861,6 +901,9 @@ gst_uri_decode_bin_get_property (GObject * object, guint prop_id,
     case PROP_USE_BUFFERING:
       g_value_set_boolean (value, dec->use_buffering);
       break;
+    case PROP_FORCE_SW_DECODERS:
+      g_value_set_boolean (value, dec->force_sw_decoders);
+      break;
     case PROP_EXPOSE_ALL_STREAMS:
       g_value_set_boolean (value, dec->expose_allstreams);
       break;
@@ -1815,6 +1858,9 @@ make_decoder (GstURIDecodeBin * decoder)
         "unknown-type", G_CALLBACK (unknown_type_cb), decoder);
   }
 
+  g_object_set (decodebin, "force-sw-decoders", decoder->force_sw_decoders,
+      NULL);
+
   /* configure caps if we have any */
   if (decoder->caps)
     g_object_set (decodebin, "caps", decoder->caps, NULL);