qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) 2013 Thibault Saunier <thibault.saunier@collabora.com>
|
|
|
|
*
|
|
|
|
* gst-qa-scenario.c - QA Scenario class
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <gst/gst.h>
|
|
|
|
#include <gio/gio.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
#include "gst-qa-scenario.h"
|
|
|
|
#include "gst-qa-reporter.h"
|
|
|
|
#include "gst-qa-report.h"
|
|
|
|
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
#define GST_QA_SCENARIO_GET_PRIVATE(o) \
|
|
|
|
(G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_QA_SCENARIO, GstQaScenarioPrivate))
|
|
|
|
|
|
|
|
#define GST_QA_SCENARIO_SUFFIX ".xml"
|
|
|
|
#define GST_QA_SCERNARIO_DIRECTORY "qa-scenario"
|
|
|
|
|
|
|
|
GST_DEBUG_CATEGORY_STATIC (gst_qa_scenario);
|
|
|
|
#define GST_CAT_DEFAULT gst_qa_scenario
|
|
|
|
|
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
#define DEFAULT_SEEK_TOLERANCE (0.1 * GST_SECOND) /* tolerance seek interval
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
TODO make it overridable */
|
2013-07-22 23:22:49 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
PROP_RUNNER,
|
|
|
|
PROP_LAST
|
|
|
|
};
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
|
|
|
|
static void gst_qa_scenario_class_init (GstQaScenarioClass * klass);
|
|
|
|
static void gst_qa_scenario_init (GstQaScenario * scenario);
|
|
|
|
static void gst_qa_scenario_dispose (GObject * object);
|
|
|
|
static void gst_qa_scenario_finalize (GObject * object);
|
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (GstQaScenario, gst_qa_scenario, G_TYPE_OBJECT,
|
|
|
|
G_IMPLEMENT_INTERFACE (GST_TYPE_QA_REPORTER, NULL));
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
|
|
|
|
typedef struct _SeekInfo
|
|
|
|
{
|
|
|
|
gchar *name;
|
|
|
|
GstClockTime seeking_time;
|
|
|
|
gdouble rate;
|
|
|
|
GstFormat format;
|
|
|
|
GstSeekFlags flags;
|
|
|
|
GstSeekType start_type;
|
|
|
|
GstClockTime start;
|
|
|
|
GstSeekType stop_type;
|
|
|
|
GstClockTime stop;
|
|
|
|
|
|
|
|
} SeekInfo;
|
|
|
|
|
|
|
|
struct _GstQaScenarioPrivate
|
|
|
|
{
|
|
|
|
GstElement *pipeline;
|
2013-07-22 23:22:49 +00:00
|
|
|
GstQaRunner *runner;
|
|
|
|
|
|
|
|
GList *seeks;
|
|
|
|
gint64 seeked_position; /* last seeked position */
|
|
|
|
GstClockTime seek_pos_tol;
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Some helper method that are missing iin Json itscenario */
|
|
|
|
static guint
|
|
|
|
get_flags_from_string (GType type, const gchar * str_flags)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
gint flags = 0;
|
|
|
|
GFlagsClass *class = g_type_class_ref (type);
|
|
|
|
|
|
|
|
for (i = 0; i < class->n_values; i++) {
|
|
|
|
if (g_strrstr (str_flags, class->values[i].value_nick)) {
|
|
|
|
flags |= class->values[i].value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_type_class_unref (class);
|
|
|
|
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
get_enum_from_string (GType type, const gchar * str_enum, guint * enum_value)
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
GEnumClass *class = g_type_class_ref (type);
|
|
|
|
|
|
|
|
for (i = 0; i < class->n_values; i++) {
|
|
|
|
if (g_strrstr (str_enum, class->values[i].value_nick)) {
|
|
|
|
*enum_value = class->values[i].value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_type_class_unref (class);
|
|
|
|
}
|
|
|
|
|
|
|
|
static SeekInfo *
|
|
|
|
_new_seek_info (void)
|
|
|
|
{
|
|
|
|
SeekInfo *info = g_slice_new (SeekInfo);
|
|
|
|
|
|
|
|
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->seeking_time = GST_SECOND;
|
|
|
|
info->start = 0;
|
|
|
|
info->stop = GST_CLOCK_TIME_NONE;
|
|
|
|
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_free_seek_info (SeekInfo * info)
|
|
|
|
{
|
|
|
|
g_slice_free (SeekInfo, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void
|
|
|
|
_parse_seek (GMarkupParseContext * context, const gchar * element_name,
|
|
|
|
const gchar ** attribute_names, const gchar ** attribute_values,
|
|
|
|
GstQaScenario * scenario, GError ** error)
|
|
|
|
{
|
|
|
|
GstQaScenarioPrivate *priv = scenario->priv;
|
|
|
|
const char *seeking_time, *format, *rate, *flags, *start_type, *start,
|
|
|
|
*stop_type, *stop;
|
|
|
|
|
|
|
|
SeekInfo *info = _new_seek_info ();
|
|
|
|
|
|
|
|
if (!g_markup_collect_attributes (element_name, attribute_names,
|
|
|
|
attribute_values, error,
|
|
|
|
G_MARKUP_COLLECT_STRDUP, "name", &info->name,
|
|
|
|
G_MARKUP_COLLECT_STRING, "seeking_time", &seeking_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;
|
|
|
|
|
|
|
|
get_enum_from_string (GST_TYPE_FORMAT, format, &info->format);
|
|
|
|
|
|
|
|
info->rate = g_ascii_strtoull (rate, NULL, 10);
|
|
|
|
info->flags = get_flags_from_string (GST_TYPE_SEEK_FLAGS, flags);
|
|
|
|
info->seeking_time = g_ascii_strtoull (seeking_time, NULL, 10);
|
|
|
|
get_enum_from_string (GST_TYPE_SEEK_TYPE, start_type, &info->start_type);
|
|
|
|
info->start = g_ascii_strtoull (start, NULL, 10);
|
|
|
|
get_enum_from_string (GST_TYPE_SEEK_TYPE, stop_type, &info->stop_type);
|
|
|
|
info->stop = g_ascii_strtoull (stop, NULL, 10);
|
|
|
|
|
|
|
|
priv->seeks = g_list_append (priv->seeks, info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_parse_element_start (GMarkupParseContext * context, const gchar * element_name,
|
|
|
|
const gchar ** attribute_names, const gchar ** attribute_values,
|
|
|
|
gpointer scenario, GError ** error)
|
|
|
|
{
|
|
|
|
if (g_strcmp0 (element_name, "seek") == 0) {
|
|
|
|
_parse_seek (context, element_name, attribute_names,
|
|
|
|
attribute_values, scenario, error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
get_position (GstQaScenario * scenario)
|
|
|
|
{
|
|
|
|
GList *tmp;
|
|
|
|
gint64 position;
|
|
|
|
GstFormat format = GST_FORMAT_TIME;
|
|
|
|
GstQaScenarioPrivate *priv = scenario->priv;
|
|
|
|
GstElement *pipeline = scenario->priv->pipeline;
|
|
|
|
|
|
|
|
gst_element_query_position (pipeline, &format, &position);
|
|
|
|
|
|
|
|
tmp = scenario->priv->seeks;
|
|
|
|
GST_DEBUG ("Current position: %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
|
|
|
|
while (tmp) {
|
|
|
|
SeekInfo *seek = tmp->data;
|
2013-07-22 23:22:49 +00:00
|
|
|
|
|
|
|
if ((position >= (seek->seeking_time - priv->seek_pos_tol))
|
|
|
|
&& (position <= (seek->seeking_time + priv->seek_pos_tol))) {
|
|
|
|
|
|
|
|
if (GST_CLOCK_TIME_IS_VALID (priv->seeked_position))
|
|
|
|
GST_QA_REPORT_ISSUE (scenario, TRUE, SEEK, TIMING,
|
|
|
|
"Previous seek to %" GST_TIME_FORMAT " was not handled",
|
|
|
|
GST_TIME_ARGS (priv->seeked_position));
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
|
|
|
|
GST_LOG ("seeking to: %" GST_TIME_FORMAT " stop: %" GST_TIME_FORMAT,
|
|
|
|
GST_TIME_ARGS (seek->start), GST_TIME_ARGS (seek->stop));
|
|
|
|
|
|
|
|
if (gst_element_seek (pipeline, seek->rate,
|
|
|
|
seek->format, seek->flags,
|
|
|
|
seek->start_type, seek->start,
|
2013-07-22 23:22:49 +00:00
|
|
|
seek->stop_type, seek->stop) == FALSE) {
|
|
|
|
GST_QA_REPORT_ISSUE (scenario, TRUE, SEEK, UNKNOWN,
|
|
|
|
"Could not seek to position %" GST_TIME_FORMAT,
|
|
|
|
GST_TIME_ARGS (priv->seeked_position));
|
|
|
|
}
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
priv->seeked_position = seek->start;
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
priv->seeks = g_list_remove_link (priv->seeks, tmp);
|
|
|
|
g_slice_free (SeekInfo, seek);
|
|
|
|
g_list_free (tmp);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
tmp = tmp->next;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
static gboolean
|
|
|
|
async_done_cb (GstBus * bus, GstMessage * message, GstQaScenario * scenario)
|
|
|
|
{
|
|
|
|
GstQaScenarioPrivate *priv = scenario->priv;
|
|
|
|
|
|
|
|
if (GST_CLOCK_TIME_IS_VALID (priv->seeked_position)) {
|
|
|
|
gint64 position;
|
|
|
|
GstFormat format = GST_FORMAT_TIME;
|
|
|
|
|
|
|
|
gst_element_query_position (priv->pipeline, &format, &position);
|
|
|
|
if (position > (priv->seeked_position + priv->seek_pos_tol) ||
|
|
|
|
position < (MAX (0,
|
|
|
|
((gint64) (priv->seeked_position - priv->seek_pos_tol))))) {
|
|
|
|
|
|
|
|
GST_QA_REPORT_ISSUE (scenario, TRUE, SEEK, TIMING,
|
|
|
|
"Seeked position %" GST_TIME_FORMAT
|
|
|
|
"not in the expected range [%" GST_TIME_FORMAT " -- %"
|
|
|
|
GST_TIME_FORMAT, GST_TIME_ARGS (position),
|
|
|
|
GST_TIME_ARGS (((MAX (0,
|
|
|
|
((gint64) (priv->seeked_position -
|
|
|
|
priv->seek_pos_tol)))))),
|
|
|
|
GST_TIME_ARGS ((priv->seeked_position + priv->seek_pos_tol)));
|
|
|
|
}
|
|
|
|
priv->seeked_position = GST_CLOCK_TIME_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
static gboolean
|
|
|
|
_load_scenario_file (GstQaScenario * scenario, const gchar * scenario_file)
|
|
|
|
{
|
|
|
|
gsize xmlsize;
|
|
|
|
GFile *file = NULL;
|
|
|
|
GError *err = NULL;
|
|
|
|
gboolean ret = TRUE;
|
|
|
|
gchar *xmlcontent = NULL;
|
|
|
|
GMarkupParseContext *parsecontext = NULL;
|
|
|
|
GstQaScenarioClass *self_class = GST_QA_SCENARIO_GET_CLASS (scenario);
|
|
|
|
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 */
|
|
|
|
if (!g_file_load_contents (file, NULL, &xmlcontent, &xmlsize, NULL, &err))
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
if (g_strcmp0 (xmlcontent, "") == 0)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
parsecontext = g_markup_parse_context_new (&self_class->content_parser,
|
|
|
|
G_MARKUP_TREAT_CDATA_AS_TEXT, scenario, NULL);
|
|
|
|
|
|
|
|
if (g_markup_parse_context_parse (parsecontext, xmlcontent, xmlsize,
|
|
|
|
&err) == FALSE)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (xmlcontent)
|
|
|
|
g_free (xmlcontent);
|
|
|
|
|
|
|
|
if (file)
|
|
|
|
gst_object_unref (file);
|
|
|
|
|
|
|
|
if (parsecontext) {
|
|
|
|
g_markup_parse_context_free (parsecontext);
|
|
|
|
parsecontext = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
wrong_uri:
|
|
|
|
GST_WARNING ("%s wrong uri", scenario_file);
|
|
|
|
|
|
|
|
ret = FALSE;
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
failed:
|
|
|
|
ret = FALSE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
gst_qa_scenario_load (GstQaScenario * scenario, const gchar * scenario_name)
|
|
|
|
{
|
|
|
|
gboolean ret = TRUE;
|
|
|
|
gchar *lfilename = NULL, *tldir = NULL;
|
|
|
|
|
|
|
|
if (!scenario_name)
|
|
|
|
goto invalid_name;
|
|
|
|
|
|
|
|
lfilename = g_strdup_printf ("%s" GST_QA_SCENARIO_SUFFIX, scenario_name);
|
|
|
|
|
|
|
|
/* Try from local profiles */
|
|
|
|
tldir =
|
|
|
|
g_build_filename (g_get_user_data_dir (), "gstreamer-" GST_API_VERSION,
|
|
|
|
GST_QA_SCERNARIO_DIRECTORY, lfilename, NULL);
|
|
|
|
|
|
|
|
if (!(ret = _load_scenario_file (scenario, tldir))) {
|
|
|
|
g_free (tldir);
|
|
|
|
/* Try from system-wide profiles */
|
|
|
|
tldir = g_build_filename (GST_DATADIR, "gstreamer-" GST_API_VERSION,
|
|
|
|
GST_QA_SCERNARIO_DIRECTORY, lfilename, NULL);
|
|
|
|
ret = _load_scenario_file (scenario, tldir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Hack to make it work uninstalled */
|
|
|
|
if (ret == FALSE) {
|
|
|
|
g_free (tldir);
|
|
|
|
|
|
|
|
tldir = g_build_filename ("data/", lfilename, NULL);
|
|
|
|
ret = _load_scenario_file (scenario, tldir);
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (tldir)
|
|
|
|
g_free (tldir);
|
|
|
|
if (lfilename)
|
|
|
|
g_free (lfilename);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
invalid_name:
|
|
|
|
{
|
2013-07-22 23:22:49 +00:00
|
|
|
GST_ERROR ("Invalid name for scenario '%s'", scenario_name);
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
ret = FALSE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
gst_qa_scenario_set_property (GObject * object, guint prop_id,
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
|
|
|
{
|
|
|
|
GstQaScenarioPrivate *priv = GST_QA_SCENARIO (object)->priv;
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
case PROP_RUNNER:
|
|
|
|
/* we assume the runner is valid as long as this scenario is,
|
|
|
|
* no ref taken */
|
|
|
|
priv->runner = g_value_get_object (value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_qa_scenario_get_property (GObject * object, guint prop_id,
|
|
|
|
GValue * value, GParamSpec * pspec)
|
|
|
|
{
|
|
|
|
GstQaScenarioPrivate *priv = GST_QA_SCENARIO (object)->priv;
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
case PROP_RUNNER:
|
|
|
|
/* we assume the runner is valid as long as this scenario is,
|
|
|
|
* no ref taken */
|
|
|
|
g_value_set_object (value, priv->runner);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
static void
|
|
|
|
gst_qa_scenario_class_init (GstQaScenarioClass * klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_qa_scenario, "gstqascenario",
|
|
|
|
GST_DEBUG_FG_MAGENTA, "gst qa scenario");
|
|
|
|
|
|
|
|
g_type_class_add_private (klass, sizeof (GstQaScenarioPrivate));
|
|
|
|
|
|
|
|
object_class->dispose = gst_qa_scenario_dispose;
|
|
|
|
object_class->finalize = gst_qa_scenario_finalize;
|
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
object_class->get_property = gst_qa_scenario_get_property;
|
|
|
|
object_class->set_property = gst_qa_scenario_set_property;
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_RUNNER,
|
|
|
|
g_param_spec_object ("qa-runner", "QA Runner", "The QA runner to "
|
|
|
|
"report errors to", GST_TYPE_QA_RUNNER,
|
|
|
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
|
|
|
|
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
klass->content_parser.start_element = _parse_element_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_qa_scenario_init (GstQaScenario * scenario)
|
|
|
|
{
|
2013-07-22 23:22:49 +00:00
|
|
|
GstQaScenarioPrivate *priv = scenario->priv =
|
|
|
|
GST_QA_SCENARIO_GET_PRIVATE (scenario);
|
|
|
|
|
|
|
|
|
|
|
|
priv->seeked_position = GST_CLOCK_TIME_NONE;
|
|
|
|
priv->seek_pos_tol = DEFAULT_SEEK_TOLERANCE;
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_qa_scenario_dispose (GObject * object)
|
|
|
|
{
|
|
|
|
GstQaScenarioPrivate *priv = GST_QA_SCENARIO (object)->priv;
|
|
|
|
|
|
|
|
gst_object_unref (priv->pipeline);
|
|
|
|
g_list_free_full (priv->seeks, (GDestroyNotify) _free_seek_info);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (gst_qa_scenario_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_qa_scenario_finalize (GObject * object)
|
|
|
|
{
|
|
|
|
G_OBJECT_CLASS (gst_qa_scenario_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
GstQaScenario *
|
2013-07-22 23:22:49 +00:00
|
|
|
gst_qa_scenario_factory_create (GstQaRunner * runner,
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
const gchar * scenario_name)
|
|
|
|
{
|
2013-07-22 23:22:49 +00:00
|
|
|
GstBus *bus;
|
|
|
|
GstQaScenario *scenario = g_object_new (GST_TYPE_QA_SCENARIO, "qa-runner",
|
|
|
|
runner, NULL);
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
|
|
|
|
GST_LOG ("Creating scenario %s", scenario_name);
|
|
|
|
if (!gst_qa_scenario_load (scenario, scenario_name)) {
|
|
|
|
g_object_unref (scenario);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-07-22 23:22:49 +00:00
|
|
|
scenario->priv->pipeline = gst_object_ref (runner->pipeline);
|
|
|
|
gst_qa_reporter_set_name (GST_QA_REPORTER (scenario),
|
|
|
|
g_strdup (scenario_name));
|
|
|
|
|
|
|
|
bus = gst_element_get_bus (runner->pipeline);
|
|
|
|
gst_bus_add_signal_watch (bus);
|
|
|
|
g_signal_connect (bus, "message::async-done", (GCallback) async_done_cb,
|
|
|
|
scenario);
|
|
|
|
gst_object_unref (bus);
|
|
|
|
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
g_timeout_add (50, (GSourceFunc) get_position, scenario);
|
|
|
|
|
|
|
|
g_print ("\n=========================================\n"
|
|
|
|
"Running scenario %s on pipeline %s"
|
|
|
|
"\n=========================================\n", scenario_name,
|
2013-07-22 23:22:49 +00:00
|
|
|
GST_OBJECT_NAME (runner->pipeline));
|
qa: Add a GstQaScenario class making it possible to execute scenarios
A scenario correspond to a suite of action to execute on a pipeline,
for the time being, we only support seeking the pipeline, but in the
future we can imagine doing some queries, setting pipeline state, etc...
The scenario can be loaded thanks to the GST_QA_SCENARIO environment
variable, making it usable with any existant application, in case, the
application can be used interactively, the user should either, not load
any scenario or let the application run without interacting with it.
2013-07-20 04:18:13 +00:00
|
|
|
|
|
|
|
return scenario;
|
|
|
|
}
|