mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
rtpbin: add support for AUX sender and receiver
AUX elements are elements that can be inserted into the rtpbin pipeline right before or after 1 or more session elements. The AUX elements are essential for implementing functionality such as error correction (FEC) and retransmission (RTX). Fixes https://bugzilla.gnome.org/show_bug.cgi?id=711087
This commit is contained in:
parent
841f9ad050
commit
d08e05b4ef
2 changed files with 412 additions and 150 deletions
|
@ -259,6 +259,9 @@ enum
|
||||||
|
|
||||||
SIGNAL_NEW_JITTERBUFFER,
|
SIGNAL_NEW_JITTERBUFFER,
|
||||||
|
|
||||||
|
SIGNAL_REQUEST_AUX_SENDER,
|
||||||
|
SIGNAL_REQUEST_AUX_RECEIVER,
|
||||||
|
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1983,6 +1986,41 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass)
|
||||||
new_jitterbuffer), NULL, NULL, g_cclosure_marshal_generic,
|
new_jitterbuffer), NULL, NULL, g_cclosure_marshal_generic,
|
||||||
G_TYPE_NONE, 3, GST_TYPE_ELEMENT, G_TYPE_UINT, G_TYPE_UINT);
|
G_TYPE_NONE, 3, GST_TYPE_ELEMENT, G_TYPE_UINT, G_TYPE_UINT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstRtpBin::request-aux-sender:
|
||||||
|
* @rtpbin: the object which received the signal
|
||||||
|
* @session: the session
|
||||||
|
*
|
||||||
|
* Request an AUX sender element for the given @session. The AUX
|
||||||
|
* element will be added to the bin.
|
||||||
|
*
|
||||||
|
* If no handler is connected, no AUX element will be used.
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
|
gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_SENDER] =
|
||||||
|
g_signal_new ("request-aux-sender", G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
|
||||||
|
request_aux_sender), _gst_element_accumulator, NULL,
|
||||||
|
g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
|
||||||
|
/**
|
||||||
|
* GstRtpBin::request-aux-receiver:
|
||||||
|
* @rtpbin: the object which received the signal
|
||||||
|
* @session: the session
|
||||||
|
*
|
||||||
|
* Request an AUX receiver element for the given @session. The AUX
|
||||||
|
* element will be added to the bin.
|
||||||
|
*
|
||||||
|
* If no handler is connected, no AUX element will be used.
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
|
gst_rtp_bin_signals[SIGNAL_REQUEST_AUX_RECEIVER] =
|
||||||
|
g_signal_new ("request-aux-receiver", G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpBinClass,
|
||||||
|
request_aux_receiver), _gst_element_accumulator, NULL,
|
||||||
|
g_cclosure_marshal_generic, GST_TYPE_ELEMENT, 1, G_TYPE_UINT);
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_SDES,
|
g_object_class_install_property (gobject_class, PROP_SDES,
|
||||||
g_param_spec_boxed ("sdes", "SDES",
|
g_param_spec_boxed ("sdes", "SDES",
|
||||||
"The SDES items of this session",
|
"The SDES items of this session",
|
||||||
|
@ -2856,6 +2894,91 @@ no_stream:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session)
|
||||||
|
{
|
||||||
|
gchar *gname;
|
||||||
|
guint sessid = session->id;
|
||||||
|
GstPad *recv_rtp_sink;
|
||||||
|
GstElement *decoder;
|
||||||
|
GstElementClass *klass;
|
||||||
|
GstPadTemplate *templ;
|
||||||
|
|
||||||
|
/* get recv_rtp pad and store */
|
||||||
|
session->recv_rtp_sink =
|
||||||
|
gst_element_get_request_pad (session->session, "recv_rtp_sink");
|
||||||
|
if (session->recv_rtp_sink == NULL)
|
||||||
|
goto pad_failed;
|
||||||
|
|
||||||
|
g_signal_connect (session->recv_rtp_sink, "notify::caps",
|
||||||
|
(GCallback) caps_changed, session);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "requesting RTP decoder");
|
||||||
|
decoder = session_request_element (session, SIGNAL_REQUEST_RTP_DECODER);
|
||||||
|
if (decoder) {
|
||||||
|
GstPad *decsrc, *decsink;
|
||||||
|
GstPadLinkReturn ret;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "linking RTP decoder");
|
||||||
|
decsink = gst_element_get_static_pad (decoder, "rtp_sink");
|
||||||
|
if (decsink == NULL)
|
||||||
|
goto dec_sink_failed;
|
||||||
|
|
||||||
|
recv_rtp_sink = decsink;
|
||||||
|
|
||||||
|
decsrc = gst_element_get_static_pad (decoder, "rtp_src");
|
||||||
|
if (decsrc == NULL)
|
||||||
|
goto dec_src_failed;
|
||||||
|
|
||||||
|
ret = gst_pad_link (decsrc, session->recv_rtp_sink);
|
||||||
|
gst_object_unref (decsrc);
|
||||||
|
|
||||||
|
if (ret != GST_PAD_LINK_OK)
|
||||||
|
goto dec_link_failed;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "no RTP decoder given");
|
||||||
|
recv_rtp_sink = gst_object_ref (session->recv_rtp_sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
|
||||||
|
klass = GST_ELEMENT_GET_CLASS (rtpbin);
|
||||||
|
gname = g_strdup_printf ("recv_rtp_sink_%u", sessid);
|
||||||
|
templ = gst_element_class_get_pad_template (klass, "recv_rtp_sink_%u");
|
||||||
|
session->recv_rtp_sink_ghost =
|
||||||
|
gst_ghost_pad_new_from_template (gname, recv_rtp_sink, templ);
|
||||||
|
gst_object_unref (recv_rtp_sink);
|
||||||
|
gst_pad_set_active (session->recv_rtp_sink_ghost, TRUE);
|
||||||
|
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->recv_rtp_sink_ghost);
|
||||||
|
g_free (gname);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
pad_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get session recv_rtp_sink pad");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
dec_sink_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get decoder sink pad for session %d", sessid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
dec_src_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get decoder src pad for session %d", sessid);
|
||||||
|
gst_object_unref (recv_rtp_sink);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
dec_link_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to link rtp decoder for session %d", sessid);
|
||||||
|
gst_object_unref (recv_rtp_sink);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a pad for receiving RTP for the session in @name. Must be called with
|
/* Create a pad for receiving RTP for the session in @name. Must be called with
|
||||||
* RTP_BIN_LOCK.
|
* RTP_BIN_LOCK.
|
||||||
*/
|
*/
|
||||||
|
@ -2863,8 +2986,8 @@ static GstPad *
|
||||||
create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
||||||
{
|
{
|
||||||
guint sessid;
|
guint sessid;
|
||||||
GstElement *decoder;
|
GstElement *aux;
|
||||||
GstPad *sinkdpad, *decsink;
|
GstPad *recv_rtp_src;
|
||||||
GstRtpBinSession *session;
|
GstRtpBinSession *session;
|
||||||
|
|
||||||
/* first get the session number */
|
/* first get the session number */
|
||||||
|
@ -2887,69 +3010,61 @@ create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
||||||
if (session->recv_rtp_sink_ghost != NULL)
|
if (session->recv_rtp_sink_ghost != NULL)
|
||||||
return session->recv_rtp_sink_ghost;
|
return session->recv_rtp_sink_ghost;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "getting RTP sink pad");
|
/* setup the session sink pad */
|
||||||
/* get recv_rtp pad and store */
|
if (!complete_session_sink (rtpbin, session))
|
||||||
session->recv_rtp_sink =
|
goto session_sink_failed;
|
||||||
gst_element_get_request_pad (session->session, "recv_rtp_sink");
|
|
||||||
if (session->recv_rtp_sink == NULL)
|
|
||||||
goto pad_failed;
|
|
||||||
|
|
||||||
g_signal_connect (session->recv_rtp_sink, "notify::caps",
|
|
||||||
(GCallback) caps_changed, session);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "requesting RTP decoder");
|
|
||||||
decoder = session_request_element (session, SIGNAL_REQUEST_RTP_DECODER);
|
|
||||||
if (decoder) {
|
|
||||||
GstPad *decsrc;
|
|
||||||
GstPadLinkReturn ret;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "linking RTP decoder");
|
|
||||||
decsink = gst_element_get_static_pad (decoder, "rtp_sink");
|
|
||||||
decsrc = gst_element_get_static_pad (decoder, "rtp_src");
|
|
||||||
|
|
||||||
if (decsink == NULL)
|
|
||||||
goto dec_sink_failed;
|
|
||||||
|
|
||||||
if (decsrc == NULL)
|
|
||||||
goto dec_src_failed;
|
|
||||||
|
|
||||||
ret = gst_pad_link (decsrc, session->recv_rtp_sink);
|
|
||||||
gst_object_unref (decsrc);
|
|
||||||
|
|
||||||
if (ret != GST_PAD_LINK_OK)
|
|
||||||
goto dec_link_failed;
|
|
||||||
} else {
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "no RTP decoder given");
|
|
||||||
decsink = gst_object_ref (session->recv_rtp_sink);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "getting RTP src pad");
|
|
||||||
/* get srcpad, link to SSRCDemux */
|
|
||||||
session->recv_rtp_src =
|
session->recv_rtp_src =
|
||||||
gst_element_get_static_pad (session->session, "recv_rtp_src");
|
gst_element_get_static_pad (session->session, "recv_rtp_src");
|
||||||
if (session->recv_rtp_src == NULL)
|
if (session->recv_rtp_src == NULL)
|
||||||
goto src_pad_failed;
|
goto pad_failed;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTP sink pad");
|
/* find out if we need AUX elements or if we can go into the SSRC demuxer
|
||||||
sinkdpad = gst_element_get_static_pad (session->demux, "sink");
|
* directly */
|
||||||
GST_DEBUG_OBJECT (rtpbin, "linking demuxer RTP sink pad");
|
aux = session_request_element (session, SIGNAL_REQUEST_AUX_RECEIVER);
|
||||||
gst_pad_link_full (session->recv_rtp_src, sinkdpad,
|
if (aux) {
|
||||||
GST_PAD_LINK_CHECK_NOTHING);
|
gchar *pname;
|
||||||
gst_object_unref (sinkdpad);
|
GstPad *auxsink;
|
||||||
|
GstPadLinkReturn ret;
|
||||||
|
|
||||||
/* connect to the new-ssrc-pad signal of the SSRC demuxer */
|
GST_DEBUG_OBJECT (rtpbin, "linking AUX receiver");
|
||||||
session->demux_newpad_sig = g_signal_connect (session->demux,
|
|
||||||
"new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
|
|
||||||
session->demux_padremoved_sig = g_signal_connect (session->demux,
|
|
||||||
"removed-ssrc-pad", (GCallback) ssrc_demux_pad_removed, session);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "ghosting session sink pad");
|
pname = g_strdup_printf ("sink_%d", sessid);
|
||||||
session->recv_rtp_sink_ghost =
|
auxsink = gst_element_get_static_pad (aux, pname);
|
||||||
gst_ghost_pad_new_from_template (name, decsink, templ);
|
g_free (pname);
|
||||||
gst_object_unref (decsink);
|
if (auxsink == NULL)
|
||||||
gst_pad_set_active (session->recv_rtp_sink_ghost, TRUE);
|
goto aux_sink_failed;
|
||||||
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->recv_rtp_sink_ghost);
|
|
||||||
|
|
||||||
|
ret = gst_pad_link (session->recv_rtp_src, auxsink);
|
||||||
|
gst_object_unref (auxsink);
|
||||||
|
if (ret != GST_PAD_LINK_OK)
|
||||||
|
goto aux_link_failed;
|
||||||
|
|
||||||
|
/* this can be NULL when this AUX element is not to be linked to
|
||||||
|
* an SSRC demuxer */
|
||||||
|
pname = g_strdup_printf ("src_%d", sessid);
|
||||||
|
recv_rtp_src = gst_element_get_static_pad (aux, pname);
|
||||||
|
g_free (pname);
|
||||||
|
} else {
|
||||||
|
recv_rtp_src = gst_object_ref (session->recv_rtp_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recv_rtp_src) {
|
||||||
|
GstPad *sinkdpad;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "getting demuxer RTP sink pad");
|
||||||
|
sinkdpad = gst_element_get_static_pad (session->demux, "sink");
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "linking demuxer RTP sink pad");
|
||||||
|
gst_pad_link_full (recv_rtp_src, sinkdpad, GST_PAD_LINK_CHECK_NOTHING);
|
||||||
|
gst_object_unref (recv_rtp_src);
|
||||||
|
gst_object_unref (sinkdpad);
|
||||||
|
|
||||||
|
/* connect to the new-ssrc-pad signal of the SSRC demuxer */
|
||||||
|
session->demux_newpad_sig = g_signal_connect (session->demux,
|
||||||
|
"new-ssrc-pad", (GCallback) new_ssrc_pad_found, session);
|
||||||
|
session->demux_padremoved_sig = g_signal_connect (session->demux,
|
||||||
|
"removed-ssrc-pad", (GCallback) ssrc_demux_pad_removed, session);
|
||||||
|
}
|
||||||
return session->recv_rtp_sink_ghost;
|
return session->recv_rtp_sink_ghost;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
@ -2963,32 +3078,24 @@ create_error:
|
||||||
/* create_session already warned */
|
/* create_session already warned */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
session_sink_failed:
|
||||||
|
{
|
||||||
|
/* warning already done */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pad_failed:
|
pad_failed:
|
||||||
{
|
{
|
||||||
g_warning ("rtpbin: failed to get session rtp_sink pad");
|
g_warning ("rtpbin: failed to get session recv_rtp_src pad");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
dec_sink_failed:
|
aux_sink_failed:
|
||||||
{
|
{
|
||||||
g_warning ("rtpbin: failed to get decoder sink pad for session %d", sessid);
|
g_warning ("rtpbin: failed to get AUX sink pad for session %d", sessid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
dec_src_failed:
|
aux_link_failed:
|
||||||
{
|
{
|
||||||
g_warning ("rtpbin: failed to get decoder src pad for session %d", sessid);
|
g_warning ("rtpbin: failed to link AUX pad to 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;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3168,18 +3275,195 @@ remove_recv_rtcp (GstRtpBin * rtpbin, GstRtpBinSession * session)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
complete_session_src (GstRtpBin * rtpbin, GstRtpBinSession * session)
|
||||||
|
{
|
||||||
|
gchar *gname;
|
||||||
|
guint sessid = session->id;
|
||||||
|
GstPad *send_rtp_src;
|
||||||
|
GstElement *encoder;
|
||||||
|
GstElementClass *klass;
|
||||||
|
GstPadTemplate *templ;
|
||||||
|
|
||||||
|
/* get srcpad */
|
||||||
|
session->send_rtp_src =
|
||||||
|
gst_element_get_static_pad (session->session, "send_rtp_src");
|
||||||
|
if (session->send_rtp_src == NULL)
|
||||||
|
goto no_srcpad;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "getting RTP encoder");
|
||||||
|
encoder = session_request_element (session, SIGNAL_REQUEST_RTP_ENCODER);
|
||||||
|
if (encoder) {
|
||||||
|
gchar *ename;
|
||||||
|
GstPad *encsrc, *encsink;
|
||||||
|
GstPadLinkReturn ret;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "linking RTP encoder");
|
||||||
|
ename = g_strdup_printf ("rtp_src_%d", sessid);
|
||||||
|
encsrc = gst_element_get_static_pad (encoder, ename);
|
||||||
|
g_free (ename);
|
||||||
|
|
||||||
|
if (encsrc == NULL)
|
||||||
|
goto enc_src_failed;
|
||||||
|
|
||||||
|
send_rtp_src = encsrc;
|
||||||
|
|
||||||
|
ename = g_strdup_printf ("rtp_sink_%d", sessid);
|
||||||
|
encsink = gst_element_get_static_pad (encoder, ename);
|
||||||
|
g_free (ename);
|
||||||
|
if (encsink == NULL)
|
||||||
|
goto enc_sink_failed;
|
||||||
|
|
||||||
|
ret = gst_pad_link (session->send_rtp_src, encsink);
|
||||||
|
gst_object_unref (encsink);
|
||||||
|
|
||||||
|
if (ret != GST_PAD_LINK_OK)
|
||||||
|
goto enc_link_failed;
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (rtpbin, "no RTP encoder given");
|
||||||
|
send_rtp_src = gst_object_ref (session->send_rtp_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ghost the new source pad */
|
||||||
|
klass = GST_ELEMENT_GET_CLASS (rtpbin);
|
||||||
|
gname = g_strdup_printf ("send_rtp_src_%u", sessid);
|
||||||
|
templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%u");
|
||||||
|
session->send_rtp_src_ghost =
|
||||||
|
gst_ghost_pad_new_from_template (gname, send_rtp_src, templ);
|
||||||
|
gst_object_unref (send_rtp_src);
|
||||||
|
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);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_srcpad:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get rtp source pad for session %d", sessid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
enc_src_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get encoder src pad for session %d", sessid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
enc_sink_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get encoder sink pad for session %d", sessid);
|
||||||
|
gst_object_unref (send_rtp_src);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
enc_link_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to link rtp encoder for session %d", sessid);
|
||||||
|
gst_object_unref (send_rtp_src);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
setup_aux_sender_fold (const GValue * item, GValue * result, gpointer user_data)
|
||||||
|
{
|
||||||
|
GstPad *pad;
|
||||||
|
gchar *name;
|
||||||
|
guint sessid;
|
||||||
|
GstRtpBinSession *session = user_data, *newsess;
|
||||||
|
GstRtpBin *rtpbin = session->bin;
|
||||||
|
GstPadLinkReturn ret;
|
||||||
|
|
||||||
|
pad = g_value_get_object (item);
|
||||||
|
name = gst_pad_get_name (pad);
|
||||||
|
|
||||||
|
if (name == NULL || sscanf (name, "src_%u", &sessid) != 1)
|
||||||
|
goto no_name;
|
||||||
|
|
||||||
|
g_free (name);
|
||||||
|
|
||||||
|
newsess = find_session_by_id (rtpbin, sessid);
|
||||||
|
if (newsess == NULL) {
|
||||||
|
/* create new session */
|
||||||
|
newsess = create_session (rtpbin, sessid);
|
||||||
|
if (newsess == NULL)
|
||||||
|
goto create_error;
|
||||||
|
} else if (newsess->send_rtp_sink != NULL)
|
||||||
|
goto existing_session;
|
||||||
|
|
||||||
|
/* get send_rtp pad and store */
|
||||||
|
newsess->send_rtp_sink =
|
||||||
|
gst_element_get_request_pad (newsess->session, "send_rtp_sink");
|
||||||
|
if (newsess->send_rtp_sink == NULL)
|
||||||
|
goto pad_failed;
|
||||||
|
|
||||||
|
ret = gst_pad_link (pad, newsess->send_rtp_sink);
|
||||||
|
if (ret != GST_PAD_LINK_OK)
|
||||||
|
goto aux_link_failed;
|
||||||
|
|
||||||
|
if (!complete_session_src (rtpbin, newsess))
|
||||||
|
goto session_src_failed;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_name:
|
||||||
|
{
|
||||||
|
GST_WARNING ("ignoring invalid pad name %s", GST_STR_NULL (name));
|
||||||
|
g_free (name);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
create_error:
|
||||||
|
{
|
||||||
|
/* create_session already warned */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
existing_session:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: session %d is already a sender", sessid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
pad_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get session pad for session %d", sessid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
aux_link_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to link AUX for session %d", sessid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
session_src_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to complete AUX for session %d", sessid);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
setup_aux_sender (GstRtpBin * rtpbin, GstRtpBinSession * session,
|
||||||
|
GstElement * aux)
|
||||||
|
{
|
||||||
|
GstIterator *it;
|
||||||
|
GValue result = { 0, };
|
||||||
|
GstIteratorResult res;
|
||||||
|
|
||||||
|
it = gst_element_iterate_src_pads (aux);
|
||||||
|
res = gst_iterator_fold (it, setup_aux_sender_fold, &result, session);
|
||||||
|
gst_iterator_free (it);
|
||||||
|
|
||||||
|
return res == GST_ITERATOR_DONE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a pad for sending RTP for the session in @name. Must be called with
|
/* Create a pad for sending RTP for the session in @name. Must be called with
|
||||||
* RTP_BIN_LOCK.
|
* RTP_BIN_LOCK.
|
||||||
*/
|
*/
|
||||||
static GstPad *
|
static GstPad *
|
||||||
create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
||||||
{
|
{
|
||||||
gchar *gname;
|
gchar *pname;
|
||||||
guint sessid;
|
guint sessid;
|
||||||
GstPad *encsrc;
|
GstPad *send_rtp_sink;
|
||||||
GstElement *encoder;
|
GstElement *aux;
|
||||||
GstRtpBinSession *session;
|
GstRtpBinSession *session;
|
||||||
GstElementClass *klass;
|
|
||||||
|
|
||||||
/* first get the session number */
|
/* first get the session number */
|
||||||
if (name == NULL || sscanf (name, "send_rtp_sink_%u", &sessid) != 1)
|
if (name == NULL || sscanf (name, "send_rtp_sink_%u", &sessid) != 1)
|
||||||
|
@ -3198,64 +3482,41 @@ create_send_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
||||||
if (session->send_rtp_sink_ghost != NULL)
|
if (session->send_rtp_sink_ghost != NULL)
|
||||||
return session->send_rtp_sink_ghost;
|
return session->send_rtp_sink_ghost;
|
||||||
|
|
||||||
/* get send_rtp pad and store */
|
/* check if we are already using this session as a sender */
|
||||||
session->send_rtp_sink =
|
if (session->send_rtp_sink != NULL)
|
||||||
gst_element_get_request_pad (session->session, "send_rtp_sink");
|
goto existing_session;
|
||||||
if (session->send_rtp_sink == NULL)
|
|
||||||
goto pad_failed;
|
|
||||||
|
|
||||||
session->send_rtp_sink_ghost =
|
GST_DEBUG_OBJECT (rtpbin, "getting RTP AUX sender");
|
||||||
gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
|
aux = session_request_element (session, SIGNAL_REQUEST_AUX_SENDER);
|
||||||
gst_pad_set_active (session->send_rtp_sink_ghost, TRUE);
|
if (aux) {
|
||||||
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_sink_ghost);
|
GST_DEBUG_OBJECT (rtpbin, "linking AUX sender");
|
||||||
|
if (!setup_aux_sender (rtpbin, session, aux))
|
||||||
|
goto aux_session_failed;
|
||||||
|
|
||||||
/* get srcpad */
|
pname = g_strdup_printf ("sink_%d", sessid);
|
||||||
session->send_rtp_src =
|
send_rtp_sink = gst_element_get_static_pad (aux, pname);
|
||||||
gst_element_get_static_pad (session->session, "send_rtp_src");
|
g_free (pname);
|
||||||
if (session->send_rtp_src == NULL)
|
|
||||||
goto no_srcpad;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "getting RTP encoder");
|
if (send_rtp_sink == NULL)
|
||||||
encoder = session_request_element (session, SIGNAL_REQUEST_RTP_ENCODER);
|
goto aux_sink_failed;
|
||||||
if (encoder) {
|
|
||||||
gchar *ename;
|
|
||||||
GstPad *encsink;
|
|
||||||
GstPadLinkReturn ret;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (rtpbin, "linking RTP encoder");
|
|
||||||
ename = g_strdup_printf ("rtp_sink_%d", sessid);
|
|
||||||
encsink = gst_element_get_static_pad (encoder, ename);
|
|
||||||
g_free (ename);
|
|
||||||
ename = g_strdup_printf ("rtp_src_%d", sessid);
|
|
||||||
encsrc = gst_element_get_static_pad (encoder, ename);
|
|
||||||
g_free (ename);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (ret != GST_PAD_LINK_OK)
|
|
||||||
goto enc_link_failed;
|
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG_OBJECT (rtpbin, "no RTP encoder given");
|
/* get send_rtp pad and store */
|
||||||
encsrc = gst_object_ref (session->send_rtp_src);
|
session->send_rtp_sink =
|
||||||
|
gst_element_get_request_pad (session->session, "send_rtp_sink");
|
||||||
|
if (session->send_rtp_sink == NULL)
|
||||||
|
goto pad_failed;
|
||||||
|
|
||||||
|
if (!complete_session_src (rtpbin, session))
|
||||||
|
goto session_src_failed;
|
||||||
|
|
||||||
|
send_rtp_sink = gst_object_ref (session->send_rtp_sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ghost the new source pad */
|
session->send_rtp_sink_ghost =
|
||||||
klass = GST_ELEMENT_GET_CLASS (rtpbin);
|
gst_ghost_pad_new_from_template (name, send_rtp_sink, templ);
|
||||||
gname = g_strdup_printf ("send_rtp_src_%u", sessid);
|
gst_object_unref (send_rtp_sink);
|
||||||
templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%u");
|
gst_pad_set_active (session->send_rtp_sink_ghost, TRUE);
|
||||||
session->send_rtp_src_ghost =
|
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), session->send_rtp_sink_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);
|
|
||||||
|
|
||||||
return session->send_rtp_sink_ghost;
|
return session->send_rtp_sink_ghost;
|
||||||
|
|
||||||
|
@ -3270,31 +3531,29 @@ create_error:
|
||||||
/* create_session already warned */
|
/* create_session already warned */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
existing_session:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: session %d is already in use", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
aux_session_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get AUX sink pad for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
aux_sink_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get AUX sink pad for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pad_failed:
|
pad_failed:
|
||||||
{
|
{
|
||||||
g_warning ("rtpbin: failed to get session pad for session %d", sessid);
|
g_warning ("rtpbin: failed to get session pad for session %d", sessid);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
no_srcpad:
|
session_src_failed:
|
||||||
{
|
{
|
||||||
g_warning ("rtpbin: failed to get rtp source pad for session %d", sessid);
|
g_warning ("rtpbin: failed to setup source pads for session %d", sessid);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
enc_src_failed:
|
|
||||||
{
|
|
||||||
g_warning ("rtpbin: failed to get encoder src pad for session %d", sessid);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
enc_sink_failed:
|
|
||||||
{
|
|
||||||
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,9 @@ struct _GstRtpBinClass {
|
||||||
GstElement* (*request_rtp_decoder) (GstRtpBin *rtpbin, guint session);
|
GstElement* (*request_rtp_decoder) (GstRtpBin *rtpbin, guint session);
|
||||||
GstElement* (*request_rtcp_encoder) (GstRtpBin *rtpbin, guint session);
|
GstElement* (*request_rtcp_encoder) (GstRtpBin *rtpbin, guint session);
|
||||||
GstElement* (*request_rtcp_decoder) (GstRtpBin *rtpbin, guint session);
|
GstElement* (*request_rtcp_decoder) (GstRtpBin *rtpbin, guint session);
|
||||||
|
|
||||||
|
GstElement* (*request_aux_sender) (GstRtpBin *rtpbin, guint session);
|
||||||
|
GstElement* (*request_aux_receiver) (GstRtpBin *rtpbin, guint session);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_rtp_bin_get_type (void);
|
GType gst_rtp_bin_get_type (void);
|
||||||
|
|
Loading…
Reference in a new issue