diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index f1b9cb205b..5687a72cc5 100644 --- a/gst/rtsp-server/rtsp-media.c +++ b/gst/rtsp-server/rtsp-media.c @@ -176,6 +176,8 @@ static gboolean default_handle_message (GstRTSPMedia * media, static void finish_unprepare (GstRTSPMedia * media); static gboolean default_prepare (GstRTSPMedia * media, GstRTSPThread * thread); static gboolean default_unprepare (GstRTSPMedia * media); +static gboolean default_suspend (GstRTSPMedia * media); +static gboolean default_unsuspend (GstRTSPMedia * media); static gboolean default_convert_range (GstRTSPMedia * media, GstRTSPTimeRange * range, GstRTSPRangeUnit unit); static gboolean default_query_position (GstRTSPMedia * media, @@ -308,6 +310,8 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass) klass->handle_message = default_handle_message; klass->prepare = default_prepare; klass->unprepare = default_unprepare; + klass->suspend = default_suspend; + klass->unsuspend = default_unsuspend; klass->convert_range = default_convert_range; klass->query_position = default_query_position; klass->query_stop = default_query_stop; @@ -2661,36 +2665,13 @@ no_setup_sdp: } } -/** - * gst_rtsp_media_suspend: - * @media: a #GstRTSPMedia - * - * Suspend @media. The state of the pipeline managed by @media is set to - * GST_STATE_NULL but all streams are kept. @media can be prepared again - * with gst_rtsp_media_unsuspend() - * - * @media must be prepared with gst_rtsp_media_prepare(); - * - * Returns: %TRUE on success. - */ +/* call with state_lock */ gboolean -gst_rtsp_media_suspend (GstRTSPMedia * media) +default_suspend (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv = media->priv; GstStateChangeReturn ret; - g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); - - GST_FIXME ("suspend for dynamic pipelines needs fixing"); - - g_rec_mutex_lock (&priv->state_lock); - if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) - goto not_prepared; - - /* don't attempt to suspend when something is busy */ - if (priv->n_active > 0) - goto done; - switch (priv->suspend_mode) { case GST_RTSP_SUSPEND_MODE_NONE: GST_DEBUG ("media %p no suspend", media); @@ -2710,8 +2691,56 @@ gst_rtsp_media_suspend (GstRTSPMedia * media) default: break; } + /* let the streams do the state changes freely, if any */ media_streams_set_blocked (media, FALSE); + + return TRUE; + + /* ERRORS */ +state_failed: + { + GST_WARNING ("failed changing pipeline's state for media %p", media); + return FALSE; + } +} + +/** + * gst_rtsp_media_suspend: + * @media: a #GstRTSPMedia + * + * Suspend @media. The state of the pipeline managed by @media is set to + * GST_STATE_NULL but all streams are kept. @media can be prepared again + * with gst_rtsp_media_unsuspend() + * + * @media must be prepared with gst_rtsp_media_prepare(); + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_suspend (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaClass *klass; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + GST_FIXME ("suspend for dynamic pipelines needs fixing"); + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status != GST_RTSP_MEDIA_STATUS_PREPARED) + goto not_prepared; + + /* don't attempt to suspend when something is busy */ + if (priv->n_active > 0) + goto done; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + if (klass->suspend) { + if (!klass->suspend (media)) + goto suspend_failed; + } + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_SUSPENDED); done: g_rec_mutex_unlock (&priv->state_lock); @@ -2725,35 +2754,21 @@ not_prepared: GST_WARNING ("media %p was not prepared", media); return FALSE; } -state_failed: +suspend_failed: { g_rec_mutex_unlock (&priv->state_lock); gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); - GST_WARNING ("failed changing pipeline's state for media %p", media); + GST_WARNING ("failed to suspend media %p", media); return FALSE; } } -/** - * gst_rtsp_media_unsuspend: - * @media: a #GstRTSPMedia - * - * Unsuspend @media if it was in a suspended state. This method does nothing - * when the media was not in the suspended state. - * - * Returns: %TRUE on success. - */ +/* call with state_lock */ gboolean -gst_rtsp_media_unsuspend (GstRTSPMedia * media) +default_unsuspend (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv = media->priv; - g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); - - g_rec_mutex_lock (&priv->state_lock); - if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED) - goto done; - switch (priv->suspend_mode) { case GST_RTSP_SUSPEND_MODE_NONE: gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_PREPARED); @@ -2776,17 +2791,13 @@ gst_rtsp_media_unsuspend (GstRTSPMedia * media) default: break; } -done: - g_rec_mutex_unlock (&priv->state_lock); return TRUE; /* ERRORS */ start_failed: { - g_rec_mutex_unlock (&priv->state_lock); GST_WARNING ("failed to preroll pipeline"); - gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); return FALSE; } preroll_failed: @@ -2796,6 +2807,48 @@ preroll_failed: } } +/** + * gst_rtsp_media_unsuspend: + * @media: a #GstRTSPMedia + * + * Unsuspend @media if it was in a suspended state. This method does nothing + * when the media was not in the suspended state. + * + * Returns: %TRUE on success. + */ +gboolean +gst_rtsp_media_unsuspend (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstRTSPMediaClass *klass; + + g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); + + g_rec_mutex_lock (&priv->state_lock); + if (priv->status != GST_RTSP_MEDIA_STATUS_SUSPENDED) + goto done; + + klass = GST_RTSP_MEDIA_GET_CLASS (media); + if (klass->unsuspend) { + if (!klass->unsuspend (media)) + goto unsuspend_failed; + } + +done: + g_rec_mutex_unlock (&priv->state_lock); + + return TRUE; + + /* ERRORS */ +unsuspend_failed: + { + g_rec_mutex_unlock (&priv->state_lock); + GST_WARNING ("failed to unsuspend media %p", media); + gst_rtsp_media_set_status (media, GST_RTSP_MEDIA_STATUS_ERROR); + return FALSE; + } +} + /* must be called with state-lock */ static void media_set_pipeline_state_locked (GstRTSPMedia * media, GstState state) diff --git a/gst/rtsp-server/rtsp-media.h b/gst/rtsp-server/rtsp-media.h index 01df74dfcc..53047595fe 100644 --- a/gst/rtsp-server/rtsp-media.h +++ b/gst/rtsp-server/rtsp-media.h @@ -110,6 +110,12 @@ struct _GstRTSPMedia { * in case of NO_PREROLL elements). * @unprepare: the default implementation sets the pipeline's state * to GST_STATE_NULL and removes all elements. + * @suspend: the default implementation sets the pipeline's state to + * GST_STATE_NULL GST_STATE_PAUSED depending on the selected + * suspend mode. + * @unsuspend: the default implementation reverts the suspend operation. + * The pipeline will be prerolled again if it's state was + * set to GST_STATE_NULL in suspend. * @convert_range: convert a range to the given unit * @query_position: query the current posision in the pipeline * @query_stop: query when playback will stop @@ -123,6 +129,8 @@ struct _GstRTSPMediaClass { gboolean (*handle_message) (GstRTSPMedia *media, GstMessage *message); gboolean (*prepare) (GstRTSPMedia *media, GstRTSPThread *thread); gboolean (*unprepare) (GstRTSPMedia *media); + gboolean (*suspend) (GstRTSPMedia *media); + gboolean (*unsuspend) (GstRTSPMedia *media); gboolean (*convert_range) (GstRTSPMedia *media, GstRTSPTimeRange *range, GstRTSPRangeUnit unit); gboolean (*query_position) (GstRTSPMedia *media, gint64 *position);