gstbasesink: Include segment.offset in the computation of position

Position queries with GST_FORMAT_TIME are supposed to return stream
time.

gst_base_sink_get_position() estimates the current stream time on its
own instead of using gst_segment_to_stream_time(), but the algorithm
used was not taking segment.offset into account, resulting in invalid
values when this field was set to a non-zero value.

https://bugzilla.gnome.org/show_bug.cgi?id=792434
This commit is contained in:
Alicia Boya García 2018-01-10 04:08:57 +01:00 committed by Thibault Saunier
parent 7fad93d035
commit 65dcb2adbf
2 changed files with 48 additions and 2 deletions

View file

@ -4530,7 +4530,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
GstSegment *segment;
GstClockTime now, latency;
GstClockTimeDiff base_time;
gint64 time, base, duration;
gint64 time, base, offset, duration;
gdouble rate;
gint64 last;
gboolean last_seen, with_clock, in_paused;
@ -4582,6 +4582,11 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
else
time = 0;
if (GST_CLOCK_TIME_IS_VALID (segment->offset))
offset = segment->offset;
else
offset = 0;
if (GST_CLOCK_TIME_IS_VALID (segment->stop))
duration = segment->stop - segment->start;
else
@ -4703,7 +4708,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
if (rate < 0.0)
time += duration;
*cur = time + gst_guint64_to_gdouble (now - base_time) * rate;
*cur = time + offset + gst_guint64_to_gdouble (now - base_time) * rate;
/* never report more than last seen position */
if (last != -1) {

View file

@ -242,6 +242,46 @@ GST_START_TEST (basesink_test_eos_after_playing)
GST_END_TEST;
GST_START_TEST (basesink_position_query_handles_segment_offset)
{
GstElement *pipeline, *sink;
GstPad *pad;
GstEvent *ev;
GstSegment segment;
gint64 position;
sink = gst_element_factory_make ("fakesink", "sink");
g_object_set (sink, "async", FALSE, "sync", TRUE, NULL);
pad = gst_element_get_static_pad (sink, "sink");
pipeline = gst_pipeline_new (NULL);
gst_bin_add (GST_BIN (pipeline), sink);
fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PAUSED),
GST_STATE_CHANGE_SUCCESS);
ev = gst_event_new_stream_start ("test");
fail_unless (gst_pad_send_event (pad, ev));
gst_segment_init (&segment, GST_FORMAT_TIME);
segment.offset = 15000;
ev = gst_event_new_segment (&segment);
fail_unless (gst_pad_send_event (pad, ev));
fail_unless (gst_element_query_position (pipeline, GST_FORMAT_TIME,
&position));
fail_unless_equals_int (position, 15000);
fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL),
GST_STATE_CHANGE_SUCCESS);
gst_object_unref (pad);
gst_object_unref (pipeline);
}
GST_END_TEST;
static Suite *
gst_basesrc_suite (void)
{
@ -253,6 +293,7 @@ gst_basesrc_suite (void)
tcase_add_test (tc, basesink_last_sample_disabled);
tcase_add_test (tc, basesink_test_gap);
tcase_add_test (tc, basesink_test_eos_after_playing);
tcase_add_test (tc, basesink_position_query_handles_segment_offset);
return s;
}