Reverse playback support
authorNikita Bobkov <NikitaDBobkov@gmail.com>
Tue, 13 Nov 2018 20:28:45 +0000 (21:28 +0100)
committerMathieu Duponchelle <mathieu@centricular.com>
Tue, 4 Jun 2019 12:32:51 +0000 (14:32 +0200)
GStreamer plays segment from stop to start when doing reverse playback.
RTSP implies that media should be played from start of Range header to
its stop. Hence we swap start and stop times before passing them to
gst_element_seek.

Also make gst_rtsp_stream_query_stop always return value that can be
used as stop time of Range header.

gst/rtsp-server/rtsp-media.c
gst/rtsp-server/rtsp-stream.c
tests/check/gst/media.c

index 6946211..e8686fd 100644 (file)
@@ -2746,9 +2746,7 @@ gst_rtsp_media_seek_full_with_rate (GstRTSPMedia * media,
   if (start != GST_CLOCK_TIME_NONE)
     start_type = GST_SEEK_TYPE_SET;
 
-  if (priv->range_stop == stop)
-    stop = GST_CLOCK_TIME_NONE;
-  else if (stop != GST_CLOCK_TIME_NONE)
+  if (stop != GST_CLOCK_TIME_NONE)
     stop_type = GST_SEEK_TYPE_SET;
 
   /* we force a seek if any seek flag is set, or if the the rate
@@ -2793,6 +2791,16 @@ gst_rtsp_media_seek_full_with_rate (GstRTSPMedia * media,
     } else {
       gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING);
 
+      if (rate < 0.0) {
+        GstClockTime temp_time = start;
+        GstSeekType temp_type = start_type;
+
+        start = stop;
+        start_type = stop_type;
+        stop = temp_time;
+        stop_type = temp_type;
+      }
+
       res = gst_element_seek (priv->pipeline, rate, GST_FORMAT_TIME,
           flags, start_type, start, stop_type, stop);
 
index 1c88cef..80f0217 100644 (file)
@@ -5270,6 +5270,9 @@ gst_rtsp_stream_query_stop (GstRTSPStream * stream, gint64 * stop)
   if (sink) {
     GstQuery *query;
     GstFormat format;
+    gdouble rate;
+    gint64 start_value;
+    gint64 stop_value;
 
     query = gst_query_new_segment (GST_FORMAT_TIME);
     if (!gst_element_query (sink, query)) {
@@ -5278,9 +5281,11 @@ gst_rtsp_stream_query_stop (GstRTSPStream * stream, gint64 * stop)
       gst_object_unref (sink);
       return FALSE;
     }
-    gst_query_parse_segment (query, NULL, &format, NULL, stop);
+    gst_query_parse_segment (query, &rate, &format, &start_value, &stop_value);
     if (format != GST_FORMAT_TIME)
       *stop = -1;
+    else
+      *stop = rate > 0.0 ? stop_value : start_value;
     gst_query_unref (query);
     gst_object_unref (sink);
   } else if (pad) {
index bcde9c3..58b3e04 100644 (file)
@@ -116,7 +116,7 @@ GST_START_TEST (test_media_seek)
   fail_unless (applied_rate == 1.0);
 
   /* seeking with rate set to -2.0 should result in rate == -2.0 */
-  fail_unless (gst_rtsp_range_parse ("npt=5-10", &range) == GST_RTSP_OK);
+  fail_unless (gst_rtsp_range_parse ("npt=10-5", &range) == GST_RTSP_OK);
   fail_unless (gst_rtsp_media_seek_full_with_rate (media, range,
           GST_SEEK_FLAG_NONE, -2.0));
   fail_unless (gst_rtsp_media_get_rates (media, &rate, &applied_rate));