From f4bcf8290b3568690dacf0dac95af7f7036f7110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Sun, 3 Nov 2019 15:52:28 +0100 Subject: [PATCH] playbin3: handle GST_PLAY_FLAG_FORCE_SW_DECODERS 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. --- gst/playback/gstdecodebin3.c | 40 +++++++++++++++++++++++++++++---- gst/playback/gstplaybin3.c | 22 +++++++++++++----- gst/playback/gsturidecodebin3.c | 30 +++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/gst/playback/gstdecodebin3.c b/gst/playback/gstdecodebin3.c index 1f18f4e12d..3fdd9d12ec 100644 --- a/gst/playback/gstdecodebin3.c +++ b/gst/playback/gstdecodebin3.c @@ -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 @@ -627,6 +645,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); } @@ -678,6 +697,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; @@ -697,6 +719,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; @@ -1037,12 +1062,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); + } } } } diff --git a/gst/playback/gstplaybin3.c b/gst/playback/gstplaybin3.c index f269fb5c5b..3c8e2d5ec9 100644 --- a/gst/playback/gstplaybin3.c +++ b/gst/playback/gstplaybin3.c @@ -1763,8 +1763,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); } @@ -3458,7 +3461,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; @@ -3477,7 +3481,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 = @@ -3599,14 +3605,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); } @@ -4508,6 +4518,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, diff --git a/gst/playback/gsturidecodebin3.c b/gst/playback/gsturidecodebin3.c index a0cd1966a3..1b3ede2d79 100644 --- a/gst/playback/gsturidecodebin3.c +++ b/gst/playback/gsturidecodebin3.c @@ -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 * @@ -821,6 +839,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; @@ -894,6 +918,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;