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
diff --git a/libs/gst/base/gstbasesink.c b/libs/gst/base/gstbasesink.c
index b4b11f0..ae02024 100644
--- a/libs/gst/base/gstbasesink.c
+++ b/libs/gst/base/gstbasesink.c
@@ -4530,7 +4530,7 @@
   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 @@
   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 @@
     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 ee97152..5415d70 100644
--- a/tests/check/libs/basesink.c
+++ b/tests/check/libs/basesink.c
@@ -242,6 +242,46 @@
 
 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 @@
   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;
 }