From 4e381b8901e0c9d3957de974171fd06fef7d0297 Mon Sep 17 00:00:00 2001 From: Haihua Hu Date: Thu, 17 Dec 2020 12:11:45 +0800 Subject: [PATCH] playback: Support runtime change connection-speed of adaptivedemux(2) Update connection-speed at runtime in playbin, uridecodebin and decodebin also do the same thing in urisourcebin. With contributions from Philippe Normand (build fixes and rebase on mono-repo). Part-of: --- .../gst/playback/gstdecodebin2.c | 107 +++++++++++------- .../gst/playback/gstplaybin2.c | 20 ++++ .../gst/playback/gsturidecodebin.c | 21 ++++ .../gst/playback/gsturisourcebin.c | 30 +++++ 4 files changed, 140 insertions(+), 38 deletions(-) diff --git a/subprojects/gst-plugins-base/gst/playback/gstdecodebin2.c b/subprojects/gst-plugins-base/gst/playback/gstdecodebin2.c index 2e8c943118..9610f8b7eb 100644 --- a/subprojects/gst-plugins-base/gst/playback/gstdecodebin2.c +++ b/subprojects/gst-plugins-base/gst/playback/gstdecodebin2.c @@ -1281,6 +1281,73 @@ gst_decode_bin_get_subs_encoding (GstDecodeBin * dbin) return encoding; } +static void +gst_decode_bin_set_demux_connection_speed (GstDecodeBin * dbin, + GstElement * element) +{ + guint64 speed = 0; + gboolean wrong_type = FALSE; + GParamSpec *pspec; + + GST_OBJECT_LOCK (dbin); + speed = dbin->connection_speed / 1000; + GST_OBJECT_UNLOCK (dbin); + + if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), + "connection-speed"))) { + if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT) { + GParamSpecUInt *pspecuint = G_PARAM_SPEC_UINT (pspec); + + speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum); + } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT) { + GParamSpecInt *pspecint = G_PARAM_SPEC_INT (pspec); + + speed = CLAMP (speed, pspecint->minimum, pspecint->maximum); + } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT64) { + GParamSpecUInt64 *pspecuint = G_PARAM_SPEC_UINT64 (pspec); + + speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum); + } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT64) { + GParamSpecInt64 *pspecint = G_PARAM_SPEC_INT64 (pspec); + + speed = CLAMP (speed, pspecint->minimum, pspecint->maximum); + } else { + GST_WARNING_OBJECT (dbin, + "The connection speed property %" G_GUINT64_FORMAT " of type %s" + " is not useful not setting it", speed, + g_type_name (G_PARAM_SPEC_TYPE (pspec))); + wrong_type = TRUE; + } + + if (!wrong_type) { + GST_DEBUG_OBJECT (dbin, "setting connection-speed=%" G_GUINT64_FORMAT + " to demuxer element", speed); + + g_object_set (element, "connection-speed", speed, NULL); + } + } +} + +static void +gst_decode_bin_update_connection_speed (GstDecodeBin * dbin) +{ + GstElement *demuxer = NULL; + + if (!dbin->decode_chain) + return; + + CHAIN_MUTEX_LOCK (dbin->decode_chain); + if (dbin->decode_chain->adaptive_demuxer) { + GstDecodeElement *delem = dbin->decode_chain->elements->data; + demuxer = gst_object_ref (delem->element); + } + CHAIN_MUTEX_UNLOCK (dbin->decode_chain); + if (demuxer) { + gst_decode_bin_set_demux_connection_speed (dbin, demuxer); + gst_object_unref (demuxer); + } +} + static void gst_decode_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -1330,6 +1397,7 @@ gst_decode_bin_set_property (GObject * object, guint prop_id, GST_OBJECT_LOCK (dbin); dbin->connection_speed = g_value_get_uint64 (value) * 1000; GST_OBJECT_UNLOCK (dbin); + gst_decode_bin_update_connection_speed (dbin); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -2451,44 +2519,7 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, /* Set connection-speed property if needed */ if (chain->demuxer) { - GParamSpec *pspec; - - if ((pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), - "connection-speed"))) { - guint64 speed = dbin->connection_speed / 1000; - gboolean wrong_type = FALSE; - - if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT) { - GParamSpecUInt *pspecuint = G_PARAM_SPEC_UINT (pspec); - - speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum); - } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT) { - GParamSpecInt *pspecint = G_PARAM_SPEC_INT (pspec); - - speed = CLAMP (speed, pspecint->minimum, pspecint->maximum); - } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_UINT64) { - GParamSpecUInt64 *pspecuint = G_PARAM_SPEC_UINT64 (pspec); - - speed = CLAMP (speed, pspecuint->minimum, pspecuint->maximum); - } else if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT64) { - GParamSpecInt64 *pspecint = G_PARAM_SPEC_INT64 (pspec); - - speed = CLAMP (speed, pspecint->minimum, pspecint->maximum); - } else { - GST_WARNING_OBJECT (dbin, - "The connection speed property %" G_GUINT64_FORMAT " of type %s" - " is not useful not setting it", speed, - g_type_name (G_PARAM_SPEC_TYPE (pspec))); - wrong_type = TRUE; - } - - if (!wrong_type) { - GST_DEBUG_OBJECT (dbin, "setting connection-speed=%" G_GUINT64_FORMAT - " to demuxer element", speed); - - g_object_set (element, "connection-speed", speed, NULL); - } - } + gst_decode_bin_set_demux_connection_speed (dbin, element); } /* try to configure the subtitle encoding property when we can */ diff --git a/subprojects/gst-plugins-base/gst/playback/gstplaybin2.c b/subprojects/gst-plugins-base/gst/playback/gstplaybin2.c index 5a4ca4404c..7f843bd446 100644 --- a/subprojects/gst-plugins-base/gst/playback/gstplaybin2.c +++ b/subprojects/gst-plugins-base/gst/playback/gstplaybin2.c @@ -2469,10 +2469,30 @@ gst_play_bin_set_property (GObject * object, guint prop_id, g_value_get_string (value)); break; case PROP_CONNECTION_SPEED: + { + guint64 connection_speed = 0; GST_PLAY_BIN_LOCK (playbin); playbin->connection_speed = g_value_get_uint64 (value) * 1000; + connection_speed = playbin->connection_speed; + if (playbin->curr_group) { + GST_SOURCE_GROUP_LOCK (playbin->curr_group); + if (playbin->curr_group->uridecodebin) { + g_object_set (playbin->curr_group->uridecodebin, + "connection-speed", connection_speed / 1000, NULL); + } + GST_SOURCE_GROUP_UNLOCK (playbin->curr_group); + } + if (playbin->next_group) { + GST_SOURCE_GROUP_LOCK (playbin->next_group); + if (playbin->next_group->uridecodebin) { + g_object_set (playbin->next_group->uridecodebin, + "connection-speed", connection_speed / 1000, NULL); + } + GST_SOURCE_GROUP_UNLOCK (playbin->next_group); + } GST_PLAY_BIN_UNLOCK (playbin); break; + } case PROP_BUFFER_SIZE: playbin->buffer_size = g_value_get_int (value); break; diff --git a/subprojects/gst-plugins-base/gst/playback/gsturidecodebin.c b/subprojects/gst-plugins-base/gst/playback/gsturidecodebin.c index 27ec4f3c40..86e20a9be4 100644 --- a/subprojects/gst-plugins-base/gst/playback/gsturidecodebin.c +++ b/subprojects/gst-plugins-base/gst/playback/gsturidecodebin.c @@ -817,6 +817,26 @@ gst_uri_decode_bin_set_encoding (GstURIDecodeBin * dec, const gchar * encoding) GST_URI_DECODE_BIN_UNLOCK (dec); } +static void +gst_uri_decode_bin_set_connection_speed (GstURIDecodeBin * dec) +{ + GSList *walk; + guint64 connection_speed; + + GST_OBJECT_LOCK (dec); + connection_speed = dec->connection_speed; + GST_OBJECT_UNLOCK (dec); + + /* set the property on all decodebins now */ + GST_URI_DECODE_BIN_LOCK (dec); + for (walk = dec->decodebins; walk; walk = g_slist_next (walk)) { + GObject *decodebin = G_OBJECT (walk->data); + + g_object_set (decodebin, "connection-speed", connection_speed / 1000, NULL); + } + GST_URI_DECODE_BIN_UNLOCK (dec); +} + static void gst_uri_decode_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -834,6 +854,7 @@ gst_uri_decode_bin_set_property (GObject * object, guint prop_id, GST_OBJECT_LOCK (dec); dec->connection_speed = g_value_get_uint64 (value) * 1000; GST_OBJECT_UNLOCK (dec); + gst_uri_decode_bin_set_connection_speed (dec); break; case PROP_CAPS: GST_OBJECT_LOCK (dec); diff --git a/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c b/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c index 8dcf371bdf..c54a2891f4 100644 --- a/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c +++ b/subprojects/gst-plugins-base/gst/playback/gsturisourcebin.c @@ -564,6 +564,35 @@ gst_uri_source_bin_finalize (GObject * obj) G_OBJECT_CLASS (parent_class)->finalize (obj); } +static void +gst_uri_source_bin_update_connection_speed (GstURISourceBin * urisrc) +{ + guint64 speed = 0; + GList *iter; + + if (!urisrc->is_adaptive) { + return; + } + + GST_OBJECT_LOCK (urisrc); + speed = urisrc->connection_speed / 1000; + GST_OBJECT_UNLOCK (urisrc); + + GST_URI_SOURCE_BIN_LOCK (urisrc); + for (iter = urisrc->src_infos; iter; iter = iter->next) { + ChildSrcPadInfo *info = iter->data; + GParamSpec *pspec = NULL; + if (!info->demuxer) + continue; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (info->demuxer), + "connection-speed"); + if (pspec != NULL) + g_object_set (info->demuxer, "connection-speed", speed, NULL); + } + GST_URI_SOURCE_BIN_UNLOCK (urisrc); +} + static void gst_uri_source_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -581,6 +610,7 @@ gst_uri_source_bin_set_property (GObject * object, guint prop_id, GST_OBJECT_LOCK (urisrc); urisrc->connection_speed = g_value_get_uint64 (value) * 1000; GST_OBJECT_UNLOCK (urisrc); + gst_uri_source_bin_update_connection_speed (urisrc); break; case PROP_BUFFER_SIZE: urisrc->buffer_size = g_value_get_int (value);