From 0fb7922e9bcb6485fa5404412846685cae216e3a Mon Sep 17 00:00:00 2001 From: Ognyan Tonchev Date: Wed, 14 May 2014 09:31:31 +0200 Subject: [PATCH] media: Make suspend()/unsuspend() virtual Fixes https://bugzilla.gnome.org/show_bug.cgi?id=730109 --- gst/rtsp-server/rtsp-media.c | 139 ++++++++++++++++++++++++++++++------------- gst/rtsp-server/rtsp-media.h | 8 +++ 2 files changed, 104 insertions(+), 43 deletions(-) diff --git a/gst/rtsp-server/rtsp-media.c b/gst/rtsp-server/rtsp-media.c index f1b9cb2..5687a72 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,6 +2665,46 @@ no_setup_sdp: } } +/* call with state_lock */ +gboolean +default_suspend (GstRTSPMedia * media) +{ + GstRTSPMediaPrivate *priv = media->priv; + GstStateChangeReturn ret; + + switch (priv->suspend_mode) { + case GST_RTSP_SUSPEND_MODE_NONE: + GST_DEBUG ("media %p no suspend", media); + break; + case GST_RTSP_SUSPEND_MODE_PAUSE: + GST_DEBUG ("media %p suspend to PAUSED", media); + ret = set_target_state (media, GST_STATE_PAUSED, TRUE); + if (ret == GST_STATE_CHANGE_FAILURE) + goto state_failed; + break; + case GST_RTSP_SUSPEND_MODE_RESET: + GST_DEBUG ("media %p suspend to NULL", media); + ret = set_target_state (media, GST_STATE_NULL, TRUE); + if (ret == GST_STATE_CHANGE_FAILURE) + goto state_failed; + break; + 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 @@ -2677,7 +2721,7 @@ gboolean gst_rtsp_media_suspend (GstRTSPMedia * media) { GstRTSPMediaPrivate *priv = media->priv; - GstStateChangeReturn ret; + GstRTSPMediaClass *klass; g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE); @@ -2691,27 +2735,12 @@ gst_rtsp_media_suspend (GstRTSPMedia * media) if (priv->n_active > 0) goto done; - switch (priv->suspend_mode) { - case GST_RTSP_SUSPEND_MODE_NONE: - GST_DEBUG ("media %p no suspend", media); - break; - case GST_RTSP_SUSPEND_MODE_PAUSE: - GST_DEBUG ("media %p suspend to PAUSED", media); - ret = set_target_state (media, GST_STATE_PAUSED, TRUE); - if (ret == GST_STATE_CHANGE_FAILURE) - goto state_failed; - break; - case GST_RTSP_SUSPEND_MODE_RESET: - GST_DEBUG ("media %p suspend to NULL", media); - ret = set_target_state (media, GST_STATE_NULL, TRUE); - if (ret == GST_STATE_CHANGE_FAILURE) - goto state_failed; - break; - default: - break; + klass = GST_RTSP_MEDIA_GET_CLASS (media); + if (klass->suspend) { + if (!klass->suspend (media)) + goto suspend_failed; } - /* let the streams do the state changes freely, if any */ - media_streams_set_blocked (media, FALSE); + 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 01df74d..5304759 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); -- 2.7.4