media: Make suspend()/unsuspend() virtual
authorOgnyan Tonchev <ognyan@axis.com>
Wed, 14 May 2014 07:31:31 +0000 (09:31 +0200)
committerWim Taymans <wtaymans@redhat.com>
Thu, 15 May 2014 13:42:18 +0000 (15:42 +0200)
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=730109

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

index f1b9cb2..5687a72 100644 (file)
@@ -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)
index 01df74d..5304759 100644 (file)
@@ -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);