rtsp-stream: Always unref return value of gst_object_get_parent()
[platform/upstream/gstreamer.git] / gst / rtsp-server / rtsp-stream-transport.c
index 40452c2..0498830 100644 (file)
 /**
  * SECTION:rtsp-stream-transport
  * @short_description: A media stream transport configuration
- * @see_also: #GstRTSPStream
+ * @see_also: #GstRTSPStream, #GstRTSPSessionMedia
  *
- * Last reviewed on 2013-07-11 (1.0.0)
+ * The #GstRTSPStreamTransport configures the transport used by a
+ * #GstRTSPStream. It is usually manages by a #GstRTSPSessionMedia object.
+ *
+ * With gst_rtsp_stream_transport_set_callbacks(), callbacks can be configured
+ * to handle the RTP and RTCP packets from the stream, for example when they
+ * need to be sent over TCP.
+ *
+ * With  gst_rtsp_stream_transport_set_active() the transports are added and
+ * removed from the stream.
+ *
+ * A #GstRTSPStream will call gst_rtsp_stream_transport_keep_alive() when RTCP
+ * is received from the client. It will also call
+ * gst_rtsp_stream_transport_set_timed_out() when a receiver has timed out.
+ *
+ * Last reviewed on 2013-07-16 (1.0.0)
  */
 
 #include <string.h>
@@ -48,6 +62,7 @@ struct _GstRTSPStreamTransportPrivate
   gboolean timed_out;
 
   GstRTSPTransport *transport;
+  GstRTSPUrl *url;
 
   GObject *rtpsource;
 };
@@ -103,9 +118,15 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
   gst_rtsp_stream_transport_set_callbacks (trans, NULL, NULL, NULL, NULL);
   gst_rtsp_stream_transport_set_keepalive (trans, NULL, NULL, NULL);
 
+  if (priv->stream)
+    g_object_unref (priv->stream);
+
   if (priv->transport)
     gst_rtsp_transport_free (priv->transport);
 
+  if (priv->url)
+    gst_rtsp_url_free (priv->url);
+
   G_OBJECT_CLASS (gst_rtsp_stream_transport_parent_class)->finalize (obj);
 }
 
@@ -117,7 +138,7 @@ gst_rtsp_stream_transport_finalize (GObject * obj)
  * Create a new #GstRTSPStreamTransport that can be used to manage
  * @stream with transport @tr.
  *
- * Returns: a new #GstRTSPStreamTransport
+ * Returns: (transfer full): a new #GstRTSPStreamTransport
  */
 GstRTSPStreamTransport *
 gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
@@ -131,6 +152,7 @@ gst_rtsp_stream_transport_new (GstRTSPStream * stream, GstRTSPTransport * tr)
   trans = g_object_new (GST_TYPE_RTSP_STREAM_TRANSPORT, NULL);
   priv = trans->priv;
   priv->stream = stream;
+  priv->stream = g_object_ref (priv->stream);
   priv->transport = tr;
 
   return trans;
@@ -157,8 +179,8 @@ gst_rtsp_stream_transport_get_stream (GstRTSPStreamTransport * trans)
  * @trans: a #GstRTSPStreamTransport
  * @send_rtp: (scope notified): a callback called when RTP should be sent
  * @send_rtcp: (scope notified): a callback called when RTCP should be sent
- * @user_data: user data passed to callbacks
- * @notify: called with the user_data when no longer needed.
+ * @user_data: (closure): user data passed to callbacks
+ * @notify: (allow-none): called with the user_data when no longer needed.
  *
  * Install callbacks that will be called when data for a stream should be sent
  * to a client. This is usually used when sending RTP/RTCP over TCP.
@@ -185,9 +207,9 @@ gst_rtsp_stream_transport_set_callbacks (GstRTSPStreamTransport * trans,
 /**
  * gst_rtsp_stream_transport_set_keepalive:
  * @trans: a #GstRTSPStreamTransport
- * @keep_alive: a callback called when the receiver is active
- * @user_data: user data passed to callback
- * @notify: called with the user_data when no longer needed.
+ * @keep_alive: (scope notified): a callback called when the receiver is active
+ * @user_data: (closure): user data passed to callback
+ * @notify: (allow-none): called with the user_data when no longer needed.
  *
  * Install callbacks that will be called when RTCP packets are received from the
  * receiver of @trans.
@@ -242,7 +264,7 @@ gst_rtsp_stream_transport_set_transport (GstRTSPStreamTransport * trans,
  * Get the transport configured in @trans.
  *
  * Returns: (transfer none): the transport configured in @trans. It remains
- *     valid for as long as @trans is valid.
+ * valid for as long as @trans is valid.
  */
 const GstRTSPTransport *
 gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans)
@@ -253,6 +275,103 @@ gst_rtsp_stream_transport_get_transport (GstRTSPStreamTransport * trans)
 }
 
 /**
+ * gst_rtsp_stream_transport_set_url:
+ * @trans: a #GstRTSPStreamTransport
+ * @url: (transfer none): a client #GstRTSPUrl
+ *
+ * Set @url as the client url.
+ */
+void
+gst_rtsp_stream_transport_set_url (GstRTSPStreamTransport * trans,
+    const GstRTSPUrl * url)
+{
+  GstRTSPStreamTransportPrivate *priv;
+
+  g_return_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans));
+
+  priv = trans->priv;
+
+  /* keep track of the transports in the stream. */
+  if (priv->url)
+    gst_rtsp_url_free (priv->url);
+  priv->url = (url ? gst_rtsp_url_copy (url) : NULL);
+}
+
+/**
+ * gst_rtsp_stream_transport_get_url:
+ * @trans: a #GstRTSPStreamTransport
+ *
+ * Get the url configured in @trans.
+ *
+ * Returns: (transfer none): the url configured in @trans. It remains
+ * valid for as long as @trans is valid.
+ */
+const GstRTSPUrl *
+gst_rtsp_stream_transport_get_url (GstRTSPStreamTransport * trans)
+{
+  g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
+
+  return trans->priv->url;
+}
+
+ /**
+ * gst_rtsp_stream_transport_get_rtpinfo:
+ * @trans: a #GstRTSPStreamTransport
+ * @start_time: a star time
+ *
+ * Get the RTP-Info string for @trans and @start_time.
+ *
+ * Returns: (transfer full) (nullable): the RTPInfo string for @trans
+ * and @start_time or %NULL when the RTP-Info could not be
+ * determined. g_free() after usage.
+ */
+gchar *
+gst_rtsp_stream_transport_get_rtpinfo (GstRTSPStreamTransport * trans,
+    GstClockTime start_time)
+{
+  GstRTSPStreamTransportPrivate *priv;
+  gchar *url_str;
+  GString *rtpinfo;
+  guint rtptime, seq, clock_rate;
+  GstClockTime running_time = GST_CLOCK_TIME_NONE;
+
+  g_return_val_if_fail (GST_IS_RTSP_STREAM_TRANSPORT (trans), NULL);
+
+  priv = trans->priv;
+
+  if (!gst_rtsp_stream_get_rtpinfo (priv->stream, &rtptime, &seq, &clock_rate,
+          &running_time))
+    return NULL;
+
+  GST_DEBUG ("RTP time %u, seq %u, rate %u, running-time %" GST_TIME_FORMAT,
+      rtptime, seq, clock_rate, GST_TIME_ARGS (running_time));
+
+  if (GST_CLOCK_TIME_IS_VALID (running_time)
+      && GST_CLOCK_TIME_IS_VALID (start_time)) {
+    if (running_time > start_time) {
+      rtptime -=
+          gst_util_uint64_scale_int (running_time - start_time, clock_rate,
+          GST_SECOND);
+    } else {
+      rtptime +=
+          gst_util_uint64_scale_int (start_time - running_time, clock_rate,
+          GST_SECOND);
+    }
+  }
+  GST_DEBUG ("RTP time %u, for start-time %" GST_TIME_FORMAT,
+      rtptime, GST_TIME_ARGS (start_time));
+
+  rtpinfo = g_string_new ("");
+
+  url_str = gst_rtsp_url_get_request_uri (trans->priv->url);
+  g_string_append_printf (rtpinfo, "url=%s;seq=%u;rtptime=%u",
+      url_str, seq, rtptime);
+  g_free (url_str);
+
+  return g_string_free (rtpinfo, FALSE);
+}
+
+/**
  * gst_rtsp_stream_transport_set_active:
  * @trans: a #GstRTSPStreamTransport
  * @active: new state of @trans
@@ -321,7 +440,7 @@ gst_rtsp_stream_transport_is_timed_out (GstRTSPStreamTransport * trans)
 /**
  * gst_rtsp_stream_transport_send_rtp:
  * @trans: a #GstRTSPStreamTransport
- * @buffer: a #GstBuffer
+ * @buffer: (transfer none): a #GstBuffer
  *
  * Send @buffer to the installed RTP callback for @trans.
  *
@@ -341,13 +460,16 @@ gst_rtsp_stream_transport_send_rtp (GstRTSPStreamTransport * trans,
         priv->send_rtp (buffer, priv->transport->interleaved.min,
         priv->user_data);
 
+  if (res)
+    gst_rtsp_stream_transport_keep_alive (trans);
+
   return res;
 }
 
 /**
  * gst_rtsp_stream_transport_send_rtcp:
  * @trans: a #GstRTSPStreamTransport
- * @buffer: a #GstBuffer
+ * @buffer: (transfer none): a #GstBuffer
  *
  * Send @buffer to the installed RTCP callback for @trans.
  *
@@ -367,6 +489,9 @@ gst_rtsp_stream_transport_send_rtcp (GstRTSPStreamTransport * trans,
         priv->send_rtcp (buffer, priv->transport->interleaved.max,
         priv->user_data);
 
+  if (res)
+    gst_rtsp_stream_transport_keep_alive (trans);
+
   return res;
 }
 
@@ -386,3 +511,35 @@ gst_rtsp_stream_transport_keep_alive (GstRTSPStreamTransport * trans)
   if (priv->keep_alive)
     priv->keep_alive (priv->ka_user_data);
 }
+
+/**
+ * gst_rtsp_stream_transport_recv_data:
+ * @trans: a #GstRTSPStreamTransport
+ * @channel: a channel
+ * @buffer: (transfer full): a #GstBuffer
+ *
+ * Receive @buffer on @channel @trans.
+ *
+ * Returns: a #GstFlowReturn. Returns GST_FLOW_NOT_LINKED when @channel is not
+ *    configured in the transport of @trans.
+ */
+GstFlowReturn
+gst_rtsp_stream_transport_recv_data (GstRTSPStreamTransport * trans,
+    guint channel, GstBuffer * buffer)
+{
+  GstRTSPStreamTransportPrivate *priv;
+  const GstRTSPTransport *tr;
+  GstFlowReturn res;
+
+  priv = trans->priv;
+  tr = priv->transport;
+
+  if (tr->interleaved.min == channel) {
+    res = gst_rtsp_stream_recv_rtp (priv->stream, buffer);
+  } else if (tr->interleaved.max == channel) {
+    res = gst_rtsp_stream_recv_rtcp (priv->stream, buffer);
+  } else {
+    res = GST_FLOW_NOT_LINKED;
+  }
+  return res;
+}