rtspsrc: improve recovery from failed seek
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 9 Mar 2011 16:07:47 +0000 (17:07 +0100)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Wed, 9 Mar 2011 16:18:09 +0000 (17:18 +0100)
In case server-side fails to perform seek, i.e. PLAY at non-zero requested
position, recovery so far would arrange for streaming to continue, albeit
having lost position tracking in the process.  So, query position prior
to seek and use upon failed seek.

gst/rtsp/gstrtspsrc.c
gst/rtsp/gstrtspsrc.h

index 980fd02..e1c8f9b 100644 (file)
@@ -1716,6 +1716,33 @@ gst_rtspsrc_connection_receive (GstRTSPSrc * src, GstRTSPConnection * conn,
   return ret;
 }
 
+static void
+gst_rtspsrc_get_position (GstRTSPSrc * src)
+{
+  GstQuery *query;
+  GList *walk;
+
+  query = gst_query_new_position (GST_FORMAT_TIME);
+  /*  should be known somewhere down the stream (e.g. jitterbuffer) */
+  for (walk = src->streams; walk; walk = g_list_next (walk)) {
+    GstRTSPStream *stream = (GstRTSPStream *) walk->data;
+    GstFormat fmt;
+    gint64 pos;
+
+    if (stream->srcpad) {
+      if (gst_pad_query (stream->srcpad, query)) {
+        gst_query_parse_position (query, &fmt, &pos);
+        GST_DEBUG_OBJECT (src, "retaining position %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (pos));
+        src->last_pos = pos;
+        return;
+      }
+    }
+  }
+
+  src->last_pos = 0;
+}
+
 static gboolean
 gst_rtspsrc_do_seek (GstRTSPSrc * src, GstSegment * segment)
 {
@@ -1808,8 +1835,11 @@ gst_rtspsrc_perform_seek (GstRTSPSrc * src, GstEvent * event)
   playing = (src->state == GST_RTSP_STATE_PLAYING);
 
   /* if we were playing, pause first */
-  if (playing)
+  if (playing) {
+    /* obtain current position in case seek fails */
+    gst_rtspsrc_get_position (src);
     gst_rtspsrc_pause (src, FALSE);
+  }
 
   gst_rtspsrc_do_seek (src, &seeksegment);
 
@@ -5885,7 +5915,7 @@ gst_rtspsrc_play (GstRTSPSrc * src, GstSegment * segment)
       /* NOTE the above also disables npt based eos detection */
       /* and below forces position to 0,
        * which is visible feedback we lost the plot */
-      segment->start = segment->last_stop = 0;
+      segment->start = segment->last_stop = src->last_pos;
     }
 
     gst_rtsp_message_unset (&request);
index 00861b6..460f29a 100644 (file)
@@ -233,7 +233,9 @@ struct _GstRTSPSrc {
 
   /* supported methods */
   gint               methods;
+
   gboolean           seekable;
+  GstClockTime       last_pos;
 
   /* session management */
   GstElement      *manager;