validate: Add the notion of INTERLACED actions

An interlaced action is an action that will be executed ASYNC but
without that will not block following actions during its execution.
The action should be set to done later on at any point during the
execution of the scenario.

API:
  + GST_VALIDATE_EXECUTE_ACTION_INTERLACED
  + GST_VALIDATE_ACTION_TYPE_INTERLACED

https://bugzilla.gnome.org/show_bug.cgi?id=743994
This commit is contained in:
Thibault Saunier 2014-12-13 19:17:45 +01:00
parent e7cc086f95
commit ef0f78f600
2 changed files with 58 additions and 9 deletions

View file

@ -64,6 +64,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_validate_scenario_debug);
gst_validate_register_action_type ((_tname), "core", (_function), (_params), (_desc), (_is_config)); \ gst_validate_register_action_type ((_tname), "core", (_function), (_params), (_desc), (_is_config)); \
} G_STMT_END } G_STMT_END
#define SCENARIO_LOCK(scenario) (g_mutex_lock(&scenario->priv->lock))
#define SCENARIO_UNLOCK(scenario) (g_mutex_unlock(&scenario->priv->lock))
enum enum
{ {
PROP_0, PROP_0,
@ -90,7 +92,10 @@ struct _GstValidateScenarioPrivate
{ {
GstValidateRunner *runner; GstValidateRunner *runner;
GMutex lock;
GList *actions; GList *actions;
GList *interlaced_actions;
/* List of action that need parsing when reaching ASYNC_DONE /* List of action that need parsing when reaching ASYNC_DONE
* most probably to be able to query duration */ * most probably to be able to query duration */
GList *needs_parsing; GList *needs_parsing;
@ -193,6 +198,12 @@ gst_validate_action_init (GstValidateAction * action)
(GstMiniObjectFreeFunction) _action_free); (GstMiniObjectFreeFunction) _action_free);
} }
static void
gst_validate_action_unref (GstValidateAction * action)
{
gst_mini_object_unref (GST_MINI_OBJECT (action));
}
static GstValidateAction * static GstValidateAction *
gst_validate_action_new (GstValidateScenario * scenario) gst_validate_action_new (GstValidateScenario * scenario)
{ {
@ -513,7 +524,6 @@ _execute_pause (GstValidateScenario * scenario, GstValidateAction * action)
GST_DEBUG ("Pausing for %" GST_TIME_FORMAT, GST_DEBUG ("Pausing for %" GST_TIME_FORMAT,
GST_TIME_ARGS (duration * GST_SECOND)); GST_TIME_ARGS (duration * GST_SECOND));
ret = _execute_set_state (scenario, action); ret = _execute_set_state (scenario, action);
if (ret && duration) if (ret && duration)
@ -955,7 +965,7 @@ get_position (GstValidateScenario * scenario)
GST_INFO_OBJECT (scenario, "Action %" GST_PTR_FORMAT " is DONE now" GST_INFO_OBJECT (scenario, "Action %" GST_PTR_FORMAT " is DONE now"
" executing next", act->structure); " executing next", act->structure);
gst_mini_object_unref (GST_MINI_OBJECT (act)); gst_validate_action_unref (act);
g_list_free (tmp); g_list_free (tmp);
if (scenario->priv->actions) { if (scenario->priv->actions) {
@ -1042,7 +1052,14 @@ get_position (GstValidateScenario * scenario)
} else if (act->state != GST_VALIDATE_EXECUTE_ACTION_ASYNC) { } else if (act->state != GST_VALIDATE_EXECUTE_ACTION_ASYNC) {
tmp = priv->actions; tmp = priv->actions;
priv->actions = g_list_remove_link (priv->actions, tmp); priv->actions = g_list_remove_link (priv->actions, tmp);
gst_mini_object_unref (GST_MINI_OBJECT (act));
if (act->state != GST_VALIDATE_EXECUTE_ACTION_INTERLACED)
gst_validate_action_unref (act);
else {
SCENARIO_LOCK (scenario);
priv->interlaced_actions = g_list_append (priv->interlaced_actions, act);
SCENARIO_UNLOCK (scenario);
}
if (priv->actions == NULL) if (priv->actions == NULL)
g_signal_emit (scenario, scenario_signals[DONE], 0); g_signal_emit (scenario, scenario_signals[DONE], 0);
@ -1383,18 +1400,22 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
case GST_MESSAGE_ERROR: case GST_MESSAGE_ERROR:
case GST_MESSAGE_EOS: case GST_MESSAGE_EOS:
{ {
if (scenario->priv->actions) { SCENARIO_LOCK (scenario);
if (scenario->priv->actions || scenario->priv->interlaced_actions) {
GList *tmp; GList *tmp;
guint nb_actions = 0; guint nb_actions = 0;
gchar *actions = g_strdup (""), *tmpconcat; gchar *actions = g_strdup (""), *tmpconcat;
GList *all_actions = g_list_concat (scenario->priv->actions,
scenario->priv->interlaced_actions);
for (tmp = scenario->priv->actions; tmp; tmp = tmp->next) { for (tmp = all_actions; tmp; tmp = tmp->next) {
GstValidateAction *action = ((GstValidateAction *) tmp->data); GstValidateAction *action = ((GstValidateAction *) tmp->data);
gchar *action_string; gchar *action_string;
tmpconcat = actions; tmpconcat = actions;
action_string = gst_structure_to_string (action->structure); action_string = gst_structure_to_string (action->structure);
if (g_regex_match_simple ("eos|stop", action_string, 0, 0)) { if (g_regex_match_simple ("eos|stop", action_string, 0, 0)) {
gst_validate_action_unref (action);
g_free (action_string); g_free (action_string);
continue; continue;
} }
@ -1402,16 +1423,20 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
nb_actions++; nb_actions++;
actions = actions =
g_strdup_printf ("%s\n%*s%s", actions, 20, "", action_string); g_strdup_printf ("%s\n%*s%s", actions, 20, "", action_string);
gst_validate_action_unref (action);
g_free (tmpconcat); g_free (tmpconcat);
g_free (action_string); g_free (action_string);
} }
g_list_free (all_actions);
scenario->priv->actions = NULL;
scenario->priv->interlaced_actions = NULL;
if (nb_actions > 0) if (nb_actions > 0)
GST_VALIDATE_REPORT (scenario, SCENARIO_NOT_ENDED, GST_VALIDATE_REPORT (scenario, SCENARIO_NOT_ENDED,
"%i actions were not executed: %s", nb_actions, actions); "%i actions were not executed: %s", nb_actions, actions);
g_free (actions); g_free (actions);
} }
SCENARIO_UNLOCK (scenario);
break; break;
} }
@ -1527,7 +1552,7 @@ _load_scenario_file (GstValidateScenario * scenario,
if (IS_CONFIG_ACTION_TYPE (action_type->flags)) { if (IS_CONFIG_ACTION_TYPE (action_type->flags)) {
ret = action_type->execute (scenario, action); ret = action_type->execute (scenario, action);
gst_mini_object_unref (GST_MINI_OBJECT (action)); gst_validate_action_unref (action);
if (ret == FALSE) if (ret == FALSE)
goto failed; goto failed;
@ -1752,6 +1777,8 @@ gst_validate_scenario_init (GstValidateScenario * scenario)
priv->seek_pos_tol = DEFAULT_SEEK_TOLERANCE; priv->seek_pos_tol = DEFAULT_SEEK_TOLERANCE;
priv->segment_start = 0; priv->segment_start = 0;
priv->segment_stop = GST_CLOCK_TIME_NONE; priv->segment_stop = GST_CLOCK_TIME_NONE;
g_mutex_init (&priv->lock);
} }
static void static void
@ -1764,7 +1791,7 @@ gst_validate_scenario_dispose (GObject * object)
if (GST_VALIDATE_SCENARIO (object)->pipeline) if (GST_VALIDATE_SCENARIO (object)->pipeline)
g_object_weak_unref (G_OBJECT (GST_VALIDATE_SCENARIO (object)->pipeline), g_object_weak_unref (G_OBJECT (GST_VALIDATE_SCENARIO (object)->pipeline),
(GWeakNotify) _pipeline_freed_cb, object); (GWeakNotify) _pipeline_freed_cb, object);
g_list_free_full (priv->actions, (GDestroyNotify) gst_mini_object_unref); g_list_free_full (priv->actions, (GDestroyNotify) gst_validate_action_unref);
G_OBJECT_CLASS (gst_validate_scenario_parent_class)->dispose (object); G_OBJECT_CLASS (gst_validate_scenario_parent_class)->dispose (object);
} }
@ -1772,6 +1799,10 @@ gst_validate_scenario_dispose (GObject * object)
static void static void
gst_validate_scenario_finalize (GObject * object) gst_validate_scenario_finalize (GObject * object)
{ {
GstValidateScenarioPrivate *priv = GST_VALIDATE_SCENARIO (object)->priv;
g_mutex_clear (&priv->lock);
G_OBJECT_CLASS (gst_validate_scenario_parent_class)->finalize (object); G_OBJECT_CLASS (gst_validate_scenario_parent_class)->finalize (object);
} }
@ -2059,6 +2090,18 @@ done:
void void
gst_validate_action_set_done (GstValidateAction * action) gst_validate_action_set_done (GstValidateAction * action)
{ {
if (action->state == GST_VALIDATE_EXECUTE_ACTION_INTERLACED) {
if (action->scenario) {
SCENARIO_LOCK (action->scenario);
action->scenario->priv->interlaced_actions =
g_list_remove (action->scenario->priv->interlaced_actions, action);
SCENARIO_UNLOCK (action->scenario);
}
gst_validate_action_unref (action);
}
action->state = GST_VALIDATE_EXECUTE_ACTION_OK; action->state = GST_VALIDATE_EXECUTE_ACTION_OK;
if (action->scenario) { if (action->scenario) {

View file

@ -48,7 +48,9 @@ enum
{ {
GST_VALIDATE_EXECUTE_ACTION_ERROR, GST_VALIDATE_EXECUTE_ACTION_ERROR,
GST_VALIDATE_EXECUTE_ACTION_OK, GST_VALIDATE_EXECUTE_ACTION_OK,
GST_VALIDATE_EXECUTE_ACTION_ASYNC GST_VALIDATE_EXECUTE_ACTION_ASYNC,
GST_VALIDATE_EXECUTE_ACTION_INTERLACED
}; };
/* TODO 2.0 -- Make it an actual enum type */ /* TODO 2.0 -- Make it an actual enum type */
@ -108,12 +110,16 @@ typedef struct _GstValidateActionType GstValidateActionType;
* @GST_VALIDATE_ACTION_TYPE_NONE: No special flag * @GST_VALIDATE_ACTION_TYPE_NONE: No special flag
* @GST_VALIDATE_ACTION_TYPE_CONFIG: The action is a config * @GST_VALIDATE_ACTION_TYPE_CONFIG: The action is a config
* @GST_VALIDATE_ACTION_TYPE_ASYNC: The action can be executed ASYNC * @GST_VALIDATE_ACTION_TYPE_ASYNC: The action can be executed ASYNC
* @GST_VALIDATE_ACTION_TYPE_INTERLACED: The action will be executed async
* but without blocking further actions
* to be executed
*/ */
typedef enum typedef enum
{ {
GST_VALIDATE_ACTION_TYPE_NONE = 0, GST_VALIDATE_ACTION_TYPE_NONE = 0,
GST_VALIDATE_ACTION_TYPE_CONFIG = 1 << 1, GST_VALIDATE_ACTION_TYPE_CONFIG = 1 << 1,
GST_VALIDATE_ACTION_TYPE_ASYNC = 1 << 2, GST_VALIDATE_ACTION_TYPE_ASYNC = 1 << 2,
GST_VALIDATE_ACTION_TYPE_INTERLACED = 1 << 3,
} GstValidateActionTypeFlags; } GstValidateActionTypeFlags;
struct _GstValidateActionType struct _GstValidateActionType