diff --git a/girs/GstValidate-1.0.gir b/girs/GstValidate-1.0.gir
index 04e9574956..4194c01e67 100644
--- a/girs/GstValidate-1.0.gir
+++ b/girs/GstValidate-1.0.gir
@@ -3839,6 +3839,12 @@ against
+
+ Emitted when the 'stop' action is fired
+
+
+
+
diff --git a/subprojects/gst-devtools/validate/gst/validate/gst-validate-scenario.c b/subprojects/gst-devtools/validate/gst/validate/gst-validate-scenario.c
index e55ee4bde2..0827168057 100644
--- a/subprojects/gst-devtools/validate/gst/validate/gst-validate-scenario.c
+++ b/subprojects/gst-devtools/validate/gst/validate/gst-validate-scenario.c
@@ -139,6 +139,7 @@ enum
{
DONE,
ACTION_DONE,
+ STOPPING,
LAST_SIGNAL
};
@@ -2161,17 +2162,32 @@ typedef struct
{
GstValidateAction *action;
GRecMutex m;
- gulong sid;
+ gulong message_sid;
+ gulong stopping_sid;
GList *wanted_streams;
+
+
+ gint wanted_n_calls;
+ gint n_calls;
+
} SelectStreamData;
static SelectStreamData *
select_stream_data_new (GstValidateAction * action)
{
- SelectStreamData *d = g_new0 (SelectStreamData, 1);
+ SelectStreamData *d = g_atomic_rc_box_new0 (SelectStreamData);
- d->action = action;
+ d->action = gst_validate_action_ref (action);
+ if (!gst_structure_get_int (action->structure, "n-calls", &d->wanted_n_calls)) {
+ d->wanted_n_calls = 1;
+ }
+
+ if (d->wanted_n_calls < -1) {
+ gst_validate_error_structure (action,
+ "`n-calls` in %" GST_PTR_FORMAT " can not be < -1, got %d",
+ action->structure, d->wanted_n_calls);
+ }
return d;
}
@@ -2181,9 +2197,13 @@ select_stream_data_free (SelectStreamData * d)
{
gst_validate_action_unref (d->action);
g_list_free_full (d->wanted_streams, g_free);
- g_free (d);
}
+static void
+select_stream_data_unref (SelectStreamData * d)
+{
+ g_atomic_rc_box_release_full (d, (GDestroyNotify) select_stream_data_free);
+}
static void
stream_selection_cb (GstBus * bus, GstMessage * message, SelectStreamData * d)
@@ -2203,6 +2223,7 @@ stream_selection_cb (GstBus * bus, GstMessage * message, SelectStreamData * d)
break;
case GST_MESSAGE_STREAMS_SELECTED:
g_rec_mutex_lock (&d->m);
+ scenario = gst_validate_action_get_scenario (d->action);
gst_message_parse_streams_selected (message, &selected_streams);
g_assert (selected_streams);
goto done;
@@ -2274,14 +2295,21 @@ stream_selection_cb (GstBus * bus, GstMessage * message, SelectStreamData * d)
g_list_free_full (d->wanted_streams, g_free);
d->wanted_streams = streams;
+ d->n_calls += 1;
done:
- if (selected_streams && d->sid) {
+ if (selected_streams && d->message_sid &&
+ d->wanted_n_calls >= 1 && d->n_calls == d->wanted_n_calls) {
/* Consider action done once we get the STREAM_SELECTED signal */
gst_validate_action_set_done (gst_validate_action_ref (d->action));
gst_bus_disable_sync_message_emission (bus);
- g_signal_handler_disconnect (bus, d->sid);
- d->sid = 0;
+ g_signal_handler_disconnect (bus, d->message_sid);
+ d->message_sid = 0;
+
+ if (d->stopping_sid) {
+ g_signal_handler_disconnect (scenario, d->stopping_sid);
+ d->stopping_sid = 0;
+ }
}
gst_clear_object (&scenario);
@@ -2290,6 +2318,40 @@ done:
g_rec_mutex_unlock (&d->m);
}
+static void
+stream_selection_scenario_stopping_cb (GstValidateScenario * scenario,
+ SelectStreamData * d)
+{
+ g_rec_mutex_lock (&d->m);
+ GstElement *pipeline = gst_validate_scenario_get_pipeline (scenario);
+ GstBus *bus = NULL;
+
+ if (pipeline) {
+ bus = gst_element_get_bus (pipeline);
+ }
+
+ if (!((d->wanted_n_calls == 0 && d->n_calls > 0) || d->wanted_n_calls == -1)) {
+ gst_validate_report_action (GST_VALIDATE_REPORTER (scenario), d->action,
+ SCENARIO_ACTION_EXECUTION_ERROR,
+ "Wrong number of calls: wanted %d got: %d",
+ d->wanted_n_calls, d->n_calls);
+ }
+
+ gst_validate_action_set_done (gst_validate_action_ref (d->action));
+
+ if (bus && d->message_sid) {
+ gst_bus_disable_sync_message_emission (bus);
+ g_signal_handler_disconnect (bus, d->message_sid);
+ d->message_sid = 0;
+ }
+
+ if (d->stopping_sid) {
+ g_signal_handler_disconnect (scenario, d->stopping_sid);
+ d->stopping_sid = 0;
+ }
+ g_rec_mutex_unlock (&d->m);
+}
+
static GstValidateExecuteActionReturn
_execute_select_streams (GstValidateScenario * scenario,
GstValidateAction * action)
@@ -2302,10 +2364,15 @@ _execute_select_streams (GstValidateScenario * scenario,
SelectStreamData *d = select_stream_data_new (action);
/* Ensure that the data signal ID is set before the callback is called */
g_rec_mutex_lock (&d->m);
- d->sid = g_signal_connect_data (bus,
+ d->message_sid = g_signal_connect_data (bus,
"sync-message",
G_CALLBACK (stream_selection_cb),
- d, (GClosureNotify) select_stream_data_free, 0);
+ d, (GClosureNotify) select_stream_data_unref, 0);
+ d->stopping_sid = g_signal_connect_data (scenario,
+ "stopping",
+ G_CALLBACK (stream_selection_scenario_stopping_cb),
+ g_atomic_rc_box_acquire (d),
+ (GClosureNotify) select_stream_data_unref, 0);
g_rec_mutex_unlock (&d->m);
gst_object_unref (bus);
@@ -5680,6 +5747,19 @@ gst_validate_scenario_class_init (GstValidateScenarioClass * klass)
g_signal_new ("action-done", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1,
GST_TYPE_VALIDATE_ACTION);
+
+ /**
+ * GstValidateScenario::stopping:
+ * @scenario: The scenario that is being stopped
+ *
+ * Emitted when the 'stop' action is fired
+ *
+ * Since: 1.26
+ */
+ scenario_signals[STOPPING] =
+ g_signal_new ("stopping", G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
+
}
static void
@@ -6861,6 +6941,9 @@ _execute_stop (GstValidateScenario * scenario, GstValidateAction * action)
DECLARE_AND_GET_PIPELINE (scenario, action);
bus = gst_element_get_bus (pipeline);
+
+ g_signal_emit (scenario, scenario_signals[STOPPING], 0);
+
SCENARIO_LOCK (scenario);
if (priv->execute_actions_source_id) {
g_source_remove (priv->execute_actions_source_id);
@@ -7903,6 +7986,17 @@ register_action_types (void)
.types = "[int]",
.possible_variables = NULL,
},
+ {
+ .name = "n-calls",
+ .description = "Number of times the `select-stream` event should be sent to the pipeline\n"
+ " - `0` means 0 or more"
+ " - `-1` means at least once"
+ " - Other numbers are exact number of calls",
+ .mandatory = FALSE,
+ .types = "int",
+ .def = "1",
+ .possible_variables = NULL,
+ },
{NULL}
}),
"Select the stream on next `GST_STREAM_COLLECTION` message on the bus.",