From f31f79f60eae1cb66db7288fadabf5a6135726a5 Mon Sep 17 00:00:00 2001 From: Nikita Bobkov Date: Tue, 13 Nov 2018 21:28:45 +0100 Subject: [PATCH] Reverse playback support 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 | 14 +++++++++++--- gst/rtsp-server/rtsp-stream.c | 7 ++++++- tests/check/gst/media.c | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 6946211ec4..e8686fd5dd 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -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); diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index 1c88cefb11..80f0217e5c 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -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) { diff --git a/tests/check/gst/media.c b/tests/check/gst/media.c index bcde9c30f9..58b3e0477c 100644 --- a/tests/check/gst/media.c +++ b/tests/check/gst/media.c @@ -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));