validate-scenario: track position query results closer

Always keep probing the pipeline for the current position and compare
with the latest requested seek segment to detect if the seek boundaries
are being respected
This commit is contained in:
Thiago Santos 2013-09-13 12:09:30 -03:00
parent b4a711c568
commit e3e463c0cc
3 changed files with 74 additions and 41 deletions

View file

@ -204,6 +204,9 @@ gst_validate_report_load_issues (void)
REGISTER_VALIDATE_ISSUE (WARNING, QUERY_POSITION_SUPERIOR_DURATION,
_("Query position reported a value superior than what query duration "
"returned"), NULL);
REGISTER_VALIDATE_ISSUE (WARNING, QUERY_POSITION_OUT_OF_SEGMENT,
_("Query position reported a value outside of the current expected "
"segment"), NULL);
}
void

View file

@ -107,6 +107,7 @@ typedef enum {
#define GST_VALIDATE_ISSUE_ID_MISSING_PLUGIN (((GstValidateIssueId) GST_VALIDATE_AREA_RUN_ERROR) << GST_VALIDATE_ISSUE_ID_SHIFT | 2)
#define GST_VALIDATE_ISSUE_ID_QUERY_POSITION_SUPERIOR_DURATION (((GstValidateIssueId) GST_VALIDATE_AREA_QUERY) << GST_VALIDATE_ISSUE_ID_SHIFT | 1)
#define GST_VALIDATE_ISSUE_ID_QUERY_POSITION_OUT_OF_SEGMENT (((GstValidateIssueId) GST_VALIDATE_AREA_QUERY) << GST_VALIDATE_ISSUE_ID_SHIFT | 2)
#define GST_VALIDATE_ISSUE_ID_AREA(id) ((guintptr)(id >> GST_VALIDATE_ISSUE_ID_SHIFT))

View file

@ -69,7 +69,10 @@ struct _GstValidateScenarioPrivate
GstValidateRunner *runner;
GList *actions;
gint64 seeked_position; /* last seeked position */
GstEvent *last_seek;
GstClockTime segment_start;
GstClockTime segment_stop;
GstClockTime seek_pos_tol;
guint num_actions;
@ -126,6 +129,7 @@ _execute_seek (GstValidateScenario * scenario, GstValidateAction * action)
{
GstValidateScenarioPrivate *priv = scenario->priv;
const char *str_format, *str_flags, *str_start_type, *str_stop_type;
gboolean ret = TRUE;
gdouble rate = 1.0, dstart, dstop;
GstFormat format = GST_FORMAT_TIME;
@ -134,6 +138,7 @@ _execute_seek (GstValidateScenario * scenario, GstValidateAction * action)
GstClockTime start;
GstSeekType stop_type = GST_SEEK_TYPE_SET;
GstClockTime stop = GST_CLOCK_TIME_NONE;
GstEvent *seek;
if (!gst_structure_get_double (action->structure, "start", &dstart)) {
GST_WARNING_OBJECT (scenario, "Could not find start for a seek, FAILED");
@ -170,16 +175,19 @@ _execute_seek (GstValidateScenario * scenario, GstValidateAction * action)
GST_TIME_FORMAT " Rate %lf\n", action->name,
action->action_number, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), rate);
priv->seeked_position = (rate > 0) ? start : stop;
if (gst_element_seek (priv->pipeline, rate, format, flags, start_type, start,
stop_type, stop) == FALSE) {
seek = gst_event_new_seek (rate, format, flags, start_type, start,
stop_type, stop);
gst_event_ref (seek);
if (gst_element_send_event (priv->pipeline, seek)) {
gst_event_replace (&priv->last_seek, seek);
} else {
GST_VALIDATE_REPORT (scenario, EVENT_SEEK_NOT_HANDLED,
"Could not seek to position %" GST_TIME_FORMAT,
GST_TIME_ARGS (priv->seeked_position));
return FALSE;
"Could not seek to position %" GST_TIME_FORMAT, GST_TIME_ARGS (start));
ret = FALSE;
}
gst_event_unref (seek);
return TRUE;
return ret;
}
static gboolean
@ -439,24 +447,20 @@ get_position (GstValidateScenario * scenario)
GList *tmp;
GstQuery *query;
gdouble rate = 1.0;
GstValidateAction *act;
GstValidateAction *act = NULL;
gint64 start_with_tolerance, stop_with_tolerance;
gint64 position, duration;
GstFormat format = GST_FORMAT_TIME;
GstValidateScenarioPrivate *priv = scenario->priv;
GstElement *pipeline = scenario->priv->pipeline;
if (scenario->priv->actions == NULL) {
GST_DEBUG_OBJECT (scenario,
"No more actions to execute, stop calling get_position");
return FALSE;
}
query = gst_query_new_segment (GST_FORMAT_DEFAULT);
if (gst_element_query (GST_ELEMENT (priv->pipeline), query))
gst_query_parse_segment (query, &rate, NULL, NULL, NULL);
gst_query_unref (query);
act = scenario->priv->actions->data;
if (scenario->priv->actions)
act = scenario->priv->actions->data;
gst_element_query_position (pipeline, format, &position);
format = GST_FORMAT_TIME;
@ -471,15 +475,30 @@ get_position (GstValidateScenario * scenario)
return TRUE;
}
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)) {
/* Check if playback is within seek segment */
start_with_tolerance =
MAX (0, (gint64) (priv->segment_start - priv->seek_pos_tol));
stop_with_tolerance =
priv->segment_stop != -1 ? priv->segment_stop + priv->seek_pos_tol : -1;
if ((stop_with_tolerance != -1 && position > stop_with_tolerance)
|| position < start_with_tolerance) {
GST_VALIDATE_REPORT (scenario, QUERY_POSITION_OUT_OF_SEGMENT,
"Current position %" GST_TIME_FORMAT " not in the expected range [%"
GST_TIME_FORMAT " -- %" GST_TIME_FORMAT, GST_TIME_ARGS (position),
GST_TIME_ARGS (start_with_tolerance),
GST_TIME_ARGS (stop_with_tolerance));
}
if (act && ((rate > 0 && (GstClockTime) position >= act->playback_time) ||
(rate < 0 && (GstClockTime) position <= act->playback_time))) {
GstValidateActionType *type;
/* TODO what about non flushing seeks? */
/* TODO why is this inside the action time if ? */
if (GST_CLOCK_TIME_IS_VALID (priv->seeked_position))
if (priv->last_seek)
return TRUE;
type = g_hash_table_lookup (action_types_table, act->type);
@ -496,30 +515,39 @@ get_position (GstValidateScenario * scenario)
return TRUE;
}
static void
gst_validate_scenario_update_segment_from_seek (GstValidateScenario * scenario,
GstEvent * seek)
{
GstValidateScenarioPrivate *priv = scenario->priv;
gint64 start, stop;
GstSeekType start_type, stop_type;
gst_event_parse_seek (seek, NULL, NULL, NULL, &start_type, &start,
&stop_type, &stop);
if (start_type == GST_SEEK_TYPE_SET) {
priv->segment_start = start;
} else if (start_type == GST_SEEK_TYPE_END) {
/* TODO fill me */
}
if (stop_type == GST_SEEK_TYPE_SET) {
priv->segment_stop = stop;
} else if (start_type == GST_SEEK_TYPE_END) {
/* TODO fill me */
}
}
static gboolean
async_done_cb (GstBus * bus, GstMessage * message,
GstValidateScenario * scenario)
{
GstValidateScenarioPrivate *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_VALIDATE_REPORT (scenario, EVENT_SEEK_RESULT_POSITION_WRONG,
"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;
if (priv->last_seek) {
gst_validate_scenario_update_segment_from_seek (scenario, priv->last_seek);
gst_event_replace (&priv->last_seek, NULL);
}
if (priv->get_pos_id == 0) {
@ -527,7 +555,6 @@ async_done_cb (GstBus * bus, GstMessage * message,
priv->get_pos_id = g_timeout_add (50, (GSourceFunc) get_position, scenario);
}
return TRUE;
}
@ -727,9 +754,9 @@ gst_validate_scenario_init (GstValidateScenario * scenario)
GstValidateScenarioPrivate *priv = scenario->priv =
GST_VALIDATE_SCENARIO_GET_PRIVATE (scenario);
priv->seeked_position = GST_CLOCK_TIME_NONE;
priv->seek_pos_tol = DEFAULT_SEEK_TOLERANCE;
priv->segment_start = 0;
priv->segment_stop = GST_CLOCK_TIME_NONE;
}
static void
@ -737,6 +764,8 @@ gst_validate_scenario_dispose (GObject * object)
{
GstValidateScenarioPrivate *priv = GST_VALIDATE_SCENARIO (object)->priv;
if (priv->last_seek)
gst_event_unref (priv->last_seek);
if (priv->pipeline)
gst_object_unref (priv->pipeline);
g_list_free_full (priv->actions, (GDestroyNotify) _free_scenario_action);