rtpbin: add Since tags
[platform/upstream/gst-plugins-good.git] / gst / rtpmanager / gstrtpbin.c
index b066b16..b2b5803 100644 (file)
@@ -227,6 +227,9 @@ struct _GstRtpBinPrivate
 
   /* UNIX (ntp) time of last SR sync used */
   guint64 last_unix;
+
+  /* list of extra elements */
+  GList *elements;
 };
 
 /* signals and args */
@@ -254,6 +257,8 @@ enum
   SIGNAL_REQUEST_RTCP_ENCODER,
   SIGNAL_REQUEST_RTCP_DECODER,
 
+  SIGNAL_NEW_JITTERBUFFER,
+
   LAST_SIGNAL
 };
 
@@ -666,10 +671,49 @@ no_demux:
   }
 }
 
+static gboolean
+bin_manage_element (GstRtpBin * bin, GstElement * element)
+{
+  GstRtpBinPrivate *priv = bin->priv;
+
+  if (g_list_find (priv->elements, element)) {
+    GST_DEBUG_OBJECT (bin, "requested element %p already in bin", element);
+  } else {
+    GST_DEBUG_OBJECT (bin, "adding requested element %p", element);
+    if (!gst_bin_add (GST_BIN_CAST (bin), element))
+      goto add_failed;
+    if (!gst_element_sync_state_with_parent (element))
+      GST_WARNING_OBJECT (bin, "unable to sync element state with rtpbin");
+  }
+  /* we add the element multiple times, each we need an equal number of
+   * removes to really remove the element from the bin */
+  priv->elements = g_list_prepend (priv->elements, element);
+
+  return TRUE;
+
+  /* ERRORS */
+add_failed:
+  {
+    GST_WARNING_OBJECT (bin, "unable to add element");
+    return FALSE;
+  }
+}
+
 static void
 remove_bin_element (GstElement * element, GstRtpBin * bin)
 {
-  gst_bin_remove (GST_BIN_CAST (bin), element);
+  GstRtpBinPrivate *priv = bin->priv;
+  GList *find;
+
+  find = g_list_find (priv->elements, element);
+  if (find) {
+    priv->elements = g_list_delete_link (priv->elements, find);
+
+    if (!g_list_find (priv->elements, element))
+      gst_bin_remove (GST_BIN_CAST (bin), element);
+    else
+      gst_object_unref (element);
+  }
 }
 
 /* called with RTP_BIN_LOCK */
@@ -1450,7 +1494,6 @@ create_stream (GstRtpBinSession * session, guint32 ssrc)
     if (!(demux = gst_element_factory_make ("rtpptdemux", NULL)))
       goto no_demux;
 
-
   stream = g_new0 (GstRtpBinStream, 1);
   stream->ssrc = ssrc;
   stream->bin = rtpbin;
@@ -1481,6 +1524,9 @@ create_stream (GstRtpBinSession * session, guint32 ssrc)
   g_object_set (buffer, "mode", rtpbin->buffer_mode, NULL);
   g_object_set (buffer, "do-retransmission", rtpbin->do_retransmission, NULL);
 
+  g_signal_emit (rtpbin, gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER], 0,
+      buffer, session->id, ssrc);
+
   if (!rtpbin->ignore_pt)
     gst_bin_add (GST_BIN_CAST (rtpbin), demux);
   gst_bin_add (GST_BIN_CAST (rtpbin), buffer);
@@ -1859,6 +1905,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
    * element will be added to the bin if not previously added.
    *
    * If no handler is connected, no encoder will be used.
+   *
+   * Since: 1.4
    */
   gst_rtp_bin_signals[SIGNAL_REQUEST_RTP_ENCODER] =
       g_signal_new ("request-rtp-encoder", G_TYPE_FROM_CLASS (klass),
@@ -1875,6 +1923,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
    * element will be added to the bin if not previously added.
    *
    * If no handler is connected, no encoder will be used.
+   *
+   * Since: 1.4
    */
   gst_rtp_bin_signals[SIGNAL_REQUEST_RTP_DECODER] =
       g_signal_new ("request-rtp-decoder", G_TYPE_FROM_CLASS (klass),
@@ -1891,6 +1941,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
    * element will be added to the bin if not previously added.
    *
    * If no handler is connected, no encoder will be used.
+   *
+   * Since: 1.4
    */
   gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_ENCODER] =
       g_signal_new ("request-rtcp-encoder", G_TYPE_FROM_CLASS (klass),
@@ -1907,6 +1959,8 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
    * element will be added to the bin if not previously added.
    *
    * If no handler is connected, no encoder will be used.
+   *
+   * Since: 1.4
    */
   gst_rtp_bin_signals[SIGNAL_REQUEST_RTCP_DECODER] =
       g_signal_new ("request-rtcp-decoder", G_TYPE_FROM_CLASS (klass),
@@ -1914,6 +1968,24 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
           request_rtcp_decoder), _gst_element_accumulator, NULL,
       g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
 
+  /**
+   * GstRtpBin::new-jitterbuffer:
+   * @rtpbin: the object which received the signal
+   * @jitterbuffer: the new jitterbuffer
+   * @session: the session
+   * @ssrc: the SSRC
+   *
+   * Notify that a new @jitterbuffer was created for @session and @ssrc.
+   * This signal can, for example, be used to configure @jitterbuffer.
+   *
+   * Since: 1.4
+   */
+  gst_rtp_bin_signals[SIGNAL_NEW_JITTERBUFFER] =
+      g_signal_new ("new-jitterbuffer", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
+          new_jitterbuffer), NULL, NULL, g_cclosure_marshal_generic,
+      G_TYPE_NONE, 3, GST_TYPE_ELEMENT, G_TYPE_UINT, G_TYPE_UINT);
+
   g_object_class_install_property (gobject_class, PROP_SDES,
       g_param_spec_boxed ("sdes", "SDES",
           "The SDES items of this session",
@@ -2532,31 +2604,21 @@ static GstElement *
 session_request_encoder (GstRtpBinSession * session, guint signal)
 {
   GstElement *encoder = NULL;
+  GstRtpBin *bin = session->bin;
 
-  g_signal_emit (session->bin, gst_rtp_bin_signals[signal], 0, session->id,
-      &encoder);
+  g_signal_emit (bin, gst_rtp_bin_signals[signal], 0, session->id, &encoder);
 
   if (encoder) {
-    if (g_slist_find (session->encoders, encoder)) {
-      GST_DEBUG_OBJECT (session->bin, "requested encoder %p already in bin",
-          encoder);
-    } else {
-      GST_DEBUG_OBJECT (session->bin, "adding requested encoder %p", encoder);
-      if (!gst_bin_add (GST_BIN_CAST (session->bin), encoder))
-        goto add_failed;
-      if (!gst_element_sync_state_with_parent (encoder))
-        GST_WARNING_OBJECT (session->bin,
-            "unable to sync encoder state with rtpbin");
-      session->encoders = g_slist_append (session->encoders, encoder);
-    }
+    if (!bin_manage_element (bin, encoder))
+      goto manage_failed;
+    session->encoders = g_slist_prepend (session->encoders, encoder);
   }
-
   return encoder;
 
   /* ERRORS */
-add_failed:
+manage_failed:
   {
-    GST_WARNING_OBJECT (session->bin, "unable to add encoder");
+    GST_WARNING_OBJECT (bin, "unable to manage encoder");
     gst_object_unref (encoder);
     return NULL;
   }
@@ -2566,31 +2628,21 @@ static GstElement *
 session_request_decoder (GstRtpBinSession * session, guint signal)
 {
   GstElement *decoder = NULL;
+  GstRtpBin *bin = session->bin;
 
-  g_signal_emit (session->bin, gst_rtp_bin_signals[signal], 0, session->id,
-      &decoder);
+  g_signal_emit (bin, gst_rtp_bin_signals[signal], 0, session->id, &decoder);
 
   if (decoder) {
-    if (g_slist_find (session->decoders, decoder)) {
-      GST_DEBUG_OBJECT (session->bin, "requested decoder %p already in bin",
-          decoder);
-    } else {
-      GST_DEBUG_OBJECT (session->bin, "adding requested decoder %p", decoder);
-      if (!gst_bin_add (GST_BIN_CAST (session->bin), decoder))
-        goto add_failed;
-      if (!gst_element_sync_state_with_parent (decoder))
-        GST_WARNING_OBJECT (session->bin,
-            "unable to sync decoder state with rtpbin");
-      session->decoders = g_slist_append (session->decoders, decoder);
-    }
+    if (!bin_manage_element (bin, decoder))
+      goto manage_failed;
+    session->decoders = g_slist_prepend (session->decoders, decoder);
   }
-
   return decoder;
 
   /* ERRORS */
-add_failed:
+manage_failed:
   {
-    GST_WARNING_OBJECT (session->bin, "unable to add decoder");
+    GST_WARNING_OBJECT (bin, "unable to manage decoder");
     gst_object_unref (decoder);
     return NULL;
   }
@@ -2895,7 +2947,7 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
       goto dec_link_failed;
   } else {
     GST_DEBUG_OBJECT (rtpbin, "no RTP decoder given");
-    decsink = session->recv_rtp_sink;
+    decsink = gst_object_ref (session->recv_rtp_sink);
   }
 
   GST_DEBUG_OBJECT (rtpbin, "getting RTP src pad");
@@ -2903,7 +2955,7 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
   session->recv_rtp_src =
       gst_element_get_static_pad (session->session, "recv_rtp_src");
   if (session->recv_rtp_src == NULL)
-    goto pad_failed;
+    goto src_pad_failed;
 
   GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTP sink pad");
   sinkdpad = gst_element_get_static_pad (session->demux, "sink");
@@ -2921,6 +2973,7 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
   GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
   session->recv_rtp_sink_ghost =
       gst_ghost_pad_new_from_template (name, decsink, templ);
+  gst_object_unref (decsink);
   gst_pad_set_active (session->recv_rtp_sink_ghost, TRUE);
   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->recv_rtp_sink_ghost);
 
@@ -2939,7 +2992,7 @@ create_error:
   }
 pad_failed:
   {
-    g_warning ("rtpbin: failed to get session pad");
+    g_warning ("rtpbin: failed to get session rtp_sink pad");
     return NULL;
   }
 dec_sink_failed:
@@ -2950,11 +3003,19 @@ dec_sink_failed:
 dec_src_failed:
   {
     g_warning ("rtpbin: failed to get decoder src pad for session %d", sessid);
+    gst_object_unref (decsink);
     return NULL;
   }
 dec_link_failed:
   {
     g_warning ("rtpbin: failed to link rtp decoder for session %d", sessid);
+    gst_object_unref (decsink);
+    return NULL;
+  }
+src_pad_failed:
+  {
+    g_warning ("rtpbin: failed to get session rtp_src pad");
+    gst_object_unref (decsink);
     return NULL;
   }
 }
@@ -3049,14 +3110,14 @@ create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
       goto dec_link_failed;
   } else {
     GST_DEBUG_OBJECT (rtpbin, "no RTCP decoder given");
-    decsink = session->recv_rtcp_sink;
+    decsink = gst_object_ref (session->recv_rtcp_sink);
   }
 
   /* get srcpad, link to SSRCDemux */
   GST_DEBUG_OBJECT (rtpbin, "getting sync src pad");
   session->sync_src = gst_element_get_static_pad (session->session, "sync_src");
   if (session->sync_src == NULL)
-    goto pad_failed;
+    goto src_pad_failed;
 
   GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTCP sink pad");
   sinkdpad = gst_element_get_static_pad (session->demux, "rtcp_sink");
@@ -3065,6 +3126,7 @@ create_recv_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ,
 
   session->recv_rtcp_sink_ghost =
       gst_ghost_pad_new_from_template (name, decsink, templ);
+  gst_object_unref (decsink);
   gst_pad_set_active (session->recv_rtcp_sink_ghost, TRUE);
   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin),
       session->recv_rtcp_sink_ghost);
@@ -3084,7 +3146,7 @@ create_error:
   }
 pad_failed:
   {
-    g_warning ("rtpbin: failed to get session pad");
+    g_warning ("rtpbin: failed to get session rtcp_sink pad");
     return NULL;
   }
 dec_sink_failed:
@@ -3095,11 +3157,19 @@ dec_sink_failed:
 dec_src_failed:
   {
     g_warning ("rtpbin: failed to get decoder src pad for session %d", sessid);
+    gst_object_unref (decsink);
     return NULL;
   }
 dec_link_failed:
   {
     g_warning ("rtpbin: failed to link rtcp decoder for session %d", sessid);
+    gst_object_unref (decsink);
+    return NULL;
+  }
+src_pad_failed:
+  {
+    g_warning ("rtpbin: failed to get session sync_src pad");
+    gst_object_unref (decsink);
     return NULL;
   }
 }
@@ -3187,12 +3257,12 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
     encsrc = gst_element_get_static_pad (encoder, ename);
     g_free (ename);
 
-    if (encsink == NULL)
-      goto enc_sink_failed;
-
     if (encsrc == NULL)
       goto enc_src_failed;
 
+    if (encsink == NULL)
+      goto enc_sink_failed;
+
     ret = gst_pad_link (session->send_rtp_src, encsink);
     gst_object_unref (encsink);
 
@@ -3200,7 +3270,7 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
       goto enc_link_failed;
   } else {
     GST_DEBUG_OBJECT (rtpbin, "no RTP encoder given");
-    encsrc = session->send_rtp_src;
+    encsrc = gst_object_ref (session->send_rtp_src);
   }
 
   /* ghost the new source pad */
@@ -3209,6 +3279,7 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
   templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%u");
   session->send_rtp_src_ghost =
       gst_ghost_pad_new_from_template (gname, encsrc, templ);
+  gst_object_unref (encsrc);
   gst_pad_set_active (session->send_rtp_src_ghost, TRUE);
   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_src_ghost);
   g_free (gname);
@@ -3236,19 +3307,21 @@ no_srcpad:
     g_warning ("rtpbin: failed to get rtp source pad for session %d", sessid);
     return NULL;
   }
-enc_sink_failed:
+enc_src_failed:
   {
-    g_warning ("rtpbin: failed to get encoder sink pad for session %d", sessid);
+    g_warning ("rtpbin: failed to get encoder src pad for session %d", sessid);
     return NULL;
   }
-enc_src_failed:
+enc_sink_failed:
   {
-    g_warning ("rtpbin: failed to get encoder src pad for session %d", sessid);
+    g_warning ("rtpbin: failed to get encoder sink pad for session %d", sessid);
+    gst_object_unref (encsrc);
     return NULL;
   }
 enc_link_failed:
   {
     g_warning ("rtpbin: failed to link rtp encoder for session %d", sessid);
+    gst_object_unref (encsrc);
     return NULL;
   }
 }
@@ -3325,12 +3398,12 @@ create_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
     encsrc = gst_element_get_static_pad (encoder, ename);
     g_free (ename);
 
-    if (encsink == NULL)
-      goto enc_sink_failed;
-
     if (encsrc == NULL)
       goto enc_src_failed;
 
+    if (encsink == NULL)
+      goto enc_sink_failed;
+
     ret = gst_pad_link (session->send_rtcp_src, encsink);
     gst_object_unref (encsink);
 
@@ -3338,11 +3411,12 @@ create_rtcp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
       goto enc_link_failed;
   } else {
     GST_DEBUG_OBJECT (rtpbin, "no RTCP encoder given");
-    encsrc = session->send_rtcp_src;
+    encsrc = gst_object_ref (session->send_rtcp_src);
   }
 
   session->send_rtcp_src_ghost =
       gst_ghost_pad_new_from_template (name, encsrc, templ);
+  gst_object_unref (encsrc);
   gst_pad_set_active (session->send_rtcp_src_ghost, TRUE);
   gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtcp_src_ghost);
 
@@ -3364,19 +3438,21 @@ pad_failed:
     g_warning ("rtpbin: failed to get rtcp pad for session %d", sessid);
     return NULL;
   }
-enc_sink_failed:
+enc_src_failed:
   {
-    g_warning ("rtpbin: failed to get encoder sink pad for session %d", sessid);
+    g_warning ("rtpbin: failed to get encoder src pad for session %d", sessid);
     return NULL;
   }
-enc_src_failed:
+enc_sink_failed:
   {
-    g_warning ("rtpbin: failed to get encoder src pad for session %d", sessid);
+    g_warning ("rtpbin: failed to get encoder sink pad for session %d", sessid);
+    gst_object_unref (encsrc);
     return NULL;
   }
 enc_link_failed:
   {
     g_warning ("rtpbin: failed to link rtcp encoder for session %d", sessid);
+    gst_object_unref (encsrc);
     return NULL;
   }
 }