[gst-cvs] gst-rtsp-server: Add beginnings of seeking.
Wim Taymans
wtay at kemper.freedesktop.org
Thu Mar 12 12:32:32 PDT 2009
Module: gst-rtsp-server
Branch: master
Commit: 525d639cde5b3e616d84fa15486669f22ea665b8
URL: http://cgit.freedesktop.org/gstreamer/gst-rtsp-server/commit/?id=525d639cde5b3e616d84fa15486669f22ea665b8
Author: Wim Taymans <wim.taymans at collabora.co.uk>
Date: Thu Mar 12 20:32:14 2009 +0100
Add beginnings of seeking.
Parse the Range header and perform a seek on the pipeline for the requested
position. It's disabled currently until I figure out what's going wrong.
---
gst/rtsp-server/rtsp-client.c | 12 +++
gst/rtsp-server/rtsp-media.c | 169 ++++++++++++++++++++++++++++++++--------
gst/rtsp-server/rtsp-media.h | 2 +
3 files changed, 149 insertions(+), 34 deletions(-)
diff --git a/gst/rtsp-server/rtsp-client.c b/gst/rtsp-server/rtsp-client.c
index b3abb7a..5711a99 100644
--- a/gst/rtsp-server/rtsp-client.c
+++ b/gst/rtsp-server/rtsp-client.c
@@ -471,6 +471,8 @@ handle_play_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPSession *ses
guint n_streams, i;
guint timestamp, seqnum;
gchar *str;
+ GstRTSPTimeRange *range;
+ GstRTSPResult res;
if (!session)
goto no_session;
@@ -485,6 +487,16 @@ handle_play_request (GstRTSPClient *client, GstRTSPUrl *uri, GstRTSPSession *ses
media->state != GST_RTSP_STATE_READY)
goto invalid_state;
+ /* parse the range header if we have one */
+ res = gst_rtsp_message_get_header (request, GST_RTSP_HDR_RANGE, &str, 0);
+ if (res == GST_RTSP_OK) {
+ if (gst_rtsp_range_parse (str, &range) == GST_RTSP_OK) {
+ /* we have a range, seek to the position */
+ gst_rtsp_media_seek (media->media, range);
+ gst_rtsp_range_free (range);
+ }
+ }
+
/* grab RTPInfo from the payloaders now */
rtpinfo = g_string_new ("");
diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c
index b75d386..6a24af0 100644
--- a/gst/rtsp-server/rtsp-media.c
+++ b/gst/rtsp-server/rtsp-media.c
@@ -157,6 +157,50 @@ do_loop (GstRTSPMediaClass *klass)
return NULL;
}
+static void
+collect_media_stats (GstRTSPMedia *media)
+{
+ GstFormat format;
+ gint64 position, duration;
+
+ media->range.unit = GST_RTSP_RANGE_NPT;
+
+ if (media->is_live) {
+ media->range.min.type = GST_RTSP_TIME_NOW;
+ media->range.min.seconds = -1;
+ media->range.max.type = GST_RTSP_TIME_END;
+ media->range.max.seconds = -1;
+ }
+ else {
+ /* get the position */
+ format = GST_FORMAT_TIME;
+ if (!gst_element_query_position (media->pipeline, &format, &position))
+ position = 0;
+
+ /* get the duration */
+ format = GST_FORMAT_TIME;
+ if (!gst_element_query_duration (media->pipeline, &format, &duration))
+ duration = -1;
+
+ if (position == -1) {
+ media->range.min.type = GST_RTSP_TIME_NOW;
+ media->range.min.seconds = -1;
+ }
+ else {
+ media->range.min.type = GST_RTSP_TIME_SECONDS;
+ media->range.min.seconds = ((gdouble)position) / GST_SECOND;
+ }
+ if (duration == -1) {
+ media->range.max.type = GST_RTSP_TIME_END;
+ media->range.max.seconds = -1;
+ }
+ else {
+ media->range.max.type = GST_RTSP_TIME_SECONDS;
+ media->range.max.seconds = ((gdouble)duration) / GST_SECOND;
+ }
+ }
+}
+
/**
* gst_rtsp_media_new:
*
@@ -251,6 +295,97 @@ gst_rtsp_media_get_stream (GstRTSPMedia *media, guint idx)
}
/**
+ * gst_rtsp_media_seek:
+ * @stream: a #GstRTSPMediaStream
+ * @range: a #GstRTSPTimeRange
+ *
+ * Seek the pipeline to @range.
+ *
+ * Returns: %TRUE on success.
+ */
+gboolean
+gst_rtsp_media_seek (GstRTSPMedia *media, GstRTSPTimeRange *range)
+{
+ GstSeekFlags flags;
+ gboolean res;
+ gint64 start, stop;
+ GstSeekType start_type, stop_type;
+
+ g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+ g_return_val_if_fail (range != NULL, FALSE);
+
+ if (range->unit != GST_RTSP_RANGE_NPT)
+ goto not_supported;
+
+ /* depends on the current playing state of the pipeline. We might need to
+ * queue this until we get EOS. */
+ flags = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE;
+
+ start_type = stop_type = GST_SEEK_TYPE_NONE;
+
+ switch (range->min.type) {
+ case GST_RTSP_TIME_NOW:
+ start = -1;
+ break;
+ case GST_RTSP_TIME_SECONDS:
+ start = range->min.seconds * GST_SECOND;
+ start_type = GST_SEEK_TYPE_SET;
+ break;
+ case GST_RTSP_TIME_END:
+ default:
+ goto weird_type;
+ }
+ switch (range->max.type) {
+ case GST_RTSP_TIME_SECONDS:
+ stop = range->max.seconds * GST_SECOND;
+ stop_type = GST_SEEK_TYPE_SET;
+ break;
+ case GST_RTSP_TIME_END:
+ stop = -1;
+ stop_type = GST_SEEK_TYPE_SET;
+ break;
+ case GST_RTSP_TIME_NOW:
+ default:
+ goto weird_type;
+ }
+
+ if (start != -1 || stop != -1) {
+ g_message ("seeking to %"GST_TIME_FORMAT" - %"GST_TIME_FORMAT,
+ GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+
+#if 0
+ res = gst_element_seek (media->pipeline, 1.0, GST_FORMAT_TIME,
+ flags, start_type, start, stop_type, stop);
+#endif
+ res = TRUE;
+
+ /* and block for the seek to complete */
+ gst_element_get_state (media->pipeline, NULL, NULL, -1);
+ g_message ("done seeking %d", res);
+
+ collect_media_stats (media);
+ }
+ else {
+ g_message ("no seek needed");
+ res = TRUE;
+ }
+
+ return res;
+
+ /* ERRORS */
+not_supported:
+ {
+ g_warning ("seek unit %d not supported", range->unit);
+ return FALSE;
+ }
+weird_type:
+ {
+ g_warning ("weird range type %d not supported", range->min.type);
+ return FALSE;
+ }
+}
+
+/**
* gst_rtsp_media_stream_rtp:
* @stream: a #GstRTSPMediaStream
* @buffer: a #GstBuffer
@@ -699,40 +834,6 @@ unlock_streams (GstRTSPMedia *media)
}
}
-static void
-collect_media_stats (GstRTSPMedia *media)
-{
- GstFormat format;
- gint64 duration;
-
- media->range.unit = GST_RTSP_RANGE_NPT;
-
- if (media->is_live) {
- media->range.min.type = GST_RTSP_TIME_NOW;
- media->range.min.seconds = -1;
- media->range.max.type = GST_RTSP_TIME_END;
- media->range.max.seconds = -1;
- }
- else {
- media->range.min.type = GST_RTSP_TIME_SECONDS;
- media->range.min.seconds = 0.0;
-
- /* get the duration */
- format = GST_FORMAT_TIME;
- if (!gst_element_query_duration (media->pipeline, &format, &duration))
- duration = -1;
-
- if (duration == -1) {
- media->range.max.type = GST_RTSP_TIME_END;
- media->range.max.seconds = -1;
- }
- else {
- media->range.max.type = GST_RTSP_TIME_SECONDS;
- media->range.max.seconds = ((gdouble)duration) / GST_SECOND;
- }
- }
-}
-
static gboolean
default_handle_message (GstRTSPMedia *media, GstMessage *message)
{
diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h
index 4aaaa1d..e2c8405 100644
--- a/gst/rtsp-server/rtsp-media.h
+++ b/gst/rtsp-server/rtsp-media.h
@@ -200,6 +200,8 @@ gboolean gst_rtsp_media_prepare (GstRTSPMedia *media);
guint gst_rtsp_media_n_streams (GstRTSPMedia *media);
GstRTSPMediaStream * gst_rtsp_media_get_stream (GstRTSPMedia *media, guint idx);
+gboolean gst_rtsp_media_seek (GstRTSPMedia *media, GstRTSPTimeRange *range);
+
GstFlowReturn gst_rtsp_media_stream_rtp (GstRTSPMediaStream *stream, GstBuffer *buffer);
GstFlowReturn gst_rtsp_media_stream_rtcp (GstRTSPMediaStream *stream, GstBuffer *buffer);
More information about the Gstreamer-commits
mailing list