mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
scenario: Rework scenarios to be: 1- Simpler to write them, 2- extendible
Make the scenario files a list of GstStructure-s as strings
This commit is contained in:
parent
711946879e
commit
ea1f0a64f2
11 changed files with 220 additions and 681 deletions
|
@ -1,112 +1,12 @@
|
|||
<scenario name="Alternative fast forward/backward">
|
||||
<actions>
|
||||
<seek name='backward seek'
|
||||
playback_time="0.0"
|
||||
format="time"
|
||||
rate="-1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="310.0" />
|
||||
<seek name='forward seek'
|
||||
playback_time="305.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="305.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="310.0"
|
||||
format="time"
|
||||
rate="2.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="310.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="320.0"
|
||||
format="time"
|
||||
rate="-2.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="320.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="310.0"
|
||||
format="time"
|
||||
rate="4.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="310.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="330.0"
|
||||
format="time"
|
||||
rate="-4.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="330.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="310.0"
|
||||
format="time"
|
||||
rate="8.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="310.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="350.0"
|
||||
format="time"
|
||||
rate="-8.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="350.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="310.0"
|
||||
format="time"
|
||||
rate="16.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="310.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="390.0"
|
||||
format="time"
|
||||
rate="-16.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="390.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="310.0"
|
||||
format="time"
|
||||
rate="32.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="310.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="470.0"
|
||||
format="time"
|
||||
rate="-32.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="310.0"
|
||||
stop_type="set"
|
||||
stop="470.0" />
|
||||
</actions>
|
||||
</scenario>
|
||||
seek, name=backward-seek, playback_time=0.0, rate=-1.0, start=0.0, stop=310.0
|
||||
seek, name=forward-seek, playback_time=305.0, rate=1.0, start=305.0
|
||||
seek, name=Fast-forward-seek, playback_time=310.0, rate=2.0, start=310.0
|
||||
seek, name=Fast-backward-seek, playback_time=320.0, rate=-2.0, start=0.0, stop=320.0
|
||||
seek, name=Fast-forward-seek, playback_time=310.0, rate=4.0, start=310.0
|
||||
seek, name=Fast-backward-seek, playback_time=330.0, rate=-4.0, start=0.0, stop=330.0
|
||||
seek, name=Fast-forward-seek, playback_time=310.0, rate=8.0, start=310.0,
|
||||
seek, name=Fast-backward-seek, playback_time=350.0, rate=-8.0, start=0.0, stop=350.0,
|
||||
seek, name=Fast-forward-seek, playback_time=310.0, rate=16.0, start=310.0
|
||||
seek, name=Fast-backward-seek, playback_time=390.0, rate=-16.0, start=0.0, stop=390.0,
|
||||
seek, name=Fast-forward-seek, playback_time=310.0, rate=32.0, start=310.0,
|
||||
seek, name=Fast-backward-seek, playback_time=470.0, rate=-32.0, start=310.0, stop=470.0,
|
||||
|
|
|
@ -1,50 +1,5 @@
|
|||
<scenario name="Fast backward">
|
||||
<actions>
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="0.0"
|
||||
format="time"
|
||||
rate="-2.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="310.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="300.0"
|
||||
format="time"
|
||||
rate="-4.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="300.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="280.0"
|
||||
format="time"
|
||||
rate="-8.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="280.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="240.0"
|
||||
format="time"
|
||||
rate="-16.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="240.0" />
|
||||
<seek name='Fast backward seek'
|
||||
playback_time="160.0"
|
||||
format="time"
|
||||
rate="-32.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="160.0" />
|
||||
</actions>
|
||||
</scenario>
|
||||
|
||||
seek, name=Fast-backward-seek, playback_time=0.0, rate=-2.0, start=0.0, stop=310.0
|
||||
seek, name=Fast-backward-seek, playback_time=300.0, rate=-4.0, start=0.0, stop=300.0
|
||||
seek, name=Fast-backward-seek, playback_time=280.0, rate=-8.0, start=0.0, stop=280.0
|
||||
seek, name=Fast-backward-seek, playback_time=240.0, rate=-16.0, start=0.0, stop=240.0
|
||||
seek, name=Fast-backward-seek, playback_time=160.0, rate=-32.0, start=0.0, stop=160.0
|
||||
|
|
|
@ -1,49 +1,5 @@
|
|||
<scenario name="Fast forward">
|
||||
<actions>
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="0.0"
|
||||
format="time"
|
||||
rate="2.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="10.0"
|
||||
format="time"
|
||||
rate="4.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="10.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="30.0"
|
||||
format="time"
|
||||
rate="8.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="30.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="70.0"
|
||||
format="time"
|
||||
rate="16.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="70.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
<seek name='Fast forward seek'
|
||||
playback_time="150.0"
|
||||
format="time"
|
||||
rate="32.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="150.0"
|
||||
stop_type="set"
|
||||
stop="310.0" />
|
||||
</actions>
|
||||
</scenario>
|
||||
seek, name=Fast-forward-seek, playback_time=0.0, rate=2.0, start=0.0
|
||||
seek, name=Fast-forward-seek, playback_time=10.0, rate=4.0, start=10.0
|
||||
seek, name=Fast-forward-seek, playback_time=30.0, rate=8.0, start=30.0
|
||||
seek, name=Fast-forward-seek, playback_time=70.0, rate=16.0, start=70.0
|
||||
seek, name=Fast-forward-seek, playback_time=150.0, rate=32.0, start=150.0, stop=310.0
|
||||
|
|
|
@ -1,15 +1,4 @@
|
|||
<scenario name="Simple pause resume">
|
||||
<actions>
|
||||
<pause name='First pause'
|
||||
playback_time="1.0"
|
||||
duration="1.0" />
|
||||
<pause name='Second pause'
|
||||
playback_time="3.0"
|
||||
duration="5.0" />
|
||||
<pause name='Third pause'
|
||||
playback_time="5.0"
|
||||
duration="1.0" />
|
||||
<eos name='Done testing'
|
||||
playback_time="7.0" />
|
||||
</actions>
|
||||
</scenario>
|
||||
pause, name=First-pause, playback_time=1.0, duration=1.0
|
||||
pause, name=Second-pause, playback_time=3.0, duration=5.0
|
||||
pause, name=Third-pause, playback_time=5.0, duration=1.0
|
||||
eos, name=Done-testing, playback_time=7.0
|
||||
|
|
|
@ -1,34 +1,3 @@
|
|||
<scenario name="Backward Seeks">
|
||||
<actions>
|
||||
<seek name='First backward seek'
|
||||
playback_time="5.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
|
||||
<seek name='Second backward seek'
|
||||
playback_time="10.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="5.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
|
||||
<seek name='Third backward seek with stop value (1 sec)'
|
||||
playback_time="15.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="10.0"
|
||||
stop_type="set"
|
||||
stop="15.0" />
|
||||
</actions>
|
||||
</scenario>
|
||||
|
||||
seek name=Backward-seek, playback_time=5.0, rate=1.0, start=0.0
|
||||
seek name=Backward-seek, playback_time=10.0, rate=1.0, start=5.0
|
||||
seek name=Backward-seek, playback_time=15.0, rate=1.0, start=10.0, stop=15.0
|
||||
|
|
|
@ -1,33 +1,3 @@
|
|||
<scenario name="Forward Seeks">
|
||||
<actions>
|
||||
<seek name='First forward seek'
|
||||
playback_time="5.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="10.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
|
||||
<seek name='Second forward seek'
|
||||
playback_time="15.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="20.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
|
||||
<seek name='Third forward seek with stop value (1 sec)'
|
||||
playback_time="25.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="30.0"
|
||||
stop_type="set"
|
||||
stop="35.0" />
|
||||
</actions>
|
||||
</scenario>
|
||||
seek, name=First-forward-seek, playback_time=5.0, start=10.0
|
||||
seek, name=Second-forward-seek, playback_time=15.0, start=20.0
|
||||
seek, name=Third-forward-seek-with-stop-value-1-sec, playback_time=25.0, start=30.0, stop=35.0
|
||||
|
|
|
@ -1,35 +1,3 @@
|
|||
<xml>
|
||||
<scenario name="Simple Seeks">
|
||||
<actions>
|
||||
<seek name='First seek'
|
||||
playback_time="1.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="2.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
|
||||
<seek name='Second seek'
|
||||
playback_time="3.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="0.0"
|
||||
stop_type="set"
|
||||
stop="-1.0" />
|
||||
|
||||
<seek name='Third seek'
|
||||
playback_time="1.0"
|
||||
format="time"
|
||||
rate="1.0"
|
||||
flags="accurate+flush"
|
||||
start_type="set"
|
||||
start="2.0"
|
||||
stop_type="set"
|
||||
stop="3.0" />
|
||||
</actions>
|
||||
</scenario>
|
||||
</xml>
|
||||
seek, playback_time=1.0, rate=1.0, start=2.0
|
||||
seek, playback_time=3.0, rate=1.0, start=0.0
|
||||
seek, playback_time=1.0, rate=1.0, start=2.0, stop=3.0
|
||||
|
|
|
@ -26,5 +26,6 @@
|
|||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gstvalidate_debug);
|
||||
#define GST_CAT_DEFAULT gstvalidate_debug
|
||||
void init_scenarios (void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <gio/gio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gst-validate-internal.h"
|
||||
#include "gst-validate-scenario.h"
|
||||
#include "gst-validate-reporter.h"
|
||||
#include "gst-validate-report.h"
|
||||
|
@ -48,57 +49,13 @@ enum
|
|||
PROP_LAST
|
||||
};
|
||||
|
||||
static GHashTable *action_types_table;
|
||||
static void gst_validate_scenario_dispose (GObject * object);
|
||||
static void gst_validate_scenario_finalize (GObject * object);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstValidateScenario, gst_validate_scenario,
|
||||
G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GST_TYPE_VALIDATE_REPORTER, NULL));
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SCENARIO_ACTION_UNKNOWN = 0,
|
||||
SCENARIO_ACTION_SEEK,
|
||||
SCENARIO_ACTION_PAUSE,
|
||||
SCENARIO_ACTION_EOS,
|
||||
} ScenarioActionType;
|
||||
|
||||
typedef struct _ScenarioAction
|
||||
{
|
||||
ScenarioActionType type;
|
||||
gchar *name;
|
||||
GstClockTime playback_time;
|
||||
guint action_number; /* The sequential number on which the action should
|
||||
be executed */
|
||||
} ScenarioAction;
|
||||
|
||||
#define SCENARIO_ACTION(act) ((ScenarioAction *)act)
|
||||
|
||||
typedef struct _SeekInfo
|
||||
{
|
||||
ScenarioAction action;
|
||||
|
||||
gdouble rate;
|
||||
GstFormat format;
|
||||
GstSeekFlags flags;
|
||||
GstSeekType start_type;
|
||||
GstClockTime start;
|
||||
GstSeekType stop_type;
|
||||
GstClockTime stop;
|
||||
|
||||
} SeekInfo;
|
||||
|
||||
typedef struct _PauseInfo
|
||||
{
|
||||
ScenarioAction action;
|
||||
|
||||
GstClockTime duration;
|
||||
} PauseInfo;
|
||||
|
||||
typedef struct _EosInfo
|
||||
{
|
||||
ScenarioAction action;
|
||||
} EosInfo;
|
||||
|
||||
struct _GstValidateScenarioPrivate
|
||||
{
|
||||
GstElement *pipeline;
|
||||
|
@ -110,31 +67,9 @@ struct _GstValidateScenarioPrivate
|
|||
|
||||
guint num_actions;
|
||||
|
||||
/* markup parser context */
|
||||
gboolean in_scenario;
|
||||
gboolean in_actions;
|
||||
|
||||
guint get_pos_id;
|
||||
};
|
||||
|
||||
static GstClockTime
|
||||
str_to_gst_time (const gchar * str)
|
||||
{
|
||||
gchar *end_of_valid_d;
|
||||
gdouble double_value = 0;
|
||||
|
||||
double_value = g_ascii_strtod (str, &end_of_valid_d);
|
||||
|
||||
if (*end_of_valid_d != '\0' || end_of_valid_d == str) {
|
||||
GST_ERROR ("%s could not be converted to GstClockTime", str);
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
}
|
||||
|
||||
if (double_value < 0)
|
||||
return GST_CLOCK_TIME_NONE;
|
||||
|
||||
return double_value * GST_SECOND;
|
||||
}
|
||||
|
||||
/* Some helper method that are missing iin Json itscenario */
|
||||
static guint
|
||||
|
@ -171,244 +106,66 @@ get_enum_from_string (GType type, const gchar * str_enum, guint * enum_value)
|
|||
}
|
||||
|
||||
static void
|
||||
_scenario_action_init (ScenarioAction * act)
|
||||
_free_scenario_action (GstValidateAction * act)
|
||||
{
|
||||
act->name = NULL;
|
||||
act->playback_time = GST_CLOCK_TIME_NONE;
|
||||
act->type = SCENARIO_ACTION_UNKNOWN;
|
||||
if (act->structure)
|
||||
gst_structure_free (act->structure);
|
||||
|
||||
g_slice_free (GstValidateAction, act);
|
||||
}
|
||||
|
||||
static SeekInfo *
|
||||
_new_seek_info (void)
|
||||
{
|
||||
SeekInfo *info = g_slice_new0 (SeekInfo);
|
||||
|
||||
_scenario_action_init (&info->action);
|
||||
info->action.type = SCENARIO_ACTION_SEEK;
|
||||
info->rate = 1.0;
|
||||
info->format = GST_FORMAT_TIME;
|
||||
info->start_type = GST_SEEK_TYPE_SET;
|
||||
info->stop_type = GST_SEEK_TYPE_SET;
|
||||
info->flags = GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH;
|
||||
info->start = 0;
|
||||
info->stop = GST_CLOCK_TIME_NONE;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static PauseInfo *
|
||||
_new_pause_info (void)
|
||||
{
|
||||
PauseInfo *pause = g_slice_new0 (PauseInfo);
|
||||
|
||||
_scenario_action_init (SCENARIO_ACTION (pause));
|
||||
pause->action.type = SCENARIO_ACTION_PAUSE;
|
||||
pause->duration = 0;
|
||||
|
||||
return pause;
|
||||
}
|
||||
|
||||
static EosInfo *
|
||||
_new_eos_info (void)
|
||||
{
|
||||
EosInfo *eos = g_slice_new0 (EosInfo);
|
||||
|
||||
_scenario_action_init (SCENARIO_ACTION (eos));
|
||||
eos->action.type = SCENARIO_ACTION_EOS;
|
||||
|
||||
return eos;
|
||||
}
|
||||
|
||||
static void
|
||||
_scenario_action_clear (ScenarioAction * act)
|
||||
{
|
||||
g_free (act->name);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_seek_info (SeekInfo * info)
|
||||
{
|
||||
_scenario_action_clear (SCENARIO_ACTION (info));
|
||||
g_slice_free (SeekInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_pause_info (PauseInfo * info)
|
||||
{
|
||||
_scenario_action_clear (SCENARIO_ACTION (info));
|
||||
g_slice_free (PauseInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_eos_info (EosInfo * info)
|
||||
{
|
||||
_scenario_action_clear (SCENARIO_ACTION (info));
|
||||
g_slice_free (EosInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
_free_scenario_action (ScenarioAction * act)
|
||||
{
|
||||
switch (act->type) {
|
||||
case SCENARIO_ACTION_SEEK:
|
||||
_free_seek_info ((SeekInfo *) act);
|
||||
break;
|
||||
case SCENARIO_ACTION_PAUSE:
|
||||
_free_pause_info ((PauseInfo *) act);
|
||||
break;
|
||||
case SCENARIO_ACTION_EOS:
|
||||
_free_eos_info ((EosInfo *) act);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
_scenario_action_clear (act);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_parse_seek (GMarkupParseContext * context, const gchar * element_name,
|
||||
const gchar ** attribute_names, const gchar ** attribute_values,
|
||||
GstValidateScenario * scenario, GError ** error)
|
||||
static gboolean
|
||||
_execute_seek (GstValidateScenario * scenario, GstValidateAction * action)
|
||||
{
|
||||
GstValidateScenarioPrivate *priv = scenario->priv;
|
||||
const char *format, *rate, *flags, *start_type, *start, *stop_type, *stop;
|
||||
const char *playback_time = NULL;
|
||||
const char *str_format, *str_flags, *str_start_type, *str_stop_type;
|
||||
|
||||
SeekInfo *info = _new_seek_info ();
|
||||
gdouble rate = 1.0, dstart, dstop;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
GstSeekFlags flags = GST_SEEK_FLAG_ACCURATE | GST_SEEK_FLAG_FLUSH;
|
||||
GstSeekType start_type = GST_SEEK_TYPE_SET;
|
||||
GstClockTime start;
|
||||
GstSeekType stop_type = GST_SEEK_TYPE_SET;
|
||||
GstClockTime stop = GST_CLOCK_TIME_NONE;
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, attribute_names,
|
||||
attribute_values, error,
|
||||
G_MARKUP_COLLECT_STRDUP | G_MARKUP_COLLECT_OPTIONAL, "name",
|
||||
&info->action.name,
|
||||
G_MARKUP_COLLECT_STRING, "playback_time",
|
||||
&playback_time,
|
||||
G_MARKUP_COLLECT_STRING, "format", &format,
|
||||
G_MARKUP_COLLECT_STRING, "rate", &rate,
|
||||
G_MARKUP_COLLECT_STRING, "flags", &flags,
|
||||
G_MARKUP_COLLECT_STRING, "start_type", &start_type,
|
||||
G_MARKUP_COLLECT_STRING, "start", &start,
|
||||
G_MARKUP_COLLECT_STRING, "stop_type", &stop_type,
|
||||
G_MARKUP_COLLECT_STRING, "stop", &stop, G_MARKUP_COLLECT_INVALID))
|
||||
return;
|
||||
if (!gst_structure_get_double (action->structure, "start", &dstart)) {
|
||||
GST_WARNING_OBJECT (scenario, "Could not find start for a seek, FAILED");
|
||||
return FALSE;
|
||||
}
|
||||
start = dstart * GST_SECOND;
|
||||
|
||||
get_enum_from_string (GST_TYPE_FORMAT, format, &info->format);
|
||||
gst_structure_get_double (action->structure, "rate", &rate);
|
||||
if ((str_format = gst_structure_get_string (action->structure, "format")))
|
||||
get_enum_from_string (GST_TYPE_FORMAT, str_format, &format);
|
||||
|
||||
if (playback_time)
|
||||
info->action.playback_time = str_to_gst_time (playback_time);
|
||||
info->rate = g_ascii_strtod (rate, NULL);
|
||||
info->flags = get_flags_from_string (GST_TYPE_SEEK_FLAGS, flags);
|
||||
get_enum_from_string (GST_TYPE_SEEK_TYPE, start_type, &info->start_type);
|
||||
info->start = str_to_gst_time (start);
|
||||
get_enum_from_string (GST_TYPE_SEEK_TYPE, stop_type, &info->stop_type);
|
||||
info->stop = str_to_gst_time (stop);
|
||||
info->action.action_number = priv->num_actions++;
|
||||
if ((str_start_type =
|
||||
gst_structure_get_string (action->structure, "start_type")))
|
||||
get_enum_from_string (GST_TYPE_SEEK_TYPE, str_start_type, &start_type);
|
||||
|
||||
priv->actions = g_list_append (priv->actions, info);
|
||||
}
|
||||
if ((str_stop_type =
|
||||
gst_structure_get_string (action->structure, "stop_type")))
|
||||
get_enum_from_string (GST_TYPE_SEEK_TYPE, str_stop_type, &stop_type);
|
||||
|
||||
static inline void
|
||||
_parse_pause (GMarkupParseContext * context, const gchar * element_name,
|
||||
const gchar ** attribute_names, const gchar ** attribute_values,
|
||||
GstValidateScenario * scenario, GError ** error)
|
||||
{
|
||||
GstValidateScenarioPrivate *priv = scenario->priv;
|
||||
const char *duration = NULL;
|
||||
const char *playback_time = NULL;
|
||||
if ((str_flags = gst_structure_get_string (action->structure, "flags")))
|
||||
flags = get_flags_from_string (GST_TYPE_SEEK_FLAGS, str_flags);
|
||||
|
||||
PauseInfo *info = _new_pause_info ();
|
||||
if (gst_structure_get_double (action->structure, "stop", &dstop))
|
||||
stop = dstop * GST_SECOND;
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, attribute_names,
|
||||
attribute_values, error,
|
||||
G_MARKUP_COLLECT_STRDUP | G_MARKUP_COLLECT_OPTIONAL, "name",
|
||||
&info->action.name, G_MARKUP_COLLECT_STRING, "playback_time",
|
||||
&playback_time, G_MARKUP_COLLECT_STRING, "duration", &duration,
|
||||
G_MARKUP_COLLECT_INVALID))
|
||||
return;
|
||||
g_print ("%s (num %u), seeking to: %" GST_TIME_FORMAT " stop: %"
|
||||
GST_TIME_FORMAT " Rate %lf\n", action->name,
|
||||
action->action_number, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), rate);
|
||||
|
||||
if (playback_time)
|
||||
info->action.playback_time = str_to_gst_time (playback_time);
|
||||
info->duration = str_to_gst_time (duration);
|
||||
|
||||
info->action.action_number = priv->num_actions++;
|
||||
|
||||
priv->actions = g_list_append (priv->actions, info);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_parse_eos (GMarkupParseContext * context, const gchar * element_name,
|
||||
const gchar ** attribute_names, const gchar ** attribute_values,
|
||||
GstValidateScenario * scenario, GError ** error)
|
||||
{
|
||||
GstValidateScenarioPrivate *priv = scenario->priv;
|
||||
const char *playback_time = NULL;
|
||||
|
||||
EosInfo *info = _new_eos_info ();
|
||||
|
||||
if (!g_markup_collect_attributes (element_name, attribute_names,
|
||||
attribute_values, error,
|
||||
G_MARKUP_COLLECT_STRDUP | G_MARKUP_COLLECT_OPTIONAL, "name",
|
||||
&info->action.name, G_MARKUP_COLLECT_STRING, "playback_time",
|
||||
&playback_time, G_MARKUP_COLLECT_INVALID))
|
||||
return;
|
||||
|
||||
if (playback_time)
|
||||
info->action.playback_time = str_to_gst_time (playback_time);
|
||||
|
||||
info->action.action_number = priv->num_actions++;
|
||||
|
||||
priv->actions = g_list_append (priv->actions, info);
|
||||
}
|
||||
|
||||
static void
|
||||
_parse_element_start (GMarkupParseContext * context, const gchar * element_name,
|
||||
const gchar ** attribute_names, const gchar ** attribute_values,
|
||||
gpointer udata, GError ** error)
|
||||
{
|
||||
GstValidateScenario *scenario = udata;
|
||||
GstValidateScenarioPrivate *priv =
|
||||
GST_VALIDATE_SCENARIO_GET_PRIVATE (scenario);
|
||||
|
||||
if (strcmp (element_name, "scenario") == 0) {
|
||||
priv->in_scenario = TRUE;
|
||||
return;
|
||||
priv->seeked_position = (rate > 0) ? start : stop;
|
||||
if (gst_element_seek (priv->pipeline, rate, format, flags, start_type, start,
|
||||
stop_type, stop) == FALSE) {
|
||||
GST_VALIDATE_REPORT (scenario, EVENT_SEEK_NOT_HANDLED,
|
||||
"Could not seek to position %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (priv->seeked_position));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (priv->in_scenario) {
|
||||
if (strcmp (element_name, "actions") == 0) {
|
||||
priv->in_actions = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->in_actions) {
|
||||
if (g_strcmp0 (element_name, "seek") == 0) {
|
||||
_parse_seek (context, element_name, attribute_names,
|
||||
attribute_values, scenario, error);
|
||||
} else if (g_strcmp0 (element_name, "pause") == 0) {
|
||||
_parse_pause (context, element_name, attribute_names,
|
||||
attribute_values, scenario, error);
|
||||
} else if (g_strcmp0 (element_name, "eos") == 0) {
|
||||
_parse_eos (context, element_name, attribute_names,
|
||||
attribute_values, scenario, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
_parse_element_end (GMarkupParseContext * context, const gchar * element_name,
|
||||
gpointer udata, GError ** error)
|
||||
{
|
||||
GstValidateScenario *scenario = udata;
|
||||
GstValidateScenarioPrivate *priv =
|
||||
GST_VALIDATE_SCENARIO_GET_PRIVATE (scenario);
|
||||
|
||||
if (strcmp (element_name, "actions") == 0) {
|
||||
priv->in_actions = FALSE;
|
||||
} else if (strcmp (element_name, "scenario") == 0) {
|
||||
priv->in_scenario = FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -425,57 +182,77 @@ _pause_action_restore_playing (GstValidateScenario * scenario)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_execute_action (GstValidateScenario * scenario, ScenarioAction * act)
|
||||
|
||||
static gboolean
|
||||
_execute_pause (GstValidateScenario * scenario, GstValidateAction * action)
|
||||
{
|
||||
gdouble duration = 0;
|
||||
|
||||
GstValidateScenarioPrivate *priv = scenario->priv;
|
||||
GstElement *pipeline = scenario->priv->pipeline;
|
||||
|
||||
if (act->type == SCENARIO_ACTION_SEEK) {
|
||||
SeekInfo *seek = (SeekInfo *) act;
|
||||
g_print ("%s (num %u), seeking to: %" GST_TIME_FORMAT " stop: %"
|
||||
GST_TIME_FORMAT " Rate %lf\n", SCENARIO_ACTION (seek)->name,
|
||||
SCENARIO_ACTION (seek)->action_number, GST_TIME_ARGS (seek->start),
|
||||
GST_TIME_ARGS (seek->stop), seek->rate);
|
||||
gst_structure_get_double (action->structure, "duration", &duration);
|
||||
g_print ("\n%s (num %u), pausing for %" GST_TIME_FORMAT "\n",
|
||||
action->name, action->action_number,
|
||||
GST_TIME_ARGS (duration * GST_SECOND));
|
||||
|
||||
priv->seeked_position = (seek->rate > 0) ? seek->start : seek->stop;
|
||||
if (gst_element_seek (pipeline, seek->rate,
|
||||
seek->format, seek->flags,
|
||||
seek->start_type, seek->start,
|
||||
seek->stop_type, seek->stop) == FALSE) {
|
||||
GST_VALIDATE_REPORT (scenario, EVENT_SEEK_NOT_HANDLED,
|
||||
"Could not seek to position %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (priv->seeked_position));
|
||||
}
|
||||
GST_DEBUG ("Pausing for %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (duration * GST_SECOND));
|
||||
|
||||
} else if (act->type == SCENARIO_ACTION_PAUSE) {
|
||||
PauseInfo *pause = (PauseInfo *) act;
|
||||
if (gst_element_set_state (priv->pipeline, GST_STATE_PAUSED) ==
|
||||
GST_STATE_CHANGE_FAILURE) {
|
||||
GST_VALIDATE_REPORT (scenario, STATE_CHANGE_FAILURE,
|
||||
"Failed to set state to paused");
|
||||
|
||||
GST_DEBUG ("Pausing for %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (pause->duration));
|
||||
|
||||
if (gst_element_set_state (pipeline, GST_STATE_PAUSED) ==
|
||||
GST_STATE_CHANGE_FAILURE) {
|
||||
GST_VALIDATE_REPORT (scenario, STATE_CHANGE_FAILURE,
|
||||
"Failed to set state to paused");
|
||||
}
|
||||
gst_element_get_state (pipeline, NULL, NULL, -1);
|
||||
g_timeout_add (pause->duration / GST_MSECOND,
|
||||
(GSourceFunc) _pause_action_restore_playing, scenario);
|
||||
} else if (act->type == SCENARIO_ACTION_EOS) {
|
||||
GST_DEBUG ("Sending eos to pipeline at %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (act->playback_time));
|
||||
gst_element_send_event (priv->pipeline, gst_event_new_eos ());
|
||||
return FALSE;
|
||||
}
|
||||
gst_element_get_state (priv->pipeline, NULL, NULL, -1);
|
||||
if (duration)
|
||||
g_timeout_add (duration * 1000,
|
||||
(GSourceFunc) _pause_action_restore_playing, scenario);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_execute_play (GstValidateScenario * scenario, GstValidateAction * action)
|
||||
{
|
||||
g_print ("\n%s (num %u), Playing back", action->name, action->action_number);
|
||||
|
||||
GST_DEBUG ("Playing back");
|
||||
|
||||
if (gst_element_set_state (scenario->priv->pipeline, GST_STATE_PLAYING) ==
|
||||
GST_STATE_CHANGE_FAILURE) {
|
||||
GST_VALIDATE_REPORT (scenario, STATE_CHANGE_FAILURE,
|
||||
"Failed to set state to playing");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
gst_element_get_state (scenario->priv->pipeline, NULL, NULL, -1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_execute_eos (GstValidateScenario * scenario, GstValidateAction * action)
|
||||
{
|
||||
g_print ("\n%s (num %u), sending EOS at %" GST_TIME_FORMAT "\n",
|
||||
action->name, action->action_number,
|
||||
GST_TIME_ARGS (action->playback_time));
|
||||
|
||||
GST_DEBUG ("Sending eos to pipeline at %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (action->playback_time));
|
||||
|
||||
return gst_element_send_event (scenario->priv->pipeline,
|
||||
gst_event_new_eos ());
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
get_position (GstValidateScenario * scenario)
|
||||
{
|
||||
GList *tmp;
|
||||
GstQuery *query;
|
||||
gdouble rate = 1.0;
|
||||
ScenarioAction *act;
|
||||
GstValidateAction *act;
|
||||
gint64 position, duration;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
GstValidateScenarioPrivate *priv = scenario->priv;
|
||||
|
@ -511,14 +288,15 @@ get_position (GstValidateScenario * scenario)
|
|||
GST_LOG ("Current position: %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
|
||||
if ((rate > 0 && (GstClockTime) position >= act->playback_time) ||
|
||||
(rate < 0 && (GstClockTime) position <= act->playback_time)) {
|
||||
GstValidateExecuteAction func;
|
||||
|
||||
/* TODO what about non flushing seeks? */
|
||||
/* TODO why is this inside the action time if ? */
|
||||
if (GST_CLOCK_TIME_IS_VALID (priv->seeked_position))
|
||||
GST_VALIDATE_REPORT (scenario, EVENT_SEEK_NOT_HANDLED,
|
||||
"Previous seek to %" GST_TIME_FORMAT " was not handled",
|
||||
GST_TIME_ARGS (priv->seeked_position));
|
||||
return TRUE;
|
||||
|
||||
_execute_action (scenario, act);
|
||||
func = g_hash_table_lookup (action_types_table, act->type);
|
||||
func (scenario, act);
|
||||
|
||||
tmp = priv->actions;
|
||||
priv->actions = g_list_remove_link (priv->actions, tmp);
|
||||
|
@ -568,14 +346,13 @@ static gboolean
|
|||
_load_scenario_file (GstValidateScenario * scenario,
|
||||
const gchar * scenario_file)
|
||||
{
|
||||
guint i;
|
||||
gsize xmlsize;
|
||||
GFile *file = NULL;
|
||||
GError *err = NULL;
|
||||
gboolean ret = TRUE;
|
||||
gchar *xmlcontent = NULL;
|
||||
GMarkupParseContext *parsecontext = NULL;
|
||||
GstValidateScenarioClass *self_class =
|
||||
GST_VALIDATE_SCENARIO_GET_CLASS (scenario);
|
||||
gchar *content = NULL, **lines = NULL;
|
||||
GstValidateScenarioPrivate *priv = scenario->priv;
|
||||
gchar *uri = gst_filename_to_uri (scenario_file, &err);
|
||||
|
||||
if (uri == NULL)
|
||||
|
@ -586,31 +363,55 @@ _load_scenario_file (GstValidateScenario * scenario,
|
|||
goto wrong_uri;
|
||||
|
||||
/* TODO Handle GCancellable */
|
||||
if (!g_file_load_contents (file, NULL, &xmlcontent, &xmlsize, NULL, &err))
|
||||
if (!g_file_load_contents (file, NULL, &content, &xmlsize, NULL, &err))
|
||||
goto failed;
|
||||
|
||||
if (g_strcmp0 (xmlcontent, "") == 0)
|
||||
if (g_strcmp0 (content, "") == 0)
|
||||
goto failed;
|
||||
|
||||
parsecontext = g_markup_parse_context_new (&self_class->content_parser,
|
||||
G_MARKUP_TREAT_CDATA_AS_TEXT, scenario, NULL);
|
||||
lines = g_strsplit (content, "\n", 0);
|
||||
for (i = 0; lines[i]; i++) {
|
||||
const gchar *type;
|
||||
gdouble playback_time;
|
||||
GstValidateAction *action;
|
||||
GstStructure *structure;
|
||||
|
||||
if (g_markup_parse_context_parse (parsecontext, xmlcontent, xmlsize,
|
||||
&err) == FALSE)
|
||||
goto failed;
|
||||
if (g_strcmp0 (lines[i], "") == 0)
|
||||
continue;
|
||||
|
||||
structure = gst_structure_from_string (lines[i], NULL);
|
||||
if (structure == NULL) {
|
||||
GST_WARNING_OBJECT (scenario, "Could not parse action %s", lines[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
type = gst_structure_get_name (structure);
|
||||
if (!g_hash_table_lookup (action_types_table, type)) {
|
||||
GST_WARNING_OBJECT (scenario, "We do not handle action types %s", type);
|
||||
}
|
||||
|
||||
action = g_slice_new0 (GstValidateAction);
|
||||
action->type = type;
|
||||
if (gst_structure_get_double (structure, "playback_time", &playback_time))
|
||||
action->playback_time = playback_time * GST_SECOND;
|
||||
else
|
||||
GST_WARNING_OBJECT (scenario, "No playback time for action %s", lines[i]);
|
||||
|
||||
if (!(action->name = gst_structure_get_string (structure, "name")))
|
||||
action->name = "";
|
||||
|
||||
action->action_number = priv->num_actions++;
|
||||
action->structure = structure;
|
||||
priv->actions = g_list_append (priv->actions, action);
|
||||
}
|
||||
|
||||
done:
|
||||
if (xmlcontent)
|
||||
g_free (xmlcontent);
|
||||
if (content)
|
||||
g_free (content);
|
||||
|
||||
if (file)
|
||||
gst_object_unref (file);
|
||||
|
||||
if (parsecontext) {
|
||||
g_markup_parse_context_free (parsecontext);
|
||||
parsecontext = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
wrong_uri:
|
||||
|
@ -652,6 +453,7 @@ gst_validate_scenario_load (GstValidateScenario * scenario,
|
|||
g_build_filename (g_get_user_data_dir (), "gstreamer-" GST_API_VERSION,
|
||||
GST_VALIDATE_SCENARIO_DIRECTORY, lfilename, NULL);
|
||||
|
||||
|
||||
if (!(ret = _load_scenario_file (scenario, tldir))) {
|
||||
g_free (tldir);
|
||||
/* Try from system-wide profiles */
|
||||
|
@ -733,9 +535,6 @@ gst_validate_scenario_class_init (GstValidateScenarioClass * klass)
|
|||
"The Validate runner to " "report errors to",
|
||||
GST_TYPE_VALIDATE_RUNNER,
|
||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
|
||||
|
||||
klass->content_parser.start_element = _parse_element_start;
|
||||
klass->content_parser.end_element = _parse_element_end;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -854,3 +653,21 @@ gst_validate_list_scenarios (void)
|
|||
g_object_unref (dir);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
gst_validate_add_action_type (const gchar *type_name, GstValidateExecuteAction function)
|
||||
{
|
||||
g_hash_table_insert (action_types_table, g_strdup (type_name), function);
|
||||
}
|
||||
|
||||
void
|
||||
init_scenarios (void)
|
||||
{
|
||||
action_types_table = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free, NULL);
|
||||
|
||||
gst_validate_add_action_type ("seek", _execute_seek);
|
||||
gst_validate_add_action_type ("pause",_execute_pause);
|
||||
gst_validate_add_action_type ("play",_execute_play);
|
||||
gst_validate_add_action_type ("eos",_execute_eos);
|
||||
}
|
||||
|
|
|
@ -39,13 +39,22 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstValidateScenario GstValidateScenario;
|
||||
typedef struct _GstValidateScenarioClass GstValidateScenarioClass;
|
||||
typedef struct _GstValidateScenarioPrivate GstValidateScenarioPrivate;
|
||||
typedef struct _GstValidateAction GstValidateAction;
|
||||
|
||||
typedef gboolean (*GstValidateExecuteAction) (GstValidateScenario * scenario, GstValidateAction * action);
|
||||
|
||||
typedef struct _GstValidateAction
|
||||
{
|
||||
const gchar *type;
|
||||
const gchar *name;
|
||||
guint action_number;
|
||||
GstClockTime playback_time;
|
||||
GstStructure *structure;
|
||||
} GstValidateAction;
|
||||
|
||||
struct _GstValidateScenarioClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
GMarkupParser content_parser;
|
||||
};
|
||||
|
||||
struct _GstValidateScenario
|
||||
|
@ -60,7 +69,9 @@ GType gst_validate_scenario_get_type (void);
|
|||
GstValidateScenario * gst_validate_scenario_factory_create (GstValidateRunner *runner,
|
||||
GstElement *pipeline,
|
||||
const gchar *scenario_name);
|
||||
void gst_validate_list_scenarios (void);
|
||||
void gst_validate_list_scenarios (void);
|
||||
void gst_validate_add_action_type (const gchar *type_name,
|
||||
GstValidateExecuteAction function);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ gst_validate_init (void)
|
|||
/* init the report system (can be called multiple times) */
|
||||
gst_validate_report_init ();
|
||||
|
||||
/* Init the scenario system */
|
||||
init_scenarios ();
|
||||
|
||||
/* Ensure we load overrides before any use of a monitor */
|
||||
gst_validate_override_registry_preload ();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue