basesink: Fix clock synchronization running time in reverse playback
authorThibault Saunier <tsaunier@igalia.com>
Thu, 23 Apr 2020 20:24:15 +0000 (16:24 -0400)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 6 May 2020 14:24:36 +0000 (14:24 +0000)
In reverse playback, buffers have to be displayed at buffer.stop running
time, otherwise a same set of buffer can't be displayed in the exact opposite
order to forward playback.

For example, seeking a video stream at 1fps with start=0, stop=5s, rate=1.0

will display the following buffers:

  b0.pts = 0s, b0.duration = 1s - at running time = 0s
  b1.pts = 1s, b1.duration = 1s - at running time = 1s
  b2.pts = 2s, b2.duration = 1s - at running time = 2s
  b3.pts = 3s, b3.duration = 1s - at running time = 3s
  b4.pts = 4s, b4.duration = 1s - at running time = 4s
  <wait at EOS for 1second>

Now, playing that reverse with start=0, stop=5s, rate=1.0 has to display
the following buffers:

  b0.pts = 4s, b0.duration = 1s - at running time = 0s
  b1.pts = 3s, b1.duration = 1s - at running time = 1s
  b2.pts = 2s, b2.duration = 1s - at running time = 2s
  b3.pts = 1s, b3.duration = 1s - at running time = 3s
  b4.pts = 0s, b4.duration = 1s - at running time = 4s
  <wait at EOS for 1second>

With the previous code, it reproduced the following:

  b0.pts = 4s, b0.duration = 1s - at running time = 1s
  b1.pts = 3s, b1.duration = 1s - at running time = 2s
  b2.pts = 2s, b2.duration = 1s - at running time = 3s
  b3.pts = 1s, b3.duration = 1s - at running time = 4s
  b4.pts = 0s, b4.duration = 1s - at running time = 5s
  <NO WAIT AT EOS AND POST EOS RIGHT AWAY>

This is being tested with the `validate.launch_pipeline.sink.reverse_playback_clock_waits.*`
set of tests

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/450>

libs/gst/base/gstbasesink.c

index c75dbcb..8bfc495 100644 (file)
@@ -2197,6 +2197,13 @@ do_times:
   rstart = gst_segment_to_running_time (segment, format, cstart);
   rstop = gst_segment_to_running_time (segment, format, cstop);
 
+  /* In reverse playback, play from stop to start */
+  if (segment->rate < 0.0 && GST_CLOCK_TIME_IS_VALID (rstop)) {
+    GstClockTime tmp = rstart;
+    rstart = rstop;
+    rstop = tmp;
+  }
+
   if (GST_CLOCK_TIME_IS_VALID (stop))
     rnext = rstop;
   else