validate:scenario: Handle action execution after pipeline destruction

Summary:
It is possible to keep executing actions after the pipeline
has been destroyed.

API:
  GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE

Depends on D171

Reviewers: Mathieu_Du

Differential Revision: http://phabricator.freedesktop.org/D172
This commit is contained in:
Thibault Saunier 2015-05-13 12:18:18 +02:00
parent 92732c9f24
commit d90f17a5b1
4 changed files with 50 additions and 21 deletions

View file

@ -66,7 +66,8 @@ gst_validate_gapplication_init (GstPlugin * plugin)
gst_validate_register_action_type_dynamic (plugin, "stop", gst_validate_register_action_type_dynamic (plugin, "stop",
GST_RANK_PRIMARY, _execute_stop, NULL, GST_RANK_PRIMARY, _execute_stop, NULL,
"Sets the pipeline state to NULL", "Sets the pipeline state to NULL",
GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL); GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL |
GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE);
return TRUE; return TRUE;
} }

View file

@ -505,7 +505,8 @@ gst_validate_gtk_init (GstPlugin * plugin)
{NULL} {NULL}
}), }),
"Put a GdkEvent on the event list using gdk_put_event", "Put a GdkEvent on the event list using gdk_put_event",
GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL); GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL |
GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE);
/* *INDENT-ON* */ /* *INDENT-ON* */
return TRUE; return TRUE;

View file

@ -1070,6 +1070,30 @@ _should_execute_action (GstValidateScenario * scenario, GstValidateAction * act,
GST_DEBUG_OBJECT (scenario, "No action to execute"); GST_DEBUG_OBJECT (scenario, "No action to execute");
return FALSE; return FALSE;
} else if (scenario->pipeline == NULL) {
if (!(GST_VALIDATE_ACTION_GET_TYPE (act)->flags &
GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE)) {
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
"Trying to execute an %s action after the pipeline has been destroyed"
" but the type has not been marked as "
"GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE", act->type);
return FALSE;
} else if (GST_CLOCK_TIME_IS_VALID (act->playback_time)) {
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
"Trying to execute action %s with playback time %" GST_TIME_FORMAT
" after the pipeline has been destroyed. It is impossible"
" to execute an action with a playback time specified "
" after the pipeline has been destroyed",
act->type, GST_TIME_ARGS (act->playback_time));
return FALSE;
}
GST_DEBUG_OBJECT (scenario, "No pipeline, go and execute action!");
return TRUE;
} else if (scenario->priv->got_eos) { } else if (scenario->priv->got_eos) {
GST_DEBUG_OBJECT (scenario, "Just got EOS go and execute next action!"); GST_DEBUG_OBJECT (scenario, "Just got EOS go and execute next action!");
scenario->priv->got_eos = FALSE; scenario->priv->got_eos = FALSE;
@ -1495,7 +1519,7 @@ stop_waiting_signal (GstBin * bin, GstElement * element,
_add_execute_actions_gsource (scenario); _add_execute_actions_gsource (scenario);
} }
static gboolean static GstValidateExecuteActionReturn
_execute_timed_wait (GstValidateScenario * scenario, GstValidateAction * action) _execute_timed_wait (GstValidateScenario * scenario, GstValidateAction * action)
{ {
GstValidateScenarioPrivate *priv = scenario->priv; GstValidateScenarioPrivate *priv = scenario->priv;
@ -1545,7 +1569,7 @@ _execute_timed_wait (GstValidateScenario * scenario, GstValidateAction * action)
return GST_VALIDATE_EXECUTE_ACTION_ASYNC; return GST_VALIDATE_EXECUTE_ACTION_ASYNC;
} }
static gboolean static GstValidateExecuteActionReturn
_execute_wait_for_signal (GstValidateScenario * scenario, _execute_wait_for_signal (GstValidateScenario * scenario,
GstValidateAction * action) GstValidateAction * action)
{ {
@ -1556,7 +1580,15 @@ _execute_wait_for_signal (GstValidateScenario * scenario,
if (signal_name == NULL) { if (signal_name == NULL) {
GST_ERROR ("No signal-name given for wait action"); GST_ERROR ("No signal-name given for wait action");
return FALSE; return GST_VALIDATE_EXECUTE_ACTION_ERROR;
}
if (scenario->pipeline == NULL) {
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
"Can't execute a 'wait for signal' action after the pipeline "
" has been destroyed.");
return GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
} }
target = _get_target_element (scenario, action); target = _get_target_element (scenario, action);
@ -1588,6 +1620,14 @@ _execute_wait_for_message (GstValidateScenario * scenario,
const gchar *message_type = gst_structure_get_string const gchar *message_type = gst_structure_get_string
(action->structure, "message-type"); (action->structure, "message-type");
if (scenario->pipeline == NULL) {
GST_VALIDATE_REPORT (scenario, SCENARIO_ACTION_EXECUTION_ERROR,
"Can't execute a 'wait for message' action after the pipeline "
" has been destroyed.");
return GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED;
}
gst_validate_printf (action, "Waiting for '%s' message\n", message_type); gst_validate_printf (action, "Waiting for '%s' message\n", message_type);
if (priv->execute_actions_source_id) { if (priv->execute_actions_source_id) {
@ -1600,7 +1640,7 @@ _execute_wait_for_message (GstValidateScenario * scenario,
return GST_VALIDATE_EXECUTE_ACTION_ASYNC; return GST_VALIDATE_EXECUTE_ACTION_ASYNC;
} }
static gboolean static GstValidateExecuteActionReturn
_execute_wait (GstValidateScenario * scenario, GstValidateAction * action) _execute_wait (GstValidateScenario * scenario, GstValidateAction * action)
{ {
if (gst_structure_has_field (action->structure, "signal-name")) { if (gst_structure_has_field (action->structure, "signal-name")) {
@ -2124,20 +2164,6 @@ static void
_pipeline_freed_cb (GstValidateScenario * scenario, _pipeline_freed_cb (GstValidateScenario * scenario,
GObject * where_the_object_was) GObject * where_the_object_was)
{ {
GstValidateScenarioPrivate *priv = scenario->priv;
SCENARIO_LOCK (scenario);
if (priv->execute_actions_source_id) {
g_source_remove (priv->execute_actions_source_id);
priv->execute_actions_source_id = 0;
}
if (priv->wait_id) {
g_source_remove (priv->wait_id);
priv->wait_id = 0;
}
SCENARIO_UNLOCK (scenario);
scenario->pipeline = NULL; scenario->pipeline = NULL;
GST_DEBUG_OBJECT (scenario, "pipeline was freed"); GST_DEBUG_OBJECT (scenario, "pipeline was freed");
@ -3353,7 +3379,7 @@ init_scenarios (void)
{NULL} {NULL}
}), }),
"Waits for signal 'signal-name', message 'message-type', or during 'duration' seconds", "Waits for signal 'signal-name', message 'message-type', or during 'duration' seconds",
GST_VALIDATE_ACTION_TYPE_NONE); GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE);
REGISTER_ACTION_TYPE ("dot-pipeline", _execute_dot_pipeline, NULL, REGISTER_ACTION_TYPE ("dot-pipeline", _execute_dot_pipeline, NULL,
"Dots the pipeline (the 'name' property will be used in the dot filename).\n" "Dots the pipeline (the 'name' property will be used in the dot filename).\n"

View file

@ -147,6 +147,7 @@ typedef enum
GST_VALIDATE_ACTION_TYPE_NEEDS_CLOCK = 1 << 5, GST_VALIDATE_ACTION_TYPE_NEEDS_CLOCK = 1 << 5,
GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL = 1 << 6, GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL = 1 << 6,
GST_VALIDATE_ACTION_TYPE_CAN_BE_OPTIONAL = 1 << 7, GST_VALIDATE_ACTION_TYPE_CAN_BE_OPTIONAL = 1 << 7,
GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE = 1 << 8,
} GstValidateActionTypeFlags; } GstValidateActionTypeFlags;
/** /**