rtsp-media: Don't set the transport mode based on what elements we find
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-media.c
index 9b64569..4ac89b1 100644 (file)
@@ -101,7 +101,7 @@ struct _GstRTSPMediaPrivate
   guint buffer_size;
   GstRTSPAddressPool *pool;
   gboolean blocked;
-  gboolean record;
+  GstRTSPTransportMode transport_mode;
 
   GstElement *element;
   GRecMutex state_lock;         /* locking order: state lock, lock */
@@ -137,6 +137,7 @@ struct _GstRTSPMediaPrivate
 
   GList *payloads;              /* protected by lock */
   GstClockTime rtx_time;        /* protected by lock */
+  guint latency;                /* protected by lock */
 };
 
 #define DEFAULT_SHARED          FALSE
@@ -148,7 +149,8 @@ struct _GstRTSPMediaPrivate
 #define DEFAULT_EOS_SHUTDOWN    FALSE
 #define DEFAULT_BUFFER_SIZE     0x80000
 #define DEFAULT_TIME_PROVIDER   FALSE
-#define DEFAULT_RECORD          FALSE
+#define DEFAULT_LATENCY         200
+#define DEFAULT_TRANSPORT_MODE  GST_RTSP_TRANSPORT_MODE_PLAY
 
 /* define to dump received RTCP packets */
 #undef DUMP_STATS
@@ -165,7 +167,8 @@ enum
   PROP_BUFFER_SIZE,
   PROP_ELEMENT,
   PROP_TIME_PROVIDER,
-  PROP_RECORD,
+  PROP_LATENCY,
+  PROP_TRANSPORT_MODE,
   PROP_LAST
 };
 
@@ -212,7 +215,6 @@ static guint gst_rtsp_media_signals[SIGNAL_LAST] = { 0 };
 
 #define C_ENUM(v) ((gint) v)
 
-#define GST_TYPE_RTSP_SUSPEND_MODE (gst_rtsp_suspend_mode_get_type())
 GType
 gst_rtsp_suspend_mode_get_type (void)
 {
@@ -233,6 +235,27 @@ gst_rtsp_suspend_mode_get_type (void)
   return (GType) id;
 }
 
+#define C_FLAGS(v) ((guint) v)
+
+GType
+gst_rtsp_transport_mode_get_type (void)
+{
+  static gsize id = 0;
+  static const GFlagsValue values[] = {
+    {C_FLAGS (GST_RTSP_TRANSPORT_MODE_PLAY), "GST_RTSP_TRANSPORT_MODE_PLAY",
+        "play"},
+    {C_FLAGS (GST_RTSP_TRANSPORT_MODE_RECORD), "GST_RTSP_TRANSPORT_MODE_RECORD",
+        "record"},
+    {0, NULL, NULL}
+  };
+
+  if (g_once_init_enter (&id)) {
+    GType tmp = g_flags_register_static ("GstRTSPTransportMode", values);
+    g_once_init_leave (&id, tmp);
+  }
+  return (GType) id;
+}
+
 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
 
 static void
@@ -293,10 +316,16 @@ gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
           "Use a NetTimeProvider for clients",
           DEFAULT_TIME_PROVIDER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-  g_object_class_install_property (gobject_class, PROP_RECORD,
-      g_param_spec_boolean ("record", "Record",
+  g_object_class_install_property (gobject_class, PROP_LATENCY,
+      g_param_spec_uint ("latency", "Latency",
+          "Latency used for receiving media in milliseconds", 0, G_MAXUINT,
+          DEFAULT_BUFFER_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_TRANSPORT_MODE,
+      g_param_spec_flags ("transport-mode", "Transport Mode",
           "If this media pipeline can be used for PLAY or RECORD",
-          DEFAULT_RECORD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+          GST_TYPE_RTSP_TRANSPORT_MODE, DEFAULT_TRANSPORT_MODE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
   gst_rtsp_media_signals[SIGNAL_NEW_STREAM] =
       g_signal_new ("new-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
@@ -364,7 +393,7 @@ gst_rtsp_media_init (GstRTSPMedia * media)
   priv->eos_shutdown = DEFAULT_EOS_SHUTDOWN;
   priv->buffer_size = DEFAULT_BUFFER_SIZE;
   priv->time_provider = DEFAULT_TIME_PROVIDER;
-  priv->record = DEFAULT_RECORD;
+  priv->transport_mode = DEFAULT_TRANSPORT_MODE;
 }
 
 static void
@@ -435,8 +464,11 @@ gst_rtsp_media_get_property (GObject * object, guint propid,
     case PROP_TIME_PROVIDER:
       g_value_set_boolean (value, gst_rtsp_media_is_time_provider (media));
       break;
-    case PROP_RECORD:
-      g_value_set_boolean (value, gst_rtsp_media_is_record (media));
+    case PROP_LATENCY:
+      g_value_set_uint (value, gst_rtsp_media_get_latency (media));
+      break;
+    case PROP_TRANSPORT_MODE:
+      g_value_set_flags (value, gst_rtsp_media_get_transport_mode (media));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
@@ -478,8 +510,11 @@ gst_rtsp_media_set_property (GObject * object, guint propid,
     case PROP_TIME_PROVIDER:
       gst_rtsp_media_use_time_provider (media, g_value_get_boolean (value));
       break;
-    case PROP_RECORD:
-      gst_rtsp_media_set_record (media, g_value_get_boolean (value));
+    case PROP_LATENCY:
+      gst_rtsp_media_set_latency (media, g_value_get_uint (value));
+      break;
+    case PROP_TRANSPORT_MODE:
+      gst_rtsp_media_set_transport_mode (media, g_value_get_flags (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propid, pspec);
@@ -1182,6 +1217,56 @@ gst_rtsp_media_get_retransmission_time (GstRTSPMedia * media)
 }
 
 /**
+ * gst_rtsp_media_set_latncy:
+ * @media: a #GstRTSPMedia
+ * @latency: latency in milliseconds
+ *
+ * Configure the latency used for receiving media.
+ */
+void
+gst_rtsp_media_set_latency (GstRTSPMedia * media, guint latency)
+{
+  GstRTSPMediaPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_MEDIA (media));
+
+  GST_LOG_OBJECT (media, "set latency %ums", latency);
+
+  priv = media->priv;
+
+  g_mutex_lock (&priv->lock);
+  priv->latency = latency;
+  if (priv->rtpbin)
+    g_object_set (priv->rtpbin, "latency", latency, NULL);
+  g_mutex_unlock (&priv->lock);
+}
+
+/**
+ * gst_rtsp_media_get_latency:
+ * @media: a #GstRTSPMedia
+ *
+ * Get the latency that is used for receiving media.
+ *
+ * Returns: latency in milliseconds
+ */
+guint
+gst_rtsp_media_get_latency (GstRTSPMedia * media)
+{
+  GstRTSPMediaPrivate *priv;
+  guint res;
+
+  g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
+
+  priv = media->priv;
+
+  g_mutex_unlock (&priv->lock);
+  res = priv->latency;
+  g_mutex_unlock (&priv->lock);
+
+  return res;
+}
+
+/**
  * gst_rtsp_media_use_time_provider:
  * @media: a #GstRTSPMedia
  * @time_provider: if a #GstNetTimeProvider should be used
@@ -1341,6 +1426,7 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media)
   GstPad *pad;
   gint i;
   gboolean have_elem;
+  GstRTSPTransportMode mode = 0;
 
   g_return_if_fail (GST_IS_RTSP_MEDIA (media));
 
@@ -1365,6 +1451,7 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media)
       gst_object_unref (elem);
 
       have_elem = TRUE;
+      mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
     }
     g_free (name);
 
@@ -1378,6 +1465,7 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media)
       g_mutex_unlock (&priv->lock);
 
       have_elem = TRUE;
+      mode |= GST_RTSP_TRANSPORT_MODE_PLAY;
     }
     g_free (name);
 
@@ -1393,9 +1481,16 @@ gst_rtsp_media_collect_streams (GstRTSPMedia * media)
       gst_object_unref (elem);
 
       have_elem = TRUE;
+      mode |= GST_RTSP_TRANSPORT_MODE_RECORD;
     }
     g_free (name);
   }
+
+  if (have_elem) {
+    if (priv->transport_mode != mode)
+      GST_WARNING ("found different mode than expected (0x%02x != 0x%02d)",
+          priv->transport_mode, mode);
+  }
 }
 
 /**
@@ -1770,7 +1865,7 @@ gst_rtsp_media_seek (GstRTSPMedia * media, GstRTSPTimeRange * range)
     goto not_prepared;
 
   /* Update the seekable state of the pipeline in case it changed */
-  if (gst_rtsp_media_is_record (media)) {
+  if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
     /* TODO: Seeking for RECORD? */
     priv->seekable = FALSE;
   } else {
@@ -1968,7 +2063,7 @@ default_handle_message (GstRTSPMedia * media, GstMessage * message)
       GST_DEBUG ("%p: went from %s to %s (pending %s)", media,
           gst_element_state_get_name (old), gst_element_state_get_name (new),
           gst_element_state_get_name (pending));
-      if (gst_rtsp_media_is_record (media)
+      if ((priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)
           && old == GST_STATE_READY && new == GST_STATE_PAUSED) {
         GST_INFO ("%p: went to PAUSED, prepared now", media);
         collect_media_stats (media);
@@ -2283,7 +2378,7 @@ start_preroll (GstRTSPMedia * media)
        * seeking query in preroll instead */
       priv->seekable = FALSE;
       priv->is_live = TRUE;
-      if (!gst_rtsp_media_is_record (media)) {
+      if (!(priv->transport_mode & GST_RTSP_TRANSPORT_MODE_RECORD)) {
         /* start blocked  to make sure nothing goes to the sink */
         media_streams_set_blocked (media, TRUE);
       }
@@ -2408,6 +2503,8 @@ default_prepare (GstRTSPMedia * media, GstRTSPThread * thread)
   if (priv->rtpbin != NULL) {
     gboolean success = TRUE;
 
+    g_object_set (priv->rtpbin, "latency", priv->latency, NULL);
+
     if (klass->setup_rtpbin)
       success = klass->setup_rtpbin (media, priv->rtpbin);
 
@@ -3875,15 +3972,15 @@ error_status:
 }
 
 /**
- * gst_rtsp_media_set_record:
+ * gst_rtsp_media_set_transport_mode:
  * @media: a #GstRTSPMedia
- * @record: the new value
+ * @mode: the new value
  *
- * Set or unset if the pipeline for @media can be used for PLAY or RECORD
- * methods.
+ * Sets if the media pipeline can work in PLAY or RECORD mode
  */
 void
-gst_rtsp_media_set_record (GstRTSPMedia * media, gboolean record)
+gst_rtsp_media_set_transport_mode (GstRTSPMedia * media,
+    GstRTSPTransportMode mode)
 {
   GstRTSPMediaPrivate *priv;
 
@@ -3892,30 +3989,30 @@ gst_rtsp_media_set_record (GstRTSPMedia * media, gboolean record)
   priv = media->priv;
 
   g_mutex_lock (&priv->lock);
-  priv->record = record;
+  priv->transport_mode = mode;
   g_mutex_unlock (&priv->lock);
 }
 
 /**
- * gst_rtsp_media_is_record:
+ * gst_rtsp_media_get_transport_mode:
  * @media: a #GstRTSPMedia
  *
  * Check if the pipeline for @media can be used for PLAY or RECORD methods.
  *
- * Returns: %TRUE if the media can be record between clients.
+ * Returns: The transport mode.
  */
-gboolean
-gst_rtsp_media_is_record (GstRTSPMedia * media)
+GstRTSPTransportMode
+gst_rtsp_media_get_transport_mode (GstRTSPMedia * media)
 {
   GstRTSPMediaPrivate *priv;
-  gboolean res;
+  GstRTSPTransportMode res;
 
   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), FALSE);
 
   priv = media->priv;
 
   g_mutex_lock (&priv->lock);
-  res = priv->record;
+  res = priv->transport_mode;
   g_mutex_unlock (&priv->lock);
 
   return res;