mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
validate: add non flushing seek support
and a couple scenarios using them https://bugzilla.gnome.org/show_bug.cgi?id=744783
This commit is contained in:
parent
d08a6b8e0c
commit
3ff55dcc31
4 changed files with 143 additions and 0 deletions
|
@ -1,7 +1,9 @@
|
||||||
scenariosdir=${datadir}/gstreamer-$(GST_API_VERSION)/validate-scenario
|
scenariosdir=${datadir}/gstreamer-$(GST_API_VERSION)/validate-scenario
|
||||||
scenarios_DATA = simple_seeks.scenario \
|
scenarios_DATA = simple_seeks.scenario \
|
||||||
seek_forward.scenario \
|
seek_forward.scenario \
|
||||||
|
seek_forward_non_flushing.scenario \
|
||||||
seek_backward.scenario \
|
seek_backward.scenario \
|
||||||
|
seek_backward_non_flushing.scenario \
|
||||||
seek_forward_backward.scenario \
|
seek_forward_backward.scenario \
|
||||||
reverse_playback.scenario \
|
reverse_playback.scenario \
|
||||||
fast_forward.scenario \
|
fast_forward.scenario \
|
||||||
|
@ -27,7 +29,9 @@ scenarios_DATA = simple_seeks.scenario \
|
||||||
|
|
||||||
EXTRA_DIST = simple_seeks.scenario \
|
EXTRA_DIST = simple_seeks.scenario \
|
||||||
seek_forward.scenario \
|
seek_forward.scenario \
|
||||||
|
seek_forward_non_flushing.scenario \
|
||||||
seek_backward.scenario \
|
seek_backward.scenario \
|
||||||
|
seek_backward_non_flushing.scenario \
|
||||||
seek_forward_backward.scenario \
|
seek_forward_backward.scenario \
|
||||||
reverse_playback.scenario \
|
reverse_playback.scenario \
|
||||||
fast_forward.scenario \
|
fast_forward.scenario \
|
||||||
|
|
5
validate/data/seek_backward_non_flushing.scenario
Normal file
5
validate/data/seek_backward_non_flushing.scenario
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
description, seek=true, duration=30, need-clock-sync=true, min-media-duration=15
|
||||||
|
seek, name=Backward-seek, playback-time="min(5.0, (duration/4))", rate=1.0, start=0.0, flags=accurate
|
||||||
|
seek, name=Backward-seek, playback-time="min(10.0, 2*(duration/4))", rate=1.0, start="min(5.0, duration/4)", flags=accurate
|
||||||
|
seek, name=Backward-seek, playback-time="min(15.0, 3*(duration/4))", rate=1.0, start="min(10.0, 2*(duration/4))", flags=accurate
|
||||||
|
stop, playback-time="min(15.0, 3*(duration/4))"
|
5
validate/data/seek_forward_non_flushing.scenario
Normal file
5
validate/data/seek_forward_non_flushing.scenario
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
description, seek=true, duration=20, need-clock-sync=true, min-media-duration=30
|
||||||
|
seek, name=First-forward-seek, playback-time="min(5.0, (duration/8))", start="min(10, 2*(duration/8))", flags=accurate
|
||||||
|
seek, name=Second-forward-seek, playback-time="min(15.0, 3*(duration/8))", start="min(20, 4*(duration/8))", flags=accurate
|
||||||
|
seek, name=Third-forward-seek, playback-time="min(25, 5*(duration/8))", start="min(30.0, 6*(duration/8))", flags=accurate
|
||||||
|
stop, playback-time=35.0
|
|
@ -113,6 +113,7 @@ struct _GstValidateScenarioPrivate
|
||||||
GstClockTime segment_start;
|
GstClockTime segment_start;
|
||||||
GstClockTime segment_stop;
|
GstClockTime segment_stop;
|
||||||
GstClockTime seek_pos_tol;
|
GstClockTime seek_pos_tol;
|
||||||
|
guint32 expected_seqnum;
|
||||||
|
|
||||||
/* If we seeked in paused the position should be exactly what
|
/* If we seeked in paused the position should be exactly what
|
||||||
* the seek value was (if accurate) */
|
* the seek value was (if accurate) */
|
||||||
|
@ -131,6 +132,8 @@ struct _GstValidateScenarioPrivate
|
||||||
GstState target_state;
|
GstState target_state;
|
||||||
|
|
||||||
GList *overrides;
|
GList *overrides;
|
||||||
|
|
||||||
|
guint segments_needed;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct KeyFileGroupName
|
typedef struct KeyFileGroupName
|
||||||
|
@ -430,6 +433,122 @@ gst_validate_action_get_clocktime (GstValidateScenario * scenario,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstPadProbeReturn
|
||||||
|
_check_new_segment_done (GstPad * pad, GstPadProbeInfo * info,
|
||||||
|
GstValidateAction * action)
|
||||||
|
{
|
||||||
|
GstEvent *event = GST_EVENT (info->data);
|
||||||
|
if (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT) {
|
||||||
|
if (GST_EVENT_SEQNUM (event) == action->scenario->priv->expected_seqnum) {
|
||||||
|
if (!--action->scenario->priv->segments_needed) {
|
||||||
|
gst_validate_action_set_done (action);
|
||||||
|
return GST_PAD_PROBE_REMOVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GST_PAD_PROBE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstObject *
|
||||||
|
_find_any_object (GstIterator * iter)
|
||||||
|
{
|
||||||
|
GstObject *object = NULL;
|
||||||
|
gboolean done = FALSE;
|
||||||
|
GValue data = { 0, };
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
switch (gst_iterator_next (iter, &data)) {
|
||||||
|
case GST_ITERATOR_OK:
|
||||||
|
{
|
||||||
|
object = g_value_get_object (&data);
|
||||||
|
gst_object_ref (object);
|
||||||
|
g_value_reset (&data);
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GST_ITERATOR_RESYNC:
|
||||||
|
gst_iterator_resync (iter);
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_DONE:
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_ERROR:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_value_unset (&data);
|
||||||
|
gst_iterator_free (iter);
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
_run_for_all_sinks (GstValidateScenario * scenario,
|
||||||
|
void (*f) (GstValidateScenario *, GstElement *, gpointer),
|
||||||
|
gpointer userdata)
|
||||||
|
{
|
||||||
|
GstElement *sink = NULL;
|
||||||
|
gboolean done = FALSE;
|
||||||
|
GValue data = { 0, };
|
||||||
|
GstIterator *iter;
|
||||||
|
guint nsinks = 0;
|
||||||
|
|
||||||
|
iter = gst_bin_iterate_sinks (GST_BIN (scenario->pipeline));
|
||||||
|
while (!done) {
|
||||||
|
switch (gst_iterator_next (iter, &data)) {
|
||||||
|
case GST_ITERATOR_OK:
|
||||||
|
{
|
||||||
|
sink = GST_ELEMENT (g_value_get_object (&data));
|
||||||
|
(*f) (scenario, sink, userdata);
|
||||||
|
g_value_reset (&data);
|
||||||
|
++nsinks;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GST_ITERATOR_RESYNC:
|
||||||
|
gst_iterator_resync (iter);
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_DONE:
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_ERROR:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
done = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_value_unset (&data);
|
||||||
|
gst_iterator_free (iter);
|
||||||
|
|
||||||
|
return nsinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstPad *
|
||||||
|
_find_any_sink_pad (GstElement * e)
|
||||||
|
{
|
||||||
|
return GST_PAD (_find_any_object (gst_element_iterate_sink_pads (e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_add_segment_check_probe (GstValidateScenario * scenario, GstElement * sink,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GstPad *sinkpad;
|
||||||
|
GstValidateAction *action = data;
|
||||||
|
|
||||||
|
sinkpad = _find_any_sink_pad (sink);
|
||||||
|
if (sinkpad) {
|
||||||
|
gst_pad_add_probe (sinkpad,
|
||||||
|
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
|
||||||
|
(GstPadProbeCallback) _check_new_segment_done, action, NULL);
|
||||||
|
gst_object_unref (sinkpad);
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (scenario, "No sink pad found on sink");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_validate_scenario_execute_seek:
|
* gst_validate_scenario_execute_seek:
|
||||||
* @scenario: The #GstValidateScenario for which to execute a seek action
|
* @scenario: The #GstValidateScenario for which to execute a seek action
|
||||||
|
@ -466,6 +585,7 @@ gst_validate_scenario_execute_seek (GstValidateScenario * scenario,
|
||||||
if (gst_element_send_event (scenario->pipeline, seek)) {
|
if (gst_element_send_event (scenario->pipeline, seek)) {
|
||||||
gst_event_replace (&priv->last_seek, seek);
|
gst_event_replace (&priv->last_seek, seek);
|
||||||
priv->seek_flags = flags;
|
priv->seek_flags = flags;
|
||||||
|
priv->expected_seqnum = GST_EVENT_SEQNUM (seek);
|
||||||
} else {
|
} else {
|
||||||
GST_VALIDATE_REPORT (scenario, EVENT_SEEK_NOT_HANDLED,
|
GST_VALIDATE_REPORT (scenario, EVENT_SEEK_NOT_HANDLED,
|
||||||
"Could not execute seek: '(position %" GST_TIME_FORMAT
|
"Could not execute seek: '(position %" GST_TIME_FORMAT
|
||||||
|
@ -478,6 +598,15 @@ gst_validate_scenario_execute_seek (GstValidateScenario * scenario,
|
||||||
}
|
}
|
||||||
gst_event_unref (seek);
|
gst_event_unref (seek);
|
||||||
|
|
||||||
|
/* Flushing seeks will be deemed done when an ASYNC_DONE message gets
|
||||||
|
received on the bus. We don't get one for non flushing seeks though,
|
||||||
|
so we look for a new segment event with a matching seqnum. */
|
||||||
|
if (ret != GST_VALIDATE_EXECUTE_ACTION_ERROR
|
||||||
|
&& !(flags & GST_SEEK_FLAG_FLUSH)) {
|
||||||
|
action->scenario->priv->segments_needed =
|
||||||
|
_run_for_all_sinks (scenario, _add_segment_check_probe, action);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue