Add beginnings of seeking.
authorWim Taymans <wim.taymans@collabora.co.uk>
Thu, 12 Mar 2009 19:32:14 +0000 (20:32 +0100)
committerWim Taymans <wim.taymans@collabora.co.uk>
Thu, 12 Mar 2009 19:32:14 +0000 (20:32 +0100)
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
gst/rtsp-server/rtsp-media.c
gst/rtsp-server/rtsp-media.h

index b3abb7a..5711a99 100644 (file)
@@ -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 ("");
 
index b75d386..6a24af0 100644 (file)
@@ -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)
 {
index 4aaaa1d..e2c8405 100644 (file)
@@ -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);