/* UNIX (ntp) time of last SR sync used */
guint64 last_unix;
+
+ /* list of extra elements */
+ GList *elements;
};
/* signals and args */
SIGNAL_REQUEST_RTCP_ENCODER,
SIGNAL_REQUEST_RTCP_DECODER,
+ SIGNAL_NEW_JITTERBUFFER,
+
LAST_SIGNAL
};
}
}
+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 */
if (!(demux = gst_element_factory_make ("rtpptdemux", NULL)))
goto no_demux;
-
stream = g_new0 (GstRtpBinStream, 1);
stream->ssrc = ssrc;
stream->bin = rtpbin;
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);
* 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),
* 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),
* 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),
* 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),
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",
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;
}
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;
}
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");
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");
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);
}
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:
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;
}
}
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");
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);
}
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:
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;
}
}
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);
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 */
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);
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;
}
}
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);
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);
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;
}
}