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.
This commit is contained in:
Nikita Bobkov 2018-11-13 21:28:45 +01:00 committed by Mathieu Duponchelle
parent bc74589601
commit f31f79f60e
3 changed files with 18 additions and 5 deletions

View file

@ -2746,9 +2746,7 @@ gst_rtsp_media_seek_full_with_rate (GstRTSPMedia * media,
if (start != GST_CLOCK_TIME_NONE) if (start != GST_CLOCK_TIME_NONE)
start_type = GST_SEEK_TYPE_SET; start_type = GST_SEEK_TYPE_SET;
if (priv->range_stop == stop) if (stop != GST_CLOCK_TIME_NONE)
stop = GST_CLOCK_TIME_NONE;
else if (stop != GST_CLOCK_TIME_NONE)
stop_type = GST_SEEK_TYPE_SET; stop_type = GST_SEEK_TYPE_SET;
/* we force a seek if any seek flag is set, or if the the rate /* 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 { } else {
gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARING); 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, res = gst_element_seek (priv->pipeline, rate, GST_FORMAT_TIME,
flags, start_type, start, stop_type, stop); flags, start_type, start, stop_type, stop);

View file

@ -5270,6 +5270,9 @@ gst_rtsp_stream_query_stop (GstRTSPStream * stream, gint64 * stop)
if (sink) { if (sink) {
GstQuery *query; GstQuery *query;
GstFormat format; GstFormat format;
gdouble rate;
gint64 start_value;
gint64 stop_value;
query = gst_query_new_segment (GST_FORMAT_TIME); query = gst_query_new_segment (GST_FORMAT_TIME);
if (!gst_element_query (sink, query)) { if (!gst_element_query (sink, query)) {
@ -5278,9 +5281,11 @@ gst_rtsp_stream_query_stop (GstRTSPStream * stream, gint64 * stop)
gst_object_unref (sink); gst_object_unref (sink);
return FALSE; 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) if (format != GST_FORMAT_TIME)
*stop = -1; *stop = -1;
else
*stop = rate > 0.0 ? stop_value : start_value;
gst_query_unref (query); gst_query_unref (query);
gst_object_unref (sink); gst_object_unref (sink);
} else if (pad) { } else if (pad) {

View file

@ -116,7 +116,7 @@ GST_START_TEST (test_media_seek)
fail_unless (applied_rate == 1.0); fail_unless (applied_rate == 1.0);
/* seeking with rate set to -2.0 should result in rate == -2.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, fail_unless (gst_rtsp_media_seek_full_with_rate (media, range,
GST_SEEK_FLAG_NONE, -2.0)); GST_SEEK_FLAG_NONE, -2.0));
fail_unless (gst_rtsp_media_get_rates (media, &rate, &applied_rate)); fail_unless (gst_rtsp_media_get_rates (media, &rate, &applied_rate));