Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/867>
"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,
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,
"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));
}
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;
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;
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;
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
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);
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);
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));
PROP_BACKGROUND,
PROP_ZERO_SIZE_IS_UNSCALED,
PROP_MAX_THREADS,
+ PROP_IGNORE_INACTIVE_PADS,
};
static void
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;
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;
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,
/* 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;
"Composite multiple video streams", "Wim Taymans <wim@fluendo.com>, "
"Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+ /**
+ * 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);