From efdb795c86d5e9fbc25da52406c0791ebccb0b05 Mon Sep 17 00:00:00 2001 From: Patricia Muscalu Date: Mon, 23 Oct 2017 09:49:09 +0200 Subject: rtsp-media: seek on media pipelines that are complete 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 | 28 ++++++++++++++++++++ gst/rtsp-server/rtsp-stream.c | 59 ++++++++++++++++++++++++++++++------------- gst/rtsp-server/rtsp-stream.h | 3 +++ 3 files changed, 73 insertions(+), 17 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index 159dd3d..0f8a194 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -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); diff --git a/gst/rtsp-server/rtsp-stream.c b/gst/rtsp-server/rtsp-stream.c index 9a8f1c2..67c02d1 100644 --- a/gst/rtsp-server/rtsp-stream.c +++ b/gst/rtsp-server/rtsp-stream.c @@ -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; +} diff --git a/gst/rtsp-server/rtsp-stream.h b/gst/rtsp-server/rtsp-stream.h index add1a88..37a8275 100644 --- a/gst/rtsp-server/rtsp-stream.h +++ b/gst/rtsp-server/rtsp-stream.h @@ -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 -- cgit v1.2.3