playbin3: handle GST_PLAY_FLAG_FORCE_SW_DECODERS 26/230426/1
authorVíctor Manuel Jáquez Leal <vjaquez@igalia.com>
Sun, 3 Nov 2019 14:52:28 +0000 (15:52 +0100)
committerEunhye Choi <eunhae1.choi@samsung.com>
Fri, 10 Apr 2020 02:14:19 +0000 (11:14 +0900)
In decodebin3 and uridecodebin3 the `force-sw-decoders` boolean property is
added. In uridecodebin3 it is only a proxy property which will forward
the value to decodebin3.

When decodebin3 has `force-sw-decoders` disabled, it will filter out in its
decoder and decodable factories those elements within the 'Hardware'
class, at reconfiguring output stream.

playbin3 adds by default GST_PLAY_FLAG_FORCE_SW_DECODERS, and sets
`force-sw-decoders` property accordingly to its internal uridecodebin, also
filters out the 'Hardware' class decoder elements when caps
negotiation.

cherry pick from upstream
commit id: f4bcf8290b3568690dacf0dac95af7f7036f7110

Change-Id: I8ccce2c891a58e272452b1af66967f037c57d571

gst/playback/gstdecodebin3.c
gst/playback/gstplaybin3.c
gst/playback/gsturidecodebin3.c

index cfe061ac31a85fa833a017734f621852d389c096..9ab45d065daf95f53a3c5224a2894047eb5ab602 100644 (file)
@@ -265,6 +265,7 @@ struct _GstDecodebin3
 
   /* Properties */
   GstCaps *caps;
+  gboolean force_sw_decoders;
 };
 
 struct _GstDecodebin3Class
@@ -371,7 +372,8 @@ typedef struct _PendingPad
 enum
 {
   PROP_0,
-  PROP_CAPS
+  PROP_CAPS,
+  PROP_FORCE_SW_DECODERS,
 };
 
 /* signals */
@@ -423,6 +425,8 @@ G_DEFINE_TYPE (GstDecodebin3, gst_decodebin3, GST_TYPE_BIN);
 
 static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS);
 
+#define DEFAULT_FORCE_SW_DECODERS FALSE
+
 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
@@ -551,6 +555,20 @@ gst_decodebin3_class_init (GstDecodebin3Class * klass)
           "The caps on which to stop decoding. (NULL = default)",
           GST_TYPE_CAPS, 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 Decoders Only",
+          "Use only sofware decoders to process streams",
+          DEFAULT_FORCE_SW_DECODERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   /* FIXME : ADD SIGNALS ! */
   /**
    * GstDecodebin3::select-stream
@@ -628,6 +646,7 @@ gst_decodebin3_init (GstDecodebin3 * dbin)
   g_mutex_init (&dbin->input_lock);
 
   dbin->caps = gst_static_caps_get (&default_raw_caps);
+  dbin->force_sw_decoders = DEFAULT_FORCE_SW_DECODERS;
 
   GST_OBJECT_FLAG_SET (dbin, GST_BIN_FLAG_STREAMS_AWARE);
 }
@@ -679,6 +698,9 @@ gst_decodebin3_set_property (GObject * object, guint prop_id,
       dbin->caps = g_value_dup_boxed (value);
       GST_OBJECT_UNLOCK (dbin);
       break;
+    case PROP_FORCE_SW_DECODERS:
+      dbin->force_sw_decoders = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -698,6 +720,9 @@ gst_decodebin3_get_property (GObject * object, guint prop_id, GValue * value,
       g_value_set_boxed (value, dbin->caps);
       GST_OBJECT_UNLOCK (dbin);
       break;
+    case PROP_FORCE_SW_DECODERS:
+      g_value_set_boolean (value, dbin->force_sw_decoders);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1038,12 +1063,19 @@ gst_decode_bin_update_factories_list (GstDecodebin3 * dbin)
     dbin->decodable_factories = NULL;
     for (tmp = dbin->factories; tmp; tmp = tmp->next) {
       GstElementFactory *fact = (GstElementFactory *) tmp->data;
+
       if (gst_element_factory_list_is_type (fact,
-              GST_ELEMENT_FACTORY_TYPE_DECODER))
-        dbin->decoder_factories = g_list_append (dbin->decoder_factories, fact);
-      else
+              GST_ELEMENT_FACTORY_TYPE_DECODER)) {
+        if (!(dbin->force_sw_decoders
+                && gst_element_factory_list_is_type (fact,
+                    GST_ELEMENT_FACTORY_TYPE_HARDWARE))) {
+          dbin->decoder_factories =
+              g_list_append (dbin->decoder_factories, fact);
+        }
+      } else {
         dbin->decodable_factories =
             g_list_append (dbin->decodable_factories, fact);
+      }
     }
   }
 }
index d35a806d0394b45269273b4b8886f25445fed0f6..8c23a97e35eaa0e544438501fa514b4f5d093900 100644 (file)
@@ -1765,8 +1765,11 @@ gst_play_bin3_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);
       }
@@ -3462,7 +3465,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;
@@ -3481,7 +3485,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 =
@@ -3603,14 +3609,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);
   }
 
@@ -4505,6 +4515,8 @@ activate_group (GstPlayBin3 * playbin, GstSourceGroup * group)
       "download", ((flags & GST_PLAY_FLAG_DOWNLOAD) != 0),
       /* configure buffering of demuxed/parsed data */
       "use-buffering", ((flags & GST_PLAY_FLAG_BUFFERING) != 0),
+      /* configure usage of hardware 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 8b1840d149221a4b72990fff737b61a44763840c..86659925ca0fbb47b0cd2ebb429ffd16db77eaca 100644 (file)
@@ -196,6 +196,7 @@ struct _GstURIDecodeBin3
   guint buffer_size;            /* When buffering, buffer size (bytes) */
   gboolean download;
   gboolean use_buffering;
+  gboolean force_sw_decoders;
   guint64 ring_buffer_max_size;
 
   GList *play_items;            /* List of GstPlayItem ordered by time of
@@ -271,6 +272,7 @@ static GstStaticCaps raw_video_caps = GST_STATIC_CAPS ("video/x-raw(ANY)");
 #define DEFAULT_BUFFER_SIZE         -1
 #define DEFAULT_DOWNLOAD            FALSE
 #define DEFAULT_USE_BUFFERING       FALSE
+#define DEFAULT_FORCE_SW_DECODERS   FALSE
 #define DEFAULT_RING_BUFFER_MAX_SIZE 0
 
 enum
@@ -286,6 +288,7 @@ enum
   PROP_BUFFER_DURATION,
   PROP_DOWNLOAD,
   PROP_USE_BUFFERING,
+  PROP_FORCE_SW_DECODERS,
   PROP_RING_BUFFER_MAX_SIZE,
   PROP_CAPS
 };
@@ -428,6 +431,21 @@ gst_uri_decode_bin3_class_init (GstURIDecodeBin3Class * klass)
           "Perform buffering on demuxed/parsed media",
           DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  /**
+   * GstURIDecodeBin3::force-sw-decoders:
+   *
+   * While auto-plugging, if set to %TRUE, those decoders within
+   * "Hardware" klass will by tried. Otherwise they will be ignored.
+   *
+   * Since: 1.18
+   */
+  g_object_class_install_property (gobject_class, PROP_FORCE_SW_DECODERS,
+      g_param_spec_boolean ("force-sw-decoders", "Software Decoders Only",
+          "Use only sofware decoders to process streams",
+          DEFAULT_FORCE_SW_DECODERS,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+
   /**
    * GstURIDecodeBin3::ring-buffer-max-size
    *
@@ -823,6 +841,12 @@ gst_uri_decode_bin3_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:
+      if (dec->decodebin) {
+        g_object_set_property (G_OBJECT (dec->decodebin), "force-sw-decoders",
+            value);
+      }
+      break;
     case PROP_RING_BUFFER_MAX_SIZE:
       dec->ring_buffer_max_size = g_value_get_uint64 (value);
       break;
@@ -896,6 +920,12 @@ gst_uri_decode_bin3_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:
+      if (dec->decodebin) {
+        g_object_get_property (G_OBJECT (dec->decodebin), "force-sw-decoders",
+            value);
+      }
+      break;
     case PROP_RING_BUFFER_MAX_SIZE:
       g_value_set_uint64 (value, dec->ring_buffer_max_size);
       break;