diff --git a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json index 2ce84963c1..5f2e75963e 100644 --- a/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-base/docs/plugins/gst_plugins_cache.json @@ -1875,6 +1875,18 @@ "type": "GstCompositorBackground", "writable": true }, + "ignore-inactive-pads": { + "blurb": "Avoid timing out waiting for inactive pads", + "conditionally-available": false, + "construct": false, + "construct-only": false, + "controllable": false, + "default": "false", + "mutable": "null", + "readable": true, + "type": "gboolean", + "writable": true + }, "max-threads": { "blurb": "Maximum number of blending/rendering worker threads to spawn (0 = auto)", "conditionally-available": false, diff --git a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c index f40975b067..4eb91db927 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/audio/gstaudioaggregator.c @@ -537,6 +537,7 @@ enum PROP_ALIGNMENT_THRESHOLD, PROP_DISCONT_WAIT, PROP_OUTPUT_BUFFER_DURATION_FRACTION, + PROP_IGNORE_INACTIVE_PADS, }; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstAudioAggregator, gst_audio_aggregator, @@ -697,6 +698,27 @@ gst_audio_aggregator_class_init (GstAudioAggregatorClass * klass) "Window of time in nanoseconds to wait before " "creating a discontinuity", 0, G_MAXUINT64 - 1, DEFAULT_DISCONT_WAIT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_PLAYING)); + + /** + * GstAudioAggregator:ignore-inactive-pads: + * + * Don't wait for inactive pads when live. An inactive pad + * is a pad that hasn't yet received a buffer, but that has + * been waited on at least once. + * + * The purpose of this property is to avoid aggregating on + * timeout when new pads are requested in advance of receiving + * data flow, for example the user may decide to connect it later, + * but wants to configure it already. + * + * Since: 1.20 + */ + g_object_class_install_property (gobject_class, + PROP_IGNORE_INACTIVE_PADS, g_param_spec_boolean ("ignore-inactive-pads", + "Ignore inactive pads", + "Avoid timing out waiting for inactive pads", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } @@ -763,6 +785,10 @@ gst_audio_aggregator_set_property (GObject * object, guint prop_id, g_object_notify (object, "output-buffer-duration"); gst_audio_aggregator_recalculate_latency (aagg); break; + case PROP_IGNORE_INACTIVE_PADS: + gst_aggregator_set_ignore_inactive_pads (GST_AGGREGATOR (object), + g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -791,6 +817,10 @@ gst_audio_aggregator_get_property (GObject * object, guint prop_id, gst_value_set_fraction (value, aagg->priv->output_buffer_duration_n, aagg->priv->output_buffer_duration_d); break; + case PROP_IGNORE_INACTIVE_PADS: + g_value_set_boolean (value, + gst_aggregator_get_ignore_inactive_pads (GST_AGGREGATOR (object))); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -2271,6 +2301,9 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout) gboolean pad_eos = gst_aggregator_pad_is_eos (aggpad); GstBuffer *input_buffer; + if (gst_aggregator_pad_is_inactive (aggpad)) + continue; + if (!pad_eos) is_eos = FALSE; @@ -2381,6 +2414,9 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout) GstAudioAggregatorPad *pad = (GstAudioAggregatorPad *) iter->data; GstAggregatorPad *aggpad = (GstAggregatorPad *) iter->data; + if (gst_aggregator_pad_is_inactive (aggpad)) + continue; + GST_OBJECT_LOCK (pad); if (pad->priv->buffer && pad->priv->output_offset >= aagg->priv->offset @@ -2432,6 +2468,9 @@ gst_audio_aggregator_aggregate (GstAggregator * agg, gboolean timeout) for (iter = GST_ELEMENT (agg)->sinkpads; iter; iter = iter->next) { GstAudioAggregatorPad *pad = GST_AUDIO_AGGREGATOR_PAD (iter->data); + if (gst_aggregator_pad_is_inactive (GST_AGGREGATOR_PAD (pad))) + continue; + max_offset = MAX ((gint64) max_offset, (gint64) pad->priv->output_offset); } GST_OBJECT_UNLOCK (agg); diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c index 6d8b1a9a96..cbad92dace 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/gstvideoaggregator.c @@ -1745,6 +1745,10 @@ gst_video_aggregator_fill_queues (GstVideoAggregator * vagg, gboolean is_eos; bpad = GST_AGGREGATOR_PAD (pad); + + if (gst_aggregator_pad_is_inactive (bpad)) + continue; + GST_OBJECT_LOCK (bpad); segment = bpad->segment; GST_OBJECT_UNLOCK (bpad); diff --git a/subprojects/gst-plugins-base/gst/compositor/compositor.c b/subprojects/gst-plugins-base/gst/compositor/compositor.c index ca4df68364..9938154176 100644 --- a/subprojects/gst-plugins-base/gst/compositor/compositor.c +++ b/subprojects/gst-plugins-base/gst/compositor/compositor.c @@ -544,6 +544,9 @@ gst_compositor_pad_prepare_frame_start (GstVideoAggregatorPad * pad, return; } + if (gst_aggregator_pad_is_inactive (GST_AGGREGATOR_PAD (pad))) + return; + frame_rect = clamp_rectangle (cpad->xpos + cpad->x_offset, cpad->ypos + cpad->y_offset, width, height, GST_VIDEO_INFO_WIDTH (&vagg->info), GST_VIDEO_INFO_HEIGHT (&vagg->info)); @@ -709,6 +712,7 @@ enum PROP_BACKGROUND, PROP_ZERO_SIZE_IS_UNSCALED, PROP_MAX_THREADS, + PROP_IGNORE_INACTIVE_PADS, }; static void @@ -727,6 +731,10 @@ gst_compositor_get_property (GObject * object, case PROP_MAX_THREADS: g_value_set_uint (value, self->max_threads); break; + case PROP_IGNORE_INACTIVE_PADS: + g_value_set_boolean (value, + gst_aggregator_get_ignore_inactive_pads (GST_AGGREGATOR (object))); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -749,6 +757,10 @@ gst_compositor_set_property (GObject * object, case PROP_MAX_THREADS: self->max_threads = g_value_get_uint (value); break; + case PROP_IGNORE_INACTIVE_PADS: + gst_aggregator_set_ignore_inactive_pads (GST_AGGREGATOR (object), + g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -968,6 +980,9 @@ _fixate_caps (GstAggregator * agg, GstCaps * caps) gint x_offset; gint y_offset; + if (gst_aggregator_pad_is_inactive (GST_AGGREGATOR_PAD (vaggpad))) + continue; + fps_n = GST_VIDEO_INFO_FPS_N (&vaggpad->info); fps_d = GST_VIDEO_INFO_FPS_D (&vaggpad->info); _mixer_pad_get_output_size (GST_COMPOSITOR (vagg), compositor_pad, par_n, @@ -1217,6 +1232,9 @@ _should_draw_background (GstVideoAggregator * vagg) /* Check if the background is completely obscured by a pad * TODO: Also skip if it's obscured by a combination of pads */ for (l = GST_ELEMENT (vagg)->sinkpads; l; l = l->next) { + if (gst_aggregator_pad_is_inactive (GST_AGGREGATOR_PAD (l->data))) + continue; + if (_pad_obscures_rectangle (vagg, l->data, bg_rect)) { draw = FALSE; break; @@ -1611,6 +1629,26 @@ gst_compositor_class_init (GstCompositorClass * klass) "Composite multiple video streams", "Wim Taymans , " "Sebastian Dröge "); + /** + * compositor:ignore-inactive-pads: + * + * Don't wait for inactive pads when live. An inactive pad + * is a pad that hasn't yet received a buffer, but that has + * been waited on at least once. + * + * The purpose of this property is to avoid aggregating on + * timeout when new pads are requested in advance of receiving + * data flow, for example the user may decide to connect it later, + * but wants to configure it already. + * + * Since: 1.20 + */ + g_object_class_install_property (gobject_class, + PROP_IGNORE_INACTIVE_PADS, g_param_spec_boolean ("ignore-inactive-pads", + "Ignore inactive pads", + "Avoid timing out waiting for inactive pads", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gst_type_mark_as_plugin_api (GST_TYPE_COMPOSITOR_PAD, 0); gst_type_mark_as_plugin_api (GST_TYPE_COMPOSITOR_OPERATOR, 0); gst_type_mark_as_plugin_api (GST_TYPE_COMPOSITOR_BACKGROUND, 0);