From 65dcb2adbfe8edeaaa0212df2798695f15497b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20Boya=20Garc=C3=ADa?= Date: Wed, 10 Jan 2018 04:08:57 +0100 Subject: [PATCH] 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 --- libs/gst/base/gstbasesink.c | 9 ++++++-- tests/check/libs/basesink.c | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c index b4b11f028c..ae0202438c 100644 --- a/libs/gst/base/gstbasesink.c +++ b/libs/gst/base/gstbasesink.c @@ -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) { diff --git a/tests/check/libs/basesink.c b/tests/check/libs/basesink.c index ee971521c4..5415d70ba3 100644 --- a/tests/check/libs/basesink.c +++ b/tests/check/libs/basesink.c @@ -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; }