mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 19:21:06 +00:00
validate:scenario: Enhance variable implementation
- Stop arbitrarily consider params as ClockTime based on their names but add a convetion that the `.type` field of the ActionType should end by `(GstClockTime)` when it is a clock time.
This commit is contained in:
parent
b7616e5fab
commit
394242c224
21 changed files with 323 additions and 204 deletions
|
@ -1,14 +1,14 @@
|
|||
description, duration=55.0, min-media-duration=470.0, seek=true, reverse-playback=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, name=backward-seek, playback-time=0.0, rate=-1.0, start=0.0, stop=310.0, flags="$(default-flags)"
|
||||
seek, name=forward-seek, playback-time=305.0, rate=1.0, start=305.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=2.0, start=310.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=320.0, rate=-2.0, start=0.0, stop=320.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=4.0, start=310.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=330.0, rate=-4.0, start=0.0, stop=330.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=8.0, start=310.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=350.0, rate=-8.0, start=0.0, stop=350.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=16.0, start=310.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=390.0, rate=-16.0, start=0.0, stop=390.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=32.0, start=310.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=470.0, rate=-32.0, start=310.0, stop=470.0, flags="$(default-flags)"
|
||||
seek, name=backward-seek, playback-time=0.0, rate=-1.0, start=0.0, stop=310.0, flags="$(default_flags)"
|
||||
seek, name=forward-seek, playback-time=305.0, rate=1.0, start=305.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=2.0, start=310.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=320.0, rate=-2.0, start=0.0, stop=320.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=4.0, start=310.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=330.0, rate=-4.0, start=0.0, stop=330.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=8.0, start=310.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=350.0, rate=-8.0, start=0.0, stop=350.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=16.0, start=310.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=390.0, rate=-16.0, start=0.0, stop=390.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time=310.0, rate=32.0, start=310.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=470.0, rate=-32.0, start=310.0, stop=470.0, flags="$(default_flags)"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
description, duration=30.0, minfo-media-duration=310.0, seek=true, reverse-playback=true, need-clock-sync=true, min-media-duration=310.0
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, name=Fast-backward-seek, playback-time=0.0, rate=-2.0, start=0.0, stop=310.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=300.0, rate=-4.0, start=0.0, stop=300.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=280.0, rate=-8.0, start=0.0, stop=280.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=240.0, rate=-16.0, start=0.0, stop=240.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=160.0, rate=-32.0, start=0.0, stop=160.0, flags="$(default-flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=0.0, rate=-2.0, start=0.0, stop=310.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=300.0, rate=-4.0, start=0.0, stop=300.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=280.0, rate=-8.0, start=0.0, stop=280.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=240.0, rate=-16.0, start=0.0, stop=240.0, flags="$(default_flags)"
|
||||
seek, name=Fast-backward-seek, playback-time=160.0, rate=-32.0, start=0.0, stop=160.0, flags="$(default_flags)"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
description, duration=25.0, seek=true, need-clock-sync=true, min-media-duration=5.0
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, name=Fast-forward-seek, playback-time=0.0, rate=2.0, start=0.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(10.0, $duration * 0.0625)", rate=4.0, start=0.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(20.0, $duration * 0.125)", rate=8.0, start=0.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(40.0, $duration * 0.25)", rate=16.0, start=0.0, flags="$(default-flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(80.0, $duration * 0.50)", rate=32.0, start=0.0, flags="$(default-flags)"
|
||||
stop, playback-time="min($duration - 0.3, 160.0)"
|
||||
seek, name=Fast-forward-seek, playback-time=0.0, rate=2.0, start=0.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(10.0, $(duration) * 0.0625)", rate=4.0, start=0.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(20.0, $(duration) * 0.125)", rate=8.0, start=0.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(40.0, $(duration) * 0.25)", rate=16.0, start=0.0, flags="$(default_flags)"
|
||||
seek, name=Fast-forward-seek, playback-time="min(80.0, $(duration) * 0.50)", rate=32.0, start=0.0, flags="$(default_flags)"
|
||||
stop, playback-time="min($(duration) - 0.3, 160.0)"
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
set-vars,\
|
||||
default-flags=accurate+flush
|
||||
default_flags=accurate+flush
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
description, seek=true, reverse-playback=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, name=Reverse-seek, playback-time=0.0, rate=-1.0, start="max($duration - 15.0, 0.0)", stop=$(duration), flags="$(default-flags)"
|
||||
seek, name=Reverse-seek, playback-time=0.0, rate=-1.0, start="max($(duration) - 15.0, 0.0)", stop="$(duration)", flags="$(default_flags)"
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
set-vars,\
|
||||
default-flags=flush
|
||||
default_flags=flush
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
description, seek=true, handles-states=true, needs_preroll=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
pause, playback-time=0.0
|
||||
seek, playback-time=0.0, start="$duration - 0.5", flags="$(default-flags)"
|
||||
seek, playback-time=0.0, start=position-0.1, repeat="min(10, ($duration - 0.6))/0.1", flags="$(default-flags)"
|
||||
seek, playback-time=0.0, start="$(duration) - 0.5", flags="$(default_flags)"
|
||||
seek, playback-time=0.0, start=position-0.1, repeat="min(10, ($(duration) - 0.6))/0.1", flags="$(default_flags)"
|
||||
play, playback-time=0.0
|
||||
stop, playback-time=1.0
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
description, seek=true, handles-states=true, needs_preroll=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
pause, playback-time=0.0
|
||||
seek, playback-time=0.0, start="$duration - 0.5", flags="$(default-flags)"
|
||||
seek, playback-time=0.0, start=position-0.1, repeat="($duration - 0.6)/0.1", flags="$(default-flags)"
|
||||
seek, playback-time=0.0, start="$(duration) - 0.5", flags="$(default_flags)"
|
||||
seek, playback-time=0.0, start=position-0.1, repeat="($(duration) - 0.6)/0.1", flags="$(default_flags)"
|
||||
play, playback-time=0.0
|
||||
stop, playback-time=1.0
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
description, seek=true, handles-states=true, needs_preroll=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
pause, playback-time=0.0
|
||||
seek, playback-time=0.0, start=position+0.1, repeat="min(10, ($duration - 0.5))/0.1", flags="$(default-flags)"
|
||||
seek, playback-time=0.0, start=position+0.1, repeat="min(10, ($(duration) - 0.5) / 0.1)", flags="$(default_flags)"
|
||||
play, playback-time=0.0
|
||||
stop, playback-time=1.0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
description, seek=true, handles-states=true, needs_preroll=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
pause, playback-time=0.0
|
||||
seek, playback-time=0.0, start=position+0.1, repeat="($duration - 0.5)/0.1", flags="$(default-flags)"
|
||||
seek, playback-time=0.0, start=position+0.1, repeat="($(duration) - 0.5)/0.1", flags="$(default_flags)"
|
||||
play, playback-time=0.0
|
||||
stop, playback-time=1.0
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
description, seek=true, duration=30, need-clock-sync=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, name=Backward-seek, playback-time="min(5.0, ($duration / 4))", rate=1.0, start=0.0, flags="$(default-flags)"
|
||||
seek, name=Backward-seek, playback-time="min(10.0, 2*($duration / 4))", rate=1.0, start="min(5.0, $duration / 4)", flags="$(default-flags)"
|
||||
seek, name=Backward-seek, playback-time="min(15.0, 3*($duration / 4))", rate=1.0, start="min(10.0, 2*($duration / 4))", flags="$(default-flags)"
|
||||
stop, playback-time="min(15.0, 3*($duration / 4))"
|
||||
seek, name=Backward-seek, playback-time="min(5.0, ($(duration) / 4))", rate=1.0, start=0.0, flags="$(default_flags)"
|
||||
seek, name=Backward-seek, playback-time="min(10.0, 2*($(duration) / 4))", rate=1.0, start="min(5.0, $(duration) / 4)", flags="$(default_flags)"
|
||||
seek, name=Backward-seek, playback-time="min(15.0, 3*($(duration) / 4))", rate=1.0, start="min(10.0, 2*($(duration) / 4))", flags="$(default_flags)"
|
||||
stop, playback-time="min(15.0, 3*($(duration) / 4))"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
description, seek=true, duration=20, need-clock-sync=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
set-vars, test=(string)5.0
|
||||
seek, name=First-forward-seek, playback-time="min($test, ($duration/8))", start="min(10, 2*($duration/8))", flags="$(default-flags)"
|
||||
seek, name=Second-forward-seek, playback-time="min(15.0, 3*($duration/8))", start="min(20, 4*($duration/8))", flags="$(default-flags)"
|
||||
seek, name=Third-forward-seek, playback-time="min(25, 5*($duration/8))", start="min(30.0, 6*($duration/8))", flags="$(default-flags)"
|
||||
seek, name=First-forward-seek, playback-time="min(5.0, ($(duration)/8))", start="min(10, 2*($(duration)/8))", flags="$(default_flags)"
|
||||
seek, name=Second-forward-seek, playback-time="min(15.0, 3*($(duration)/8))", start="min(20, 4*($(duration)/8))", flags="$(default_flags)"
|
||||
seek, name=Third-forward-seek, playback-time="min(25, 5*($(duration)/8))", start="min(30.0, 6*($(duration)/8))", flags="$(default_flags)"
|
||||
stop, playback-time=35.0
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
description, seek=true, duration=40, min-media-duration=45.0
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, name=Forward-seek, playback-time=0.0, rate=1.0, start=5.0, flags="$(default-flags)"
|
||||
seek, name=Backward-seek, playback-time=10.0, rate=1.0, start=0.0, flags="$(default-flags)"
|
||||
seek, name=Backward-seek, playback-time=5.0, rate=1.0, start=25.0, stop=-1, flags="$(default-flags)"
|
||||
seek, name=Backward-seek, playback-time=30.0, rate=1.0, start=0.0, flags="$(default-flags)"
|
||||
seek, name=Forward-seek, playback-time=5.0, rate=1.0, start=15.0, flags="$(default-flags)"
|
||||
seek, name=Forward-seek, playback-time=20.0, rate=1.0, start=35.0, flags="$(default-flags)"
|
||||
seek, name=Backward-seek, playback-time=40.0, rate=1.0, start=25.0, flags="$(default-flags)"
|
||||
seek, name=Last-backward-seek, playback-time=30.0, rate=1.0, start=5.0, stop=10.0, flags="$(default-flags)"
|
||||
seek, name=Forward-seek, playback-time=0.0, rate=1.0, start=5.0, flags="$(default_flags)"
|
||||
seek, name=Backward-seek, playback-time=10.0, rate=1.0, start=0.0, flags="$(default_flags)"
|
||||
seek, name=Backward-seek, playback-time=5.0, rate=1.0, start=25.0, stop=-1, flags="$(default_flags)"
|
||||
seek, name=Backward-seek, playback-time=30.0, rate=1.0, start=0.0, flags="$(default_flags)"
|
||||
seek, name=Forward-seek, playback-time=5.0, rate=1.0, start=15.0, flags="$(default_flags)"
|
||||
seek, name=Forward-seek, playback-time=20.0, rate=1.0, start=35.0, flags="$(default_flags)"
|
||||
seek, name=Backward-seek, playback-time=40.0, rate=1.0, start=25.0, flags="$(default_flags)"
|
||||
seek, name=Last-backward-seek, playback-time=30.0, rate=1.0, start=5.0, stop=10.0, flags="$(default_flags)"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
description, seek=true, duration=5.0, need_clock_sync=true, min-media-duration=2
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, playback-time=1.0, start=0.0, stop="min(5.0, duration-1.0)", flags="$(default-flags)"
|
||||
seek, playback-time=1.0, start=0.0, stop="min(5.0, duration-1.0)", flags="$(default_flags)"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
description, seek=true, duration=5.0
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, playback-time=1.0, rate=1.0, start=2.0, flags="$(default-flags)"
|
||||
seek, playback-time=3.0, rate=1.0, start=0.0, flags="$(default-flags)"
|
||||
seek, playback-time=1.0, rate=1.0, start=2.0, stop=3.0, flags="$(default-flags)"
|
||||
seek, playback-time=1.0, rate=1.0, start=2.0, flags="$(default_flags)"
|
||||
seek, playback-time=3.0, rate=1.0, start=0.0, flags="$(default_flags)"
|
||||
seek, playback-time=1.0, rate=1.0, start=2.0, stop=3.0, flags="$(default_flags)"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
description, summary="Use the set seek type to seek at 5 seconds after 2 seconds", seek=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, playback-time=2.0, rate=1.0, start_type=set, start=5.0, stop_type=none, stop=0.0, flags="$(default-flags)"
|
||||
seek, playback-time=2.0, rate=1.0, start_type=set, start=5.0, stop_type=none, stop=0.0, flags="$(default_flags)"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
description, summary="Use the set seek type to seek at 0 secs stop 10secs after 5 secs", seek=true
|
||||
description, duration=15.0, seek=true
|
||||
include,location=includes/default-seek-flags.scenario
|
||||
seek, playback-time=5.0, rate=1.0, start_type=none, start=0.0, stop_type=set, stop=10.0, flags="$(default-flags)"
|
||||
seek, playback-time=5.0, rate=1.0, start_type=none, start=0.0, stop_type=set, stop=10.0, flags="$(default_flags)"
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
*
|
||||
* Copyright (C) 2013 Collabora Ltd.
|
||||
* Author: Thibault Saunier <thibault.saunier@collabora.com>
|
||||
* Copyright (C) 2018 Thibault Saunier <tsaunier@igalia.com>
|
||||
* Copyright (C) 2018-2019 Igalia S.L
|
||||
|
||||
*
|
||||
* gst-validate-scenario.c - Validate Scenario class
|
||||
*
|
||||
|
@ -124,6 +125,8 @@ struct _GstValidateScenarioPrivate
|
|||
GList *interlaced_actions; /* MT safe. Protected with SCENARIO_LOCK */
|
||||
GList *on_addition_actions; /* MT safe. Protected with SCENARIO_LOCK */
|
||||
|
||||
gboolean needs_playback_parsing;
|
||||
|
||||
/* List of action that need parsing when reaching ASYNC_DONE
|
||||
* most probably to be able to query duration */
|
||||
|
||||
|
@ -340,7 +343,7 @@ gst_validate_action_init (GstValidateAction * action)
|
|||
g_weak_ref_init (&action->priv->scenario, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
gst_validate_action_unref (GstValidateAction * action)
|
||||
{
|
||||
gst_mini_object_unref (GST_MINI_OBJECT (action));
|
||||
|
@ -442,93 +445,115 @@ _find_action_type (const gchar * type_name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_set_variable_func (const gchar * name, double *value, gpointer user_data)
|
||||
static void
|
||||
_update_well_known_vars (GstValidateScenario * scenario)
|
||||
{
|
||||
gboolean res;
|
||||
const gchar *value_str;
|
||||
gchar *tmp;
|
||||
GstValidateScenario *scenario = GST_VALIDATE_SCENARIO (user_data);
|
||||
gint64 duration, position;
|
||||
gdouble dduration, dposition;
|
||||
GstElement *pipeline = gst_validate_scenario_get_pipeline (scenario);
|
||||
|
||||
if (!pipeline) {
|
||||
GST_ERROR_OBJECT (scenario, "No pipeline set anymore!");
|
||||
gst_structure_remove_fields (scenario->priv->vars, "position", "duration",
|
||||
NULL);
|
||||
|
||||
return FALSE;
|
||||
if (!pipeline)
|
||||
return;
|
||||
|
||||
if (!gst_element_query_duration (pipeline, GST_FORMAT_TIME, &duration) ||
|
||||
!GST_CLOCK_TIME_IS_VALID (duration)) {
|
||||
GstValidateMonitor *monitor =
|
||||
(GstValidateMonitor *) (g_object_get_data ((GObject *)
|
||||
pipeline, "validate-monitor"));
|
||||
GST_INFO_OBJECT (scenario,
|
||||
"Could not query duration. Trying to get duration from media-info");
|
||||
if (monitor && monitor->media_descriptor)
|
||||
duration =
|
||||
gst_validate_media_descriptor_get_duration
|
||||
(monitor->media_descriptor);
|
||||
}
|
||||
|
||||
if (!g_strcmp0 (name, "$duration") || !g_strcmp0 (name, "duration")) {
|
||||
gint64 duration;
|
||||
if (!GST_CLOCK_TIME_IS_VALID (duration))
|
||||
dduration = G_MAXDOUBLE;
|
||||
else
|
||||
dduration = ((double) duration / GST_SECOND);
|
||||
|
||||
if (!(res =
|
||||
gst_element_query_duration (pipeline, GST_FORMAT_TIME, &duration))
|
||||
|| !GST_CLOCK_TIME_IS_VALID (duration)) {
|
||||
GstValidateMonitor *monitor =
|
||||
(GstValidateMonitor *) (g_object_get_data ((GObject *)
|
||||
pipeline, "validate-monitor"));
|
||||
GST_WARNING_OBJECT (scenario,
|
||||
"Could not query duration. Trying to get duration from media-info");
|
||||
if (monitor && monitor->media_descriptor)
|
||||
duration =
|
||||
gst_validate_media_descriptor_get_duration
|
||||
(monitor->media_descriptor);
|
||||
else {
|
||||
GST_ERROR_OBJECT (scenario, "Media-info not set");
|
||||
if (!res)
|
||||
goto fail;
|
||||
gst_structure_set (scenario->priv->vars, "duration", G_TYPE_DOUBLE, dduration,
|
||||
NULL);
|
||||
if (gst_element_query_position (pipeline, GST_FORMAT_TIME, &position)) {
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (position))
|
||||
dposition = G_MAXDOUBLE;
|
||||
else
|
||||
dposition = ((double) position / GST_SECOND);
|
||||
|
||||
gst_structure_set (scenario->priv->vars, "position", G_TYPE_DOUBLE,
|
||||
dposition, NULL);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (scenario, "Could not query position");
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
_replace_variables_in_string (GstValidateScenario * scenario,
|
||||
GstValidateAction * action, const gchar * in_string)
|
||||
{
|
||||
GRegex *regex;
|
||||
gint varname_len;
|
||||
GMatchInfo *match_info;
|
||||
const gchar *var_value;
|
||||
gchar *tmpstring, *string = g_strdup (in_string);
|
||||
|
||||
_update_well_known_vars (scenario);
|
||||
regex = g_regex_new ("\\$\\((\\w+)\\)", 0, 0, NULL);
|
||||
g_regex_match (regex, string, 0, &match_info);
|
||||
while (g_match_info_matches (match_info)) {
|
||||
GRegex *replace_regex;
|
||||
gchar *tmp, *varname, *pvarname = g_match_info_fetch (match_info, 0);
|
||||
|
||||
varname_len = strlen (pvarname);
|
||||
varname = g_malloc (sizeof (gchar) * varname_len - 3);
|
||||
strncpy (varname, &pvarname[2], varname_len - 3);
|
||||
varname[varname_len - 3] = '\0';
|
||||
|
||||
if (gst_structure_has_field_typed (scenario->priv->vars, varname,
|
||||
G_TYPE_DOUBLE)) {
|
||||
var_value = varname;
|
||||
} else {
|
||||
var_value = gst_structure_get_string (scenario->priv->vars, varname);
|
||||
if (!var_value) {
|
||||
g_error ("Trying to use undefined variable : %s (%s)", varname,
|
||||
gst_structure_to_string (scenario->priv->vars));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (duration))
|
||||
*value = G_MAXDOUBLE;
|
||||
else
|
||||
*value = ((double) duration / GST_SECOND);
|
||||
tmp = g_strdup_printf ("\\$\\(%s\\)", varname);
|
||||
replace_regex = g_regex_new (tmp, 0, 0, NULL);
|
||||
tmpstring = string;
|
||||
string = g_regex_replace (replace_regex, string, -1, 0, var_value, 0, NULL);
|
||||
|
||||
goto done;
|
||||
} else if (!g_strcmp0 (name, "$position") || !g_strcmp0 (name, "position")) {
|
||||
gint64 position;
|
||||
GST_INFO_OBJECT (action, "Setting variable %s to %s", varname, var_value);
|
||||
g_free (tmpstring);
|
||||
g_regex_unref (replace_regex);
|
||||
g_free (pvarname);
|
||||
|
||||
if (!gst_element_query_position (pipeline, GST_FORMAT_TIME, &position)) {
|
||||
GST_WARNING_OBJECT (scenario, "Could not query position");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (position))
|
||||
*value = G_MAXDOUBLE;
|
||||
else
|
||||
*value = ((double) position / GST_SECOND);
|
||||
|
||||
goto done;
|
||||
g_match_info_next (match_info, NULL);
|
||||
}
|
||||
g_match_info_free (match_info);
|
||||
g_regex_unref (regex);
|
||||
|
||||
if (name[0] != '$') {
|
||||
g_error ("Variable name %s is invalid as it doesn't start with $", name);
|
||||
return string;
|
||||
}
|
||||
|
||||
goto fail;
|
||||
}
|
||||
static gboolean
|
||||
_set_variable_func (const gchar * name, double *value, gpointer user_data)
|
||||
{
|
||||
GstValidateScenario *scenario = (GstValidateScenario *) user_data;
|
||||
|
||||
if (gst_structure_get_double (scenario->priv->vars, &name[1], value))
|
||||
goto done;
|
||||
if (!gst_structure_get_double (scenario->priv->vars, name, value))
|
||||
return FALSE;
|
||||
|
||||
value_str = gst_structure_get_string (scenario->priv->vars, &name[1]);
|
||||
*value = g_strtod (value_str, &tmp);
|
||||
if (tmp[0] != '\0') {
|
||||
gchar *vars = gst_structure_to_string (scenario->priv->vars);
|
||||
g_error ("Variable name: %s=%s is not a double (%s)", name, value_str,
|
||||
vars);
|
||||
g_free (vars);
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
done:
|
||||
gst_object_unref (pipeline);
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
gst_object_unref (pipeline);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Check that @list doesn't contain any non-optional actions */
|
||||
|
@ -587,20 +612,27 @@ gst_validate_action_get_clocktime (GstValidateScenario * scenario,
|
|||
{
|
||||
if (!gst_validate_utils_get_clocktime (action->structure, name, retval)) {
|
||||
gdouble val;
|
||||
gchar *error = NULL;
|
||||
const gchar *strval;
|
||||
gchar *error = NULL, *strval;
|
||||
const gchar *tmpvalue = gst_structure_get_string (action->structure, name);
|
||||
|
||||
if (!(strval = gst_structure_get_string (action->structure, name))) {
|
||||
GST_INFO_OBJECT (scenario, "Could not find %s", name);
|
||||
if (!tmpvalue) {
|
||||
GST_INFO_OBJECT (scenario, "Could not find %s (%" GST_PTR_FORMAT ")",
|
||||
name, action->structure);
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = gst_validate_utils_parse_expression (strval, _set_variable_func,
|
||||
scenario, &error);
|
||||
strval = _replace_variables_in_string (scenario, action, tmpvalue);
|
||||
if (!strval)
|
||||
return FALSE;
|
||||
|
||||
val =
|
||||
gst_validate_utils_parse_expression (strval, _set_variable_func,
|
||||
scenario, &error);
|
||||
if (error) {
|
||||
GST_WARNING ("Error while parsing %s: %s", strval, error);
|
||||
GST_WARNING ("Error while parsing %s: %s (%" GST_PTR_FORMAT ")",
|
||||
strval, error, scenario->priv->vars);
|
||||
g_free (error);
|
||||
g_free (strval);
|
||||
|
||||
return FALSE;
|
||||
} else if (val == -1.0) {
|
||||
|
@ -609,6 +641,8 @@ gst_validate_action_get_clocktime (GstValidateScenario * scenario,
|
|||
*retval = val * GST_SECOND;
|
||||
*retval = GST_ROUND_UP_4 (*retval);
|
||||
}
|
||||
gst_structure_set (action->structure, name, G_TYPE_UINT64, *retval, NULL);
|
||||
g_free (strval);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1737,9 +1771,8 @@ gst_validate_parse_next_action_playback_time (GstValidateScenario * self)
|
|||
GstValidateAction *action;
|
||||
GstValidateScenarioPrivate *priv = self->priv;
|
||||
|
||||
if (!priv->actions) {
|
||||
if (!priv->actions)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
action = (GstValidateAction *) priv->actions->data;
|
||||
if (!action->priv->needs_playback_parsing)
|
||||
|
@ -1785,7 +1818,6 @@ gst_validate_execute_action (GstValidateActionType * action_type,
|
|||
gst_object_unref (scenario);
|
||||
|
||||
if (!gst_structure_has_field (action->structure, "sub-action")) {
|
||||
|
||||
gst_structure_free (action->structure);
|
||||
action->priv->printed = FALSE;
|
||||
action->structure = gst_structure_copy (action->priv->main_structure);
|
||||
|
@ -1811,7 +1843,7 @@ _fill_action (GstValidateScenario * scenario, GstValidateAction * action,
|
|||
GstValidateActionType *action_type;
|
||||
const gchar *str_playback_time = NULL;
|
||||
GstValidateScenarioPrivate *priv = scenario ? scenario->priv : NULL;
|
||||
GstValidateExecuteActionReturn res = GST_VALIDATE_EXECUTE_ACTION_OK;
|
||||
GstValidateExecuteActionReturn res = GST_VALIDATE_EXECUTE_ACTION_NONE;
|
||||
gboolean optional, needs_parsing;
|
||||
|
||||
action->type = gst_structure_get_name (structure);
|
||||
|
@ -2075,19 +2107,6 @@ execute_next_action (GstValidateScenario * scenario)
|
|||
|
||||
type = _find_action_type (act->type);
|
||||
|
||||
if (act->repeat == -1 &&
|
||||
!gst_structure_get_int (act->structure, "repeat", &act->repeat)) {
|
||||
gchar *error = NULL;
|
||||
const gchar *repeat_expr = gst_structure_get_string (act->structure,
|
||||
"repeat");
|
||||
|
||||
if (repeat_expr) {
|
||||
act->repeat =
|
||||
gst_validate_utils_parse_expression (repeat_expr,
|
||||
_set_variable_func, scenario, &error);
|
||||
}
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (scenario, "Executing %" GST_PTR_FORMAT
|
||||
" at %" GST_TIME_FORMAT, act->structure, GST_TIME_ARGS (position));
|
||||
priv->seeked_in_pause = FALSE;
|
||||
|
@ -2867,9 +2886,8 @@ static gboolean
|
|||
_structure_set_variables (GQuark field_id, GValue * value,
|
||||
GstValidateAction * action)
|
||||
{
|
||||
gchar *str;
|
||||
GstValidateScenario *scenario;
|
||||
const gchar *var_value, *pvarname;
|
||||
gint varname_len;
|
||||
|
||||
if (!G_VALUE_HOLDS_STRING (value))
|
||||
return TRUE;
|
||||
|
@ -2878,26 +2896,14 @@ _structure_set_variables (GQuark field_id, GValue * value,
|
|||
if (!scenario)
|
||||
return TRUE;
|
||||
|
||||
pvarname = g_value_get_string (value);
|
||||
varname_len = strlen (pvarname);
|
||||
if (varname_len > 3 && pvarname[0] == '$' && pvarname[1] == '('
|
||||
&& pvarname[varname_len - 1] == ')') {
|
||||
gchar *varname = g_malloc (sizeof (gchar) * varname_len - 3);
|
||||
strncpy (varname, &pvarname[2], varname_len - 3);
|
||||
varname[varname_len - 3] = '\0';
|
||||
|
||||
var_value = gst_structure_get_string (scenario->priv->vars, varname);
|
||||
if (!var_value) {
|
||||
g_error ("Trying to use undefined variable : %s", pvarname);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (action, "Setting variable %s to %s", varname, var_value);
|
||||
g_value_set_string (value, var_value);
|
||||
str =
|
||||
_replace_variables_in_string (scenario, action,
|
||||
g_value_get_string (value));
|
||||
if (str) {
|
||||
g_value_set_string (value, str);
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
g_clear_object (&scenario);
|
||||
gst_object_unref (scenario);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -2905,31 +2911,65 @@ _structure_set_variables (GQuark field_id, GValue * value,
|
|||
static gboolean
|
||||
gst_validate_action_default_prepare_func (GstValidateAction * action)
|
||||
{
|
||||
gulong i;
|
||||
GstClockTime time;
|
||||
const gchar *vars[] = { "duration", "start", "stop" };
|
||||
gint i;
|
||||
GstClockTime tmp;
|
||||
gchar *repeat_expr;
|
||||
gchar *error = NULL;
|
||||
GstValidateActionType *type = gst_validate_get_action_type (action->type);
|
||||
GstValidateScenario *scenario = gst_validate_action_get_scenario (action);
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (vars); i++) {
|
||||
gint res = gst_validate_action_get_clocktime (scenario, action, vars[i],
|
||||
&time);
|
||||
if (res == FALSE) {
|
||||
GST_ERROR_OBJECT (scenario, "Could not get clocktime for"
|
||||
" variable %s", vars[i]);
|
||||
|
||||
gst_object_unref (scenario);
|
||||
return FALSE;
|
||||
} else if (res == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
gst_structure_set (action->structure, vars[i], GST_TYPE_CLOCK_TIME,
|
||||
time, NULL);
|
||||
}
|
||||
gst_object_unref (scenario);
|
||||
gst_structure_filter_and_map_in_place (action->structure,
|
||||
(GstStructureFilterMapFunc) _structure_set_variables, action);
|
||||
|
||||
for (i = 0; type->parameters[i].name; i++) {
|
||||
if (g_str_has_suffix (type->parameters[i].types, "(GstClockTime)"))
|
||||
gst_validate_action_get_clocktime (scenario, action,
|
||||
type->parameters[i].name, &tmp);
|
||||
}
|
||||
|
||||
if (action->repeat > 0) {
|
||||
GST_ERROR ("Repeat already set!");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!gst_structure_has_field (action->structure, "repeat"))
|
||||
return TRUE;
|
||||
|
||||
if (gst_structure_get_int (action->structure, "repeat", &action->repeat))
|
||||
return TRUE;
|
||||
|
||||
if (gst_structure_get_double (action->structure, "repeat",
|
||||
(gdouble *) & action->repeat))
|
||||
return TRUE;
|
||||
|
||||
repeat_expr =
|
||||
g_strdup (gst_structure_get_string (action->structure, "repeat"));
|
||||
if (!repeat_expr) {
|
||||
g_error ("Invalid value for 'repeat' in %s",
|
||||
gst_structure_to_string (action->structure));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
action->repeat =
|
||||
gst_validate_utils_parse_expression (repeat_expr, _set_variable_func,
|
||||
scenario, &error);
|
||||
if (error) {
|
||||
g_error ("Invalid value for 'repeat' in %s: %s",
|
||||
gst_structure_to_string (action->structure), error);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
g_free (repeat_expr);
|
||||
|
||||
gst_structure_set (action->structure, "repeat", G_TYPE_INT, action->repeat,
|
||||
NULL);
|
||||
gst_structure_set (action->priv->main_structure, "repeat", G_TYPE_INT,
|
||||
action->repeat, NULL);
|
||||
|
||||
if (scenario)
|
||||
gst_object_unref (scenario);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -3030,8 +3070,11 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
|
|||
|
||||
}
|
||||
|
||||
if (!gst_validate_parse_next_action_playback_time (scenario))
|
||||
return FALSE;
|
||||
if (scenario->priv->needs_playback_parsing) {
|
||||
scenario->priv->needs_playback_parsing = FALSE;
|
||||
if (!gst_validate_parse_next_action_playback_time (scenario))
|
||||
return FALSE;
|
||||
}
|
||||
_add_execute_actions_gsource (scenario);
|
||||
break;
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
|
@ -3145,9 +3188,9 @@ message_cb (GstBus * bus, GstMessage * message, GstValidateScenario * scenario)
|
|||
GST_DEBUG_OBJECT (scenario, "Got EOS; generate 'stop' action");
|
||||
|
||||
stop_action_type = _find_action_type ("stop");
|
||||
s = gst_structure_from_string ("stop, generated-after-eos=true;", NULL);
|
||||
stop_action = gst_validate_action_new (scenario, stop_action_type,
|
||||
gst_structure_from_string ("stop, generated-after-eos=true;", NULL),
|
||||
FALSE);
|
||||
s, FALSE);
|
||||
gst_structure_free (s);
|
||||
gst_validate_execute_action (stop_action_type, stop_action);
|
||||
gst_mini_object_unref (GST_MINI_OBJECT (stop_action));
|
||||
|
@ -3607,6 +3650,7 @@ gst_validate_scenario_init (GstValidateScenario * scenario)
|
|||
priv->segment_stop = GST_CLOCK_TIME_NONE;
|
||||
priv->action_execution_interval = 10;
|
||||
priv->vars = gst_structure_new_empty ("vars");
|
||||
priv->needs_playback_parsing = TRUE;
|
||||
g_weak_ref_init (&scenario->priv->ref_pipeline, NULL);
|
||||
priv->max_latency = GST_CLOCK_TIME_NONE;
|
||||
priv->max_dropped = -1;
|
||||
|
@ -4235,8 +4279,8 @@ _action_set_done (GstValidateAction * action)
|
|||
action->priv->state = _execute_sub_action_action (action);
|
||||
|
||||
if (action->priv->state != GST_VALIDATE_EXECUTE_ACTION_ASYNC) {
|
||||
GST_DEBUG_OBJECT (scenario, "Sub action executed ASYNC");
|
||||
|
||||
GST_DEBUG_OBJECT (scenario, "Sub action executed ASYNC");
|
||||
execute_next_action (scenario);
|
||||
}
|
||||
gst_object_unref (scenario);
|
||||
|
@ -4667,7 +4711,7 @@ init_scenarios (void)
|
|||
.name = "start",
|
||||
.description = "The starting value of the seek",
|
||||
.mandatory = TRUE,
|
||||
.types = "double or string",
|
||||
.types = "double or string (GstClockTime)",
|
||||
.possible_variables = "position: The current position in the stream\n"
|
||||
"duration: The duration of the stream",
|
||||
NULL
|
||||
|
@ -4693,7 +4737,7 @@ init_scenarios (void)
|
|||
" [none, set, end]",
|
||||
.mandatory = FALSE,
|
||||
.types = "string",
|
||||
.possible_variables = NULL,
|
||||
.possible_variables = NULL,
|
||||
.def = "set"
|
||||
},
|
||||
{
|
||||
|
@ -4705,10 +4749,14 @@ init_scenarios (void)
|
|||
.possible_variables = NULL,
|
||||
.def = "set"
|
||||
},
|
||||
{"stop", "The stop value of the seek", FALSE, "double or ",
|
||||
"position: The current position in the stream\n"
|
||||
"duration: The duration of the stream"
|
||||
"GST_CLOCK_TIME_NONE",
|
||||
{
|
||||
.name = "stop",
|
||||
.description = "The stop value of the seek",
|
||||
.mandatory = FALSE,
|
||||
.types = "double or string (GstClockTime)",
|
||||
.possible_variables = "position: The current position in the stream\n"
|
||||
"duration: The duration of the stream",
|
||||
.def ="GST_CLOCK_TIME_NONE",
|
||||
},
|
||||
{NULL}
|
||||
}),
|
||||
|
@ -4783,6 +4831,7 @@ init_scenarios (void)
|
|||
.name = "duration",
|
||||
.description = "the duration while no other action will be executed",
|
||||
.mandatory = FALSE,
|
||||
.types = "double or string (GstClockTime)",
|
||||
NULL},
|
||||
{
|
||||
.name = "target-element-name",
|
||||
|
@ -5144,6 +5193,7 @@ init_scenarios (void)
|
|||
gst_structure_set_name (plug_conf, action_typename);
|
||||
|
||||
action = gst_validate_action_new (NULL, atype, plug_conf, FALSE);
|
||||
gst_validate_action_unref (action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ typedef enum
|
|||
GST_VALIDATE_EXECUTE_ACTION_ASYNC,
|
||||
GST_VALIDATE_EXECUTE_ACTION_INTERLACED,
|
||||
GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED,
|
||||
GST_VALIDATE_EXECUTE_ACTION_IN_PROGRESS
|
||||
GST_VALIDATE_EXECUTE_ACTION_IN_PROGRESS,
|
||||
GST_VALIDATE_EXECUTE_ACTION_NONE,
|
||||
} GstValidateActionReturn;
|
||||
|
||||
/* TODO 2.0 -- Make it an actual enum type */
|
||||
|
@ -124,6 +125,8 @@ GstValidateAction * gst_validate_action_new (GstValidateScenario * sc
|
|||
GstValidateActionType * action_type,
|
||||
GstStructure *structure,
|
||||
gboolean add_to_lists);
|
||||
GST_VALIDATE_API
|
||||
void gst_validate_action_unref (GstValidateAction * action);
|
||||
|
||||
#define GST_TYPE_VALIDATE_ACTION (gst_validate_action_get_type ())
|
||||
#define GST_IS_VALIDATE_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VALIDATE_ACTION))
|
||||
|
@ -214,8 +217,11 @@ gboolean gst_validate_print_action_types (const gchar ** wanted_types, gint num_
|
|||
* @mandatory: Whether the parameter is mandatory for
|
||||
* a specific action type
|
||||
* @types: The types the parameter can take described as a
|
||||
* string. It can be precisely describing how the typing works
|
||||
* string. It can be precisely describing how the typing works
|
||||
* using '\n' between the various acceptable types.
|
||||
* NOTE: The types should end with `(GstClockTime)` if its final
|
||||
* type is a GstClockTime, this way it will be processed when preparing
|
||||
* the actions.
|
||||
* @possible_variables: The name of the variables that can be
|
||||
* used to compute the value of the parameter.
|
||||
* For example for the start value of a seek
|
||||
|
|
|
@ -3,7 +3,8 @@ validate_tests = [
|
|||
['validate/padmonitor'],
|
||||
['validate/monitoring'],
|
||||
['validate/reporting'],
|
||||
['validate/overrides']
|
||||
['validate/overrides'],
|
||||
['validate/scenario']
|
||||
]
|
||||
|
||||
test_defines = [
|
||||
|
@ -38,6 +39,7 @@ foreach t : validate_tests
|
|||
c_args : gst_c_args + test_defines,
|
||||
include_directories : [inc_dirs],
|
||||
dependencies : [validate_dep, gst_check_dep],
|
||||
link_with: gstvalidate
|
||||
)
|
||||
env.set('GST_REGISTRY',
|
||||
'@0@/@1@.registry'.format(meson.current_build_dir(), test_name))
|
||||
|
|
62
validate/tests/check/validate/scenario.c
Normal file
62
validate/tests/check/validate/scenario.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include <gst/check/gstcheck.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gst/validate/validate.h>
|
||||
|
||||
GST_START_TEST (test_expression_parser)
|
||||
{
|
||||
GstClockTime start;
|
||||
GstValidateRunner *runner = gst_validate_runner_new ();
|
||||
GstValidateActionType *set_vars = gst_validate_get_action_type ("set-vars");
|
||||
GstValidateActionType *seek_type = gst_validate_get_action_type ("seek");
|
||||
GstValidateScenario *scenario =
|
||||
g_object_new (GST_TYPE_VALIDATE_SCENARIO, "validate-runner",
|
||||
runner, NULL);
|
||||
GstValidateAction *action;
|
||||
|
||||
fail_unless (seek_type);
|
||||
|
||||
action = gst_validate_action_new (scenario, set_vars,
|
||||
gst_structure_from_string
|
||||
("set-vars, a=(string)\"50\", b=(string)\"70\", default_flags=flush",
|
||||
NULL), FALSE);
|
||||
fail_unless_equals_int (gst_validate_execute_action (set_vars, action),
|
||||
GST_VALIDATE_EXECUTE_ACTION_OK);
|
||||
gst_validate_action_unref (action);
|
||||
|
||||
action = gst_validate_action_new (scenario, seek_type,
|
||||
gst_structure_from_string
|
||||
("seek, start=\"min($(a), $(b))\", flags=\"$(default_flags)\"", NULL),
|
||||
FALSE);
|
||||
fail_unless (action);
|
||||
|
||||
fail_unless (seek_type->prepare (action));
|
||||
fail_unless (gst_validate_action_get_clocktime (scenario, action, "start",
|
||||
&start));
|
||||
fail_unless_equals_uint64 (start, 50 * GST_SECOND);
|
||||
gst_validate_action_unref (action);
|
||||
|
||||
gst_object_unref (runner);
|
||||
}
|
||||
|
||||
GST_END_TEST;
|
||||
|
||||
static Suite *
|
||||
gst_validate_suite (void)
|
||||
{
|
||||
Suite *s = suite_create ("registry");
|
||||
TCase *tc_chain = tcase_create ("registry");
|
||||
suite_add_tcase (s, tc_chain);
|
||||
|
||||
if (atexit (gst_validate_deinit) != 0) {
|
||||
GST_ERROR ("failed to set gst_validate_deinit as exit function");
|
||||
}
|
||||
|
||||
g_setenv ("GST_VALIDATE_REPORTING_DETAILS", "all", TRUE);
|
||||
gst_validate_init ();
|
||||
tcase_add_test (tc_chain, test_expression_parser);
|
||||
gst_validate_deinit ();
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
GST_CHECK_MAIN (gst_validate);
|
Loading…
Reference in a new issue