rtsp-media: seek on media pipelines that are complete
authorPatricia Muscalu <patricia@axis.com>
Mon, 23 Oct 2017 07:49:09 +0000 (09:49 +0200)
committerSebastian Dröge <sebastian@centricular.com>
Wed, 15 Nov 2017 17:56:26 +0000 (19:56 +0200)
Make sure that a seek is performed on pipelines that
contain at least one sink element.

Change-Id: Icf398e10add3191d104b1289de612412da326819

https://bugzilla.gnome.org/show_bug.cgi?id=788340

gst/rtsp-server/rtsp-media.c
gst/rtsp-server/rtsp-stream.c
gst/rtsp-server/rtsp-stream.h

index 159dd3d..0f8a194 100644 (file)
@@ -705,6 +705,23 @@ check_seekable (GstRTSPMedia * media)
   gst_query_unref (query);
 }
 
+/* must be called with state lock */
+static gboolean
+check_complete (GstRTSPMedia * media)
+{
+  GstRTSPMediaPrivate *priv = media->priv;
+
+  guint i, n = priv->streams->len;
+
+  for (i = 0; i < n; i++) {
+    GstRTSPStream *stream = g_ptr_array_index (priv->streams, i);
+
+    if (gst_rtsp_stream_is_complete (stream))
+      return TRUE;
+  }
+
+  return FALSE;
+}
 
 /* must be called with state lock */
 static void
@@ -2209,6 +2226,11 @@ gst_rtsp_media_seek_full (GstRTSPMedia * media, GstRTSPTimeRange * range,
   if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED)
     goto not_prepared;
 
+  /* check if the media pipeline is complete in order to perform a
+   * seek operation on it */
+  if (!check_complete (media))
+    goto not_complete;
+
   /* Update the seekable state of the pipeline in case it changed */
   check_seekable (media);
 
@@ -2322,6 +2344,12 @@ not_prepared:
     GST_INFO ("media %p is not prepared", media);
     return FALSE;
   }
+not_complete:
+  {
+    g_rec_mutex_unlock (&priv->state_lock);
+    GST_INFO ("pipeline is not complete");
+    return FALSE;
+  }
 not_seekable:
   {
     g_rec_mutex_unlock (&priv->state_lock);
index 9a8f1c2..67c02d1 100644 (file)
@@ -77,6 +77,9 @@ struct _GstRTSPStreamPrivate
   gboolean client_side;
   gchar *control;
 
+  /* TRUE if stream is complete. This means that the receiver and the sender
+   * parts are present in the stream. */
+  gboolean is_complete;
   GstRTSPProfile profiles;
   GstRTSPLowerTrans protocols;
 
@@ -273,6 +276,7 @@ gst_rtsp_stream_finalize (GObject * obj)
 {
   GstRTSPStream *stream;
   GstRTSPStreamPrivate *priv;
+  guint i;
 
   stream = GST_RTSP_STREAM (obj);
   priv = stream->priv;
@@ -295,22 +299,16 @@ gst_rtsp_stream_finalize (GObject * obj)
   if (priv->rtxsend)
     g_object_unref (priv->rtxsend);
 
-  if (priv->socket_v4[0])
-    g_object_unref (priv->socket_v4[0]);
-  if (priv->socket_v4[1])
-    g_object_unref (priv->socket_v4[1]);
-  if (priv->socket_v6[0])
-    g_object_unref (priv->socket_v6[0]);
-  if (priv->socket_v6[1])
-    g_object_unref (priv->socket_v6[1]);
-  if (priv->mcast_socket_v4[0])
-    g_object_unref (priv->mcast_socket_v4[0]);
-  if (priv->mcast_socket_v4[1])
-    g_object_unref (priv->mcast_socket_v4[1]);
-  if (priv->mcast_socket_v6[0])
-    g_object_unref (priv->mcast_socket_v6[0]);
-  if (priv->mcast_socket_v6[1])
-    g_object_unref (priv->mcast_socket_v6[1]);
+  for (i = 0; i < 2; i++) {
+    if (priv->socket_v4[i])
+      g_object_unref (priv->socket_v4[i]);
+    if (priv->socket_v6[i])
+      g_object_unref (priv->socket_v6[i]);
+    if (priv->mcast_socket_v4[i])
+      g_object_unref (priv->mcast_socket_v4[i]);
+    if (priv->mcast_socket_v6[i])
+      g_object_unref (priv->mcast_socket_v6[i]);
+  }
 
   g_free (priv->multicast_iface);
 
@@ -4455,7 +4453,7 @@ gst_rtsp_stream_query_stop (GstRTSPStream * stream, gint64 * stop)
  * Add a receiver and sender part to the pipeline based on the transport from
  * SETUP.
  *
- * Returns: %TRUE if the pipeline has been sucessfully updated.
+ * Returns: %TRUE if the stream has been sucessfully updated.
  */
 gboolean
 gst_rtsp_stream_complete_stream (GstRTSPStream * stream,
@@ -4480,6 +4478,7 @@ gst_rtsp_stream_complete_stream (GstRTSPStream * stream,
   if (!create_sender_part (stream, transport))
     goto create_sender_error;
 
+  priv->is_complete = TRUE;
   g_mutex_unlock (&priv->lock);
 
   GST_DEBUG_OBJECT (stream, "pipeline sucsessfully updated");
@@ -4493,3 +4492,29 @@ unallowed_transport:
     return FALSE;
   }
 }
+
+/**
+ * gst_rtsp_stream_is_complete:
+ * @stream: a #GstRTSPStream
+ *
+ * Checks whether the stream is complete, contains the receiver and the sender
+ * parts. As the stream contains sink(s) element(s), it's possible to perform
+ * seek operations on it.
+ *
+ * Returns: %TRUE if the stream contains at least one sink element.
+ */
+gboolean
+gst_rtsp_stream_is_complete (GstRTSPStream * stream)
+{
+  GstRTSPStreamPrivate *priv;
+  gboolean ret = FALSE;
+
+  g_return_val_if_fail (GST_IS_RTSP_STREAM (stream), FALSE);
+
+  priv = stream->priv;
+  g_mutex_lock (&priv->lock);
+  ret = priv->is_complete;
+  g_mutex_unlock (&priv->lock);
+
+  return ret;
+}
index add1a88..37a8275 100644 (file)
@@ -287,6 +287,9 @@ GstRTSPPublishClockMode gst_rtsp_stream_get_publish_clock_mode (GstRTSPStream *
 GST_EXPORT
 gboolean          gst_rtsp_stream_complete_stream (GstRTSPStream * stream, const GstRTSPTransport * transport);
 
+GST_EXPORT
+gboolean           gst_rtsp_stream_is_complete (GstRTSPStream * stream);
+
 /**
  * GstRTSPStreamTransportFilterFunc:
  * @stream: a #GstRTSPStream object