validate: Add a way to add a "description" to scenario files

Print details about the descriptions when listing scenario in a KeyFile
format

The description can contain any information about the scenario such as its duration before
EOS, how long the pipeline needs to be so the scenario can be applied...etc
This commit is contained in:
Thibault Saunier 2014-02-11 23:05:00 +01:00
parent efc6938d01
commit 9e66ac00f6
3 changed files with 194 additions and 66 deletions

View file

@ -53,6 +53,7 @@ enum
static GHashTable *action_types_table; static GHashTable *action_types_table;
static void gst_validate_scenario_dispose (GObject * object); static void gst_validate_scenario_dispose (GObject * object);
static void gst_validate_scenario_finalize (GObject * object); static void gst_validate_scenario_finalize (GObject * object);
static GRegex *clean_action_str;
G_DEFINE_TYPE_WITH_CODE (GstValidateScenario, gst_validate_scenario, G_DEFINE_TYPE_WITH_CODE (GstValidateScenario, gst_validate_scenario,
G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GST_TYPE_VALIDATE_REPORTER, NULL)); G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (GST_TYPE_VALIDATE_REPORTER, NULL));
@ -81,11 +82,15 @@ struct _GstValidateScenarioPrivate
GstClockTime seek_pos_tol; GstClockTime seek_pos_tol;
guint num_actions; guint num_actions;
GRegex *clean_action_str;
guint get_pos_id; guint get_pos_id;
}; };
typedef struct KeyFileGroupName
{
GKeyFile *kf;
gchar *group_name;
} KeyFileGroupName;
static guint static guint
get_flags_from_string (GType type, const gchar * str_flags) get_flags_from_string (GType type, const gchar * str_flags)
@ -537,7 +542,6 @@ _set_rank (GstValidateScenario * scenario, GstValidateAction * action)
} }
gst_plugin_feature_set_rank (feature, rank); gst_plugin_feature_set_rank (feature, rank);
GST_ERROR ("Setting %s rank to %i", feature_name, rank);
gst_object_unref (feature); gst_object_unref (feature);
return TRUE; return TRUE;
@ -614,7 +618,6 @@ get_position (GstValidateScenario * scenario)
if (repeat_expr) { if (repeat_expr) {
act->repeat = parse_expression (repeat_expr, _set_variable_func, act->repeat = parse_expression (repeat_expr, _set_variable_func,
scenario, &error); scenario, &error);
g_print ("REPEAT %i", act->repeat);
} }
} }
@ -742,58 +745,159 @@ _pipeline_freed_cb (GstValidateScenario * scenario,
GST_DEBUG_OBJECT (scenario, "pipeline was freed"); GST_DEBUG_OBJECT (scenario, "pipeline was freed");
} }
static gboolean static gchar **
_load_scenario_file (GstValidateScenario * scenario, _scenario_file_get_lines (GFile *file)
const gchar * scenario_file, gboolean * is_config)
{ {
guint i; gsize size;
gsize xmlsize;
GFile *file = NULL;
GError *err = NULL; GError *err = NULL;
gboolean ret = TRUE; gchar *content = NULL, *escaped_content = NULL, **lines = NULL;
gchar *content = NULL, *escaped_content, **lines = NULL;
GstValidateScenarioPrivate *priv = scenario->priv;
gchar *uri = gst_filename_to_uri (scenario_file, &err);
if (uri == NULL)
goto failed;
GST_DEBUG ("Trying to load %s", scenario_file);
if ((file = g_file_new_for_path (scenario_file)) == NULL)
goto wrong_uri;
/* TODO Handle GCancellable */ /* TODO Handle GCancellable */
if (!g_file_load_contents (file, NULL, &content, &xmlsize, NULL, &err)) if (!g_file_load_contents (file, NULL, &content, &size, NULL, &err))
goto failed; goto failed;
if (g_strcmp0 (content, "") == 0) if (g_strcmp0 (content, "") == 0)
goto failed; goto failed;
*is_config = FALSE; escaped_content = g_regex_replace (clean_action_str, content, -1, 0, "", 0,
escaped_content = g_regex_replace (priv->clean_action_str, NULL);
content, -1, 0, "", 0, NULL); g_free (content);
lines = g_strsplit (escaped_content, "\n", 0); lines = g_strsplit (escaped_content, "\n", 0);
g_free (escaped_content); g_free (escaped_content);
done:
return lines;
failed:
if (err) {
GST_WARNING ("Failed to load contents: %d %s", err->code, err->message);
g_error_free (err);
}
if (content)
g_free (content);
content = NULL;
if (escaped_content)
g_free (escaped_content);
escaped_content = NULL;
if (lines)
g_strfreev (lines);
lines = NULL;
goto done;
}
static gchar **
_scenario_get_lines (const gchar *scenario_file)
{
GFile *file = NULL;
gchar **lines = NULL;
GST_DEBUG ("Trying to load %s", scenario_file);
if ((file = g_file_new_for_path (scenario_file)) == NULL) {
GST_WARNING ("%s wrong uri", scenario_file);
return NULL;
}
lines = _scenario_file_get_lines (file);
g_object_unref (file);
return lines;
}
static GList *
_scenario_lines_get_strutures (gchar **lines)
{
gint i;
GList *structures = NULL;
for (i = 0; lines[i]; i++) { for (i = 0; lines[i]; i++) {
const gchar *type, *str_playback_time;
gdouble playback_time;
GstValidateAction *action;
GstStructure *structure; GstStructure *structure;
GstValidateActionType *action_type;
if (g_strcmp0 (lines[i], "") == 0) if (g_strcmp0 (lines[i], "") == 0)
continue; continue;
structure = gst_structure_from_string (lines[i], NULL); structure = gst_structure_from_string (lines[i], NULL);
if (structure == NULL) { if (structure == NULL) {
GST_ERROR_OBJECT (scenario, "Could not parse action %s", lines[i]); GST_ERROR ("Could not parse action %s", lines[i]);
goto failed; goto failed;
} }
type = gst_structure_get_name (structure); structures = g_list_append (structures, structure);
if (!g_strcmp0 (type, "scenario")) { }
gst_structure_get_boolean (structure, "is-config", is_config);
done:
if (lines)
g_strfreev (lines);
return structures;
failed:
if (structures)
g_list_free_full (structures, (GDestroyNotify) gst_structure_free);
structures = NULL;
goto done;
}
static GList*
_scenario_get_structures (const gchar *scenario_file)
{
gchar **lines;
lines = _scenario_get_lines (scenario_file);
if (lines == NULL)
return NULL;
return _scenario_lines_get_strutures (lines);
}
static GList*
_scenario_file_get_structures (GFile *scenario_file)
{
gchar **lines;
lines = _scenario_file_get_lines (scenario_file);
if (lines == NULL)
return NULL;
return _scenario_lines_get_strutures (lines);
}
static gboolean
_load_scenario_file (GstValidateScenario * scenario,
const gchar * scenario_file, gboolean * is_config)
{
gboolean ret = TRUE;
GList *structures, *tmp;
GstValidateScenarioPrivate *priv = scenario->priv;
*is_config = FALSE;
structures = _scenario_get_structures (scenario_file);
if (structures == NULL)
goto failed;
for (tmp = structures; tmp; tmp = tmp->next) {
gdouble playback_time;
GstValidateAction *action;
GstValidateActionType *action_type;
const gchar *type, *str_playback_time;
GstStructure *structure = tmp->data;
type = gst_structure_get_name (structure);
if (!g_strcmp0 (type, "description")) {
gst_structure_get_boolean (structure, "is-config", is_config);
continue; continue;
} else if (!(action_type = g_hash_table_lookup (action_types_table, type))) { } else if (!(action_type = g_hash_table_lookup (action_types_table, type))) {
GST_ERROR_OBJECT (scenario, "We do not handle action types %s", type); GST_ERROR_OBJECT (scenario, "We do not handle action types %s", type);
@ -809,7 +913,8 @@ _load_scenario_file (GstValidateScenario * scenario,
gst_structure_get_string (structure, "playback_time"))) { gst_structure_get_string (structure, "playback_time"))) {
priv->needs_parsing = g_list_append (priv->needs_parsing, action); priv->needs_parsing = g_list_append (priv->needs_parsing, action);
} else } else
GST_WARNING_OBJECT (scenario, "No playback time for action %s", lines[i]); GST_WARNING_OBJECT (scenario, "No playback time for action %" GST_PTR_FORMAT,
structure);
if (!(action->name = gst_structure_get_string (structure, "name"))) if (!(action->name = gst_structure_get_string (structure, "name")))
action->name = ""; action->name = "";
@ -830,26 +935,17 @@ _load_scenario_file (GstValidateScenario * scenario,
} }
done: done:
if (content) if (structures)
g_free (content); g_list_free (structures);
if (file)
gst_object_unref (file);
return ret; return ret;
wrong_uri:
GST_WARNING ("%s wrong uri", scenario_file);
ret = FALSE;
goto done;
failed: failed:
ret = FALSE; ret = FALSE;
if (err) { if (structures)
GST_WARNING ("Failed to load contents: %d %s", err->code, err->message); g_list_free_full (structures, (GDestroyNotify) gst_structure_free);
g_error_free (err); structures = NULL;
}
goto done; goto done;
} }
@ -868,9 +964,9 @@ gst_validate_scenario_load (GstValidateScenario * scenario,
scenarios = g_strsplit (scenario_name, ":", -1); scenarios = g_strsplit (scenario_name, ":", -1);
for (i=0; scenarios[i]; i++) { for (i = 0; scenarios[i]; i++) {
lfilename = lfilename =
g_strdup_printf ("%s" GST_VALIDATE_SCENARIO_SUFFIX, scenarios[i]); g_strdup_printf ("%s" GST_VALIDATE_SCENARIO_SUFFIX, scenarios[i]);
tldir = g_build_filename ("data/", lfilename, NULL); tldir = g_build_filename ("data/", lfilename, NULL);
@ -901,9 +997,9 @@ gst_validate_scenario_load (GstValidateScenario * scenario,
if (!(ret = _load_scenario_file (scenario, tldir, &is_config))) { if (!(ret = _load_scenario_file (scenario, tldir, &is_config))) {
goto invalid_name; goto invalid_name;
} }
} /* else check scenario */ }
/* else check scenario */
check_scenario: check_scenario:
if (tldir) if (tldir)
g_free (tldir); g_free (tldir);
if (lfilename) if (lfilename)
@ -1004,8 +1100,6 @@ 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;
priv->clean_action_str =
g_regex_new ("\\\\\n| ", G_REGEX_CASELESS, 0, NULL);
} }
static void static void
@ -1018,7 +1112,6 @@ gst_validate_scenario_dispose (GObject * object)
if (priv->pipeline) if (priv->pipeline)
gst_object_unref (priv->pipeline); gst_object_unref (priv->pipeline);
g_list_free_full (priv->actions, (GDestroyNotify) _free_scenario_action); g_list_free_full (priv->actions, (GDestroyNotify) _free_scenario_action);
g_regex_unref (priv->clean_action_str);
G_OBJECT_CLASS (gst_validate_scenario_parent_class)->dispose (object); G_OBJECT_CLASS (gst_validate_scenario_parent_class)->dispose (object);
} }
@ -1064,8 +1157,18 @@ gst_validate_scenario_factory_create (GstValidateRunner * runner,
return scenario; return scenario;
} }
static gboolean
_add_description (GQuark field_id, const GValue *value, KeyFileGroupName *kfg)
{
g_key_file_set_string (kfg->kf, kfg->group_name, g_quark_to_string (field_id),
gst_value_serialize (value));
return TRUE;
}
static void static void
_list_scenarios_in_dir (GFile * dir) _list_scenarios_in_dir (GFile * dir, GKeyFile *kf)
{ {
GFileEnumerator *fenum; GFileEnumerator *fenum;
GFileInfo *info; GFileInfo *info;
@ -1079,12 +1182,34 @@ _list_scenarios_in_dir (GFile * dir)
for (info = g_file_enumerator_next_file (fenum, NULL, NULL); for (info = g_file_enumerator_next_file (fenum, NULL, NULL);
info; info = g_file_enumerator_next_file (fenum, NULL, NULL)) { info; info = g_file_enumerator_next_file (fenum, NULL, NULL)) {
if (g_str_has_suffix (g_file_info_get_name (info), if (g_str_has_suffix (g_file_info_get_name (info),
GST_VALIDATE_SCENARIO_SUFFIX)) { GST_VALIDATE_SCENARIO_SUFFIX)) {
gchar **name = g_strsplit (g_file_info_get_name (info), gchar **name = g_strsplit (g_file_info_get_name (info),
GST_VALIDATE_SCENARIO_SUFFIX, 0); GST_VALIDATE_SCENARIO_SUFFIX, 0);
g_print ("Scenario %s \n", name[0]);
GstStructure *desc = NULL;
GFile *f = g_file_enumerator_get_child (fenum, info);
GList *tmp, *structures = _scenario_file_get_structures (f);
gst_object_unref (f);
for (tmp = structures; tmp; tmp=tmp->next) {
if (gst_structure_has_name(tmp->data, "description")) {
desc = tmp->data;
break;
}
}
if (desc) {
KeyFileGroupName kfg;
kfg.group_name = name[0];
kfg.kf = kf;
gst_structure_foreach (desc, (GstStructureForeachFunc) _add_description, &kfg);
} else {
g_key_file_set_string (kf, name[0], "noinfo", "nothing");
}
g_list_free_full (structures, (GDestroyNotify) gst_structure_free);
g_strfreev (name); g_strfreev (name);
} }
} }
@ -1093,36 +1218,37 @@ _list_scenarios_in_dir (GFile * dir)
void void
gst_validate_list_scenarios (void) gst_validate_list_scenarios (void)
{ {
GKeyFile *kf = NULL;
const gchar *env_scenariodir = g_getenv ("GST_VALIDATE_SCENARIOS_PATH"); const gchar *env_scenariodir = g_getenv ("GST_VALIDATE_SCENARIOS_PATH");
gchar *tldir = g_build_filename (g_get_user_data_dir (), gchar *tldir = g_build_filename (g_get_user_data_dir (),
"gstreamer-" GST_API_VERSION, GST_VALIDATE_SCENARIO_DIRECTORY, "gstreamer-" GST_API_VERSION, GST_VALIDATE_SCENARIO_DIRECTORY,
NULL); NULL);
GFile *dir = g_file_new_for_path (tldir); GFile *dir = g_file_new_for_path (tldir);
g_print ("====================\n" kf = g_key_file_new ();
"Avalaible scenarios:\n" "====================\n"); _list_scenarios_in_dir (dir, kf);
_list_scenarios_in_dir (dir);
g_object_unref (dir); g_object_unref (dir);
g_free (tldir); g_free (tldir);
tldir = g_build_filename (GST_DATADIR, "gstreamer-" GST_API_VERSION, tldir = g_build_filename (GST_DATADIR, "gstreamer-" GST_API_VERSION,
GST_VALIDATE_SCENARIO_DIRECTORY, NULL); GST_VALIDATE_SCENARIO_DIRECTORY, NULL);
dir = g_file_new_for_path (tldir); dir = g_file_new_for_path (tldir);
_list_scenarios_in_dir (dir); _list_scenarios_in_dir (dir, kf);
g_object_unref (dir); g_object_unref (dir);
g_free (tldir); g_free (tldir);
if (env_scenariodir) { if (env_scenariodir) {
dir = g_file_new_for_path (env_scenariodir); dir = g_file_new_for_path (env_scenariodir);
_list_scenarios_in_dir (dir); _list_scenarios_in_dir (dir, kf);
g_object_unref (dir); g_object_unref (dir);
} }
/* Hack to make it work uninstalled */ /* Hack to make it work uninstalled */
dir = g_file_new_for_path ("data/"); dir = g_file_new_for_path ("data/");
_list_scenarios_in_dir (dir); _list_scenarios_in_dir (dir, kf);
g_object_unref (dir); g_object_unref (dir);
g_print ("Full file:\n%s", g_key_file_to_data (kf, NULL, NULL));
} }
static void static void
@ -1161,6 +1287,8 @@ init_scenarios (void)
{ {
const gchar *seek_mandatory_fields[] = { "start", NULL }; const gchar *seek_mandatory_fields[] = { "start", NULL };
clean_action_str =
g_regex_new ("\\\\\n", G_REGEX_CASELESS, 0, NULL);
gst_validate_add_action_type ("seek", _execute_seek, seek_mandatory_fields, gst_validate_add_action_type ("seek", _execute_seek, seek_mandatory_fields,
"Allows to seek into the files", FALSE); "Allows to seek into the files", FALSE);
gst_validate_add_action_type ("pause", _execute_pause, NULL, gst_validate_add_action_type ("pause", _execute_pause, NULL,

View file

@ -56,6 +56,7 @@ struct _GstValidateAction
struct _GstValidateScenarioClass struct _GstValidateScenarioClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
}; };
struct _GstValidateScenario struct _GstValidateScenario

View file

@ -235,7 +235,6 @@ main (int argc, gchar ** argv)
if (list_scenarios) { if (list_scenarios) {
gst_validate_list_scenarios (); gst_validate_list_scenarios ();
return 0; return 0;
} }