mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 17:20:36 +00:00
gst/rtpmanager/: Some more ghostpad magic.
Original commit message from CVS: * gst/rtpmanager/gstrtpbin.c: (find_session_by_id), (create_session), (gst_rtp_bin_base_init), (create_recv_rtp), (create_recv_rtcp), (create_send_rtp), (create_rtcp), (gst_rtp_bin_request_new_pad): * gst/rtpmanager/gstrtpbin.h: * gst/rtpmanager/gstrtpclient.c: Some more ghostpad magic.
This commit is contained in:
parent
fdae491de7
commit
5351f0cb51
3 changed files with 350 additions and 7 deletions
|
@ -79,8 +79,8 @@ GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%d_%d_%d",
|
||||||
GST_STATIC_CAPS ("application/x-rtp")
|
GST_STATIC_CAPS ("application/x-rtp")
|
||||||
);
|
);
|
||||||
|
|
||||||
static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
|
static GstStaticPadTemplate rtpbin_rtcp_src_template =
|
||||||
GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%d",
|
GST_STATIC_PAD_TEMPLATE ("rtcp_src_%d",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_REQUEST,
|
GST_PAD_REQUEST,
|
||||||
GST_STATIC_CAPS ("application/x-rtcp")
|
GST_STATIC_CAPS ("application/x-rtcp")
|
||||||
|
@ -112,6 +112,63 @@ enum
|
||||||
PROP_0
|
PROP_0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* helper objects */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* session id */
|
||||||
|
gint id;
|
||||||
|
/* the session element */
|
||||||
|
GstElement *session;
|
||||||
|
/* the SSRC demuxer */
|
||||||
|
GstElement *ssrcdemux;
|
||||||
|
|
||||||
|
/* the pads of the session */
|
||||||
|
GstPad *recv_rtp_sink;
|
||||||
|
GstPad *recv_rtcp_sink;
|
||||||
|
GstPad *send_rtp_sink;
|
||||||
|
GstPad *rtcp_src;
|
||||||
|
|
||||||
|
} GstRTPBinSession;
|
||||||
|
|
||||||
|
/* find a session with the given id */
|
||||||
|
static GstRTPBinSession *
|
||||||
|
find_session_by_id (GstRTPBin * rtpbin, gint id)
|
||||||
|
{
|
||||||
|
GList *walk;
|
||||||
|
|
||||||
|
for (walk = rtpbin->sessions; walk; walk = g_list_next (walk)) {
|
||||||
|
GstRTPBinSession *sess = (GstRTPBinSession *) walk->data;
|
||||||
|
|
||||||
|
if (sess->id == id)
|
||||||
|
return sess;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create a session with the given id */
|
||||||
|
static GstRTPBinSession *
|
||||||
|
create_session (GstRTPBin * rtpbin, gint id)
|
||||||
|
{
|
||||||
|
GstRTPBinSession *sess;
|
||||||
|
GstElement *elem;
|
||||||
|
|
||||||
|
if (!(elem = gst_element_factory_make ("rtpsession", NULL)))
|
||||||
|
goto no_session;
|
||||||
|
|
||||||
|
sess = g_new0 (GstRTPBinSession, 1);
|
||||||
|
sess->id = id;
|
||||||
|
sess->session = elem;
|
||||||
|
|
||||||
|
return sess;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_session:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: could not create rtpsession element");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* GObject vmethods */
|
/* GObject vmethods */
|
||||||
static void gst_rtp_bin_finalize (GObject * object);
|
static void gst_rtp_bin_finalize (GObject * object);
|
||||||
static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
|
static void gst_rtp_bin_set_property (GObject * object, guint prop_id,
|
||||||
|
@ -147,7 +204,7 @@ gst_rtp_bin_base_init (gpointer klass)
|
||||||
gst_element_class_add_pad_template (element_class,
|
gst_element_class_add_pad_template (element_class,
|
||||||
gst_static_pad_template_get (&rtpbin_recv_rtp_src_template));
|
gst_static_pad_template_get (&rtpbin_recv_rtp_src_template));
|
||||||
gst_element_class_add_pad_template (element_class,
|
gst_element_class_add_pad_template (element_class,
|
||||||
gst_static_pad_template_get (&rtpbin_send_rtcp_src_template));
|
gst_static_pad_template_get (&rtpbin_rtcp_src_template));
|
||||||
gst_element_class_add_pad_template (element_class,
|
gst_element_class_add_pad_template (element_class,
|
||||||
gst_static_pad_template_get (&rtpbin_send_rtp_src_template));
|
gst_static_pad_template_get (&rtpbin_send_rtp_src_template));
|
||||||
|
|
||||||
|
@ -255,6 +312,267 @@ gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create a pad for receiving RTP for the session in @name
|
||||||
|
*/
|
||||||
|
static GstPad *
|
||||||
|
create_recv_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
||||||
|
{
|
||||||
|
GstPad *result;
|
||||||
|
guint sessid;
|
||||||
|
GstRTPBinSession *session;
|
||||||
|
|
||||||
|
/* first get the session number */
|
||||||
|
if (name == NULL || sscanf (name, "recv_rtp_sink_%d", &sessid) != 1)
|
||||||
|
goto no_name;
|
||||||
|
|
||||||
|
/* get or create session */
|
||||||
|
session = find_session_by_id (rtpbin, sessid);
|
||||||
|
if (!session) {
|
||||||
|
/* create session now */
|
||||||
|
session = create_session (rtpbin, sessid);
|
||||||
|
if (session == NULL)
|
||||||
|
goto create_error;
|
||||||
|
}
|
||||||
|
/* check if pad was requested */
|
||||||
|
if (session->recv_rtp_sink != NULL)
|
||||||
|
goto existed;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
result =
|
||||||
|
gst_ghost_pad_new_from_template (name, session->recv_rtp_sink, templ);
|
||||||
|
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
|
||||||
|
|
||||||
|
/* FIXME, get srcpad, link to SSRCDemux */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_name:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: invalid name given");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
create_error:
|
||||||
|
{
|
||||||
|
/* create_session already warned */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
existed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: recv_rtp pad already requested for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pad_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get session pad");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a pad for receiving RTCP for the session in @name
|
||||||
|
*/
|
||||||
|
static GstPad *
|
||||||
|
create_recv_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ,
|
||||||
|
const gchar * name)
|
||||||
|
{
|
||||||
|
GstPad *result;
|
||||||
|
guint sessid;
|
||||||
|
GstRTPBinSession *session;
|
||||||
|
|
||||||
|
/* first get the session number */
|
||||||
|
if (name == NULL || sscanf (name, "recv_rtcp_sink_%d", &sessid) != 1)
|
||||||
|
goto no_name;
|
||||||
|
|
||||||
|
/* get the session, it must exist or we error */
|
||||||
|
session = find_session_by_id (rtpbin, sessid);
|
||||||
|
if (!session)
|
||||||
|
goto no_session;
|
||||||
|
|
||||||
|
/* check if pad was requested */
|
||||||
|
if (session->recv_rtcp_sink != NULL)
|
||||||
|
goto existed;
|
||||||
|
|
||||||
|
/* get recv_rtp pad and store */
|
||||||
|
session->recv_rtcp_sink =
|
||||||
|
gst_element_get_request_pad (session->session, "recv_rtcp_sink");
|
||||||
|
if (session->recv_rtcp_sink == NULL)
|
||||||
|
goto pad_failed;
|
||||||
|
|
||||||
|
result =
|
||||||
|
gst_ghost_pad_new_from_template (name, session->recv_rtcp_sink, templ);
|
||||||
|
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
|
||||||
|
|
||||||
|
/* FIXME, get srcpad, link to SSRCDemux */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_name:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: invalid name given");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
no_session:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: no session with id %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
existed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: recv_rtcp pad already requested for session %d",
|
||||||
|
sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pad_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get session pad");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a pad for sending RTP for the session in @name
|
||||||
|
*/
|
||||||
|
static GstPad *
|
||||||
|
create_send_rtp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
||||||
|
{
|
||||||
|
GstPad *result, *srcpad, *srcghost;
|
||||||
|
gchar *gname;
|
||||||
|
guint sessid;
|
||||||
|
GstRTPBinSession *session;
|
||||||
|
GstElementClass *klass;
|
||||||
|
|
||||||
|
/* first get the session number */
|
||||||
|
if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
|
||||||
|
goto no_name;
|
||||||
|
|
||||||
|
/* get or create session */
|
||||||
|
session = find_session_by_id (rtpbin, sessid);
|
||||||
|
if (!session) {
|
||||||
|
/* create session now */
|
||||||
|
session = create_session (rtpbin, sessid);
|
||||||
|
if (session == NULL)
|
||||||
|
goto create_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if pad was requested */
|
||||||
|
if (session->send_rtp_sink != NULL)
|
||||||
|
goto existed;
|
||||||
|
|
||||||
|
/* get recv_rtp pad and store */
|
||||||
|
session->send_rtp_sink =
|
||||||
|
gst_element_get_request_pad (session->session, "send_rtp_sink");
|
||||||
|
if (session->send_rtp_sink == NULL)
|
||||||
|
goto pad_failed;
|
||||||
|
|
||||||
|
result =
|
||||||
|
gst_ghost_pad_new_from_template (name, session->send_rtp_sink, templ);
|
||||||
|
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
|
||||||
|
|
||||||
|
/* get srcpad */
|
||||||
|
srcpad = gst_element_get_pad (session->session, "send_rtp_src");
|
||||||
|
if (srcpad == NULL)
|
||||||
|
goto no_srcpad;
|
||||||
|
|
||||||
|
/* ghost the new source pad */
|
||||||
|
klass = GST_ELEMENT_GET_CLASS (rtpbin);
|
||||||
|
gname = g_strdup_printf ("send_rtp_src_%d", sessid);
|
||||||
|
templ = gst_element_class_get_pad_template (klass, "send_rtp_src_%d");
|
||||||
|
srcghost =
|
||||||
|
gst_ghost_pad_new_from_template (gname, session->send_rtp_sink, templ);
|
||||||
|
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), srcghost);
|
||||||
|
g_free (gname);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_name:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: invalid name given");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
create_error:
|
||||||
|
{
|
||||||
|
/* create_session already warned */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
existed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: send_rtp pad already requested for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pad_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get session pad for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
no_srcpad:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get rtp source pad for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a pad for sending RTCP for the session in @name
|
||||||
|
*/
|
||||||
|
static GstPad *
|
||||||
|
create_rtcp (GstRTPBin * rtpbin, GstPadTemplate * templ, const gchar * name)
|
||||||
|
{
|
||||||
|
GstPad *result;
|
||||||
|
guint sessid;
|
||||||
|
GstRTPBinSession *session;
|
||||||
|
|
||||||
|
/* first get the session number */
|
||||||
|
if (name == NULL || sscanf (name, "send_rtp_sink_%d", &sessid) != 1)
|
||||||
|
goto no_name;
|
||||||
|
|
||||||
|
/* get or create session */
|
||||||
|
session = find_session_by_id (rtpbin, sessid);
|
||||||
|
if (!session)
|
||||||
|
goto no_session;
|
||||||
|
|
||||||
|
/* check if pad was requested */
|
||||||
|
if (session->rtcp_src != NULL)
|
||||||
|
goto existed;
|
||||||
|
|
||||||
|
/* get rtcp_src pad and store */
|
||||||
|
session->rtcp_src =
|
||||||
|
gst_element_get_request_pad (session->session, "rtcp_src");
|
||||||
|
if (session->rtcp_src == NULL)
|
||||||
|
goto pad_failed;
|
||||||
|
|
||||||
|
result = gst_ghost_pad_new_from_template (name, session->rtcp_src, templ);
|
||||||
|
gst_element_add_pad (GST_ELEMENT_CAST (rtpbin), result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
no_name:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: invalid name given");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
no_session:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: session with id %d does not exist", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
existed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: rtcp_src pad already requested for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pad_failed:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: failed to get rtcp pad for session %d", sessid);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*/
|
*/
|
||||||
static GstPad *
|
static GstPad *
|
||||||
|
@ -263,6 +581,7 @@ gst_rtp_bin_request_new_pad (GstElement * element,
|
||||||
{
|
{
|
||||||
GstRTPBin *rtpbin;
|
GstRTPBin *rtpbin;
|
||||||
GstElementClass *klass;
|
GstElementClass *klass;
|
||||||
|
GstPad *result;
|
||||||
|
|
||||||
g_return_val_if_fail (templ != NULL, NULL);
|
g_return_val_if_fail (templ != NULL, NULL);
|
||||||
g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
|
g_return_val_if_fail (GST_IS_RTP_BIN (element), NULL);
|
||||||
|
@ -270,7 +589,28 @@ gst_rtp_bin_request_new_pad (GstElement * element,
|
||||||
rtpbin = GST_RTP_BIN (element);
|
rtpbin = GST_RTP_BIN (element);
|
||||||
klass = GST_ELEMENT_GET_CLASS (element);
|
klass = GST_ELEMENT_GET_CLASS (element);
|
||||||
|
|
||||||
return NULL;
|
/* figure out the template */
|
||||||
|
if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%d")) {
|
||||||
|
result = create_recv_rtp (rtpbin, templ, name);
|
||||||
|
} else if (templ == gst_element_class_get_pad_template (klass,
|
||||||
|
"recv_rtcp_sink_%d")) {
|
||||||
|
result = create_recv_rtcp (rtpbin, templ, name);
|
||||||
|
} else if (templ == gst_element_class_get_pad_template (klass,
|
||||||
|
"send_rtp_sink_%d")) {
|
||||||
|
result = create_send_rtp (rtpbin, templ, name);
|
||||||
|
} else if (templ == gst_element_class_get_pad_template (klass, "rtcp_src_%d")) {
|
||||||
|
result = create_rtcp (rtpbin, templ, name);
|
||||||
|
} else
|
||||||
|
goto wrong_template;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
wrong_template:
|
||||||
|
{
|
||||||
|
g_warning ("rtpbin: this is not our template");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -40,8 +40,8 @@ typedef struct _GstRTPBinPrivate GstRTPBinPrivate;
|
||||||
struct _GstRTPBin {
|
struct _GstRTPBin {
|
||||||
GstBin element;
|
GstBin element;
|
||||||
|
|
||||||
/* a list of streams from a client */
|
/* a list of session */
|
||||||
GList *streams;
|
GList *sessions;
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
GstRTPBinPrivate *priv;
|
GstRTPBinPrivate *priv;
|
||||||
|
|
|
@ -27,10 +27,13 @@
|
||||||
* This element handles RTP data from one client. It accepts multiple RTP streams that
|
* This element handles RTP data from one client. It accepts multiple RTP streams that
|
||||||
* should be synchronized together.
|
* should be synchronized together.
|
||||||
* </para>
|
* </para>
|
||||||
|
* <para>
|
||||||
|
* Normally the SSRCs that map to the same CNAME (as given in the RTCP SDES messages)
|
||||||
|
* should be synchronized.
|
||||||
|
* </para>
|
||||||
* <title>Example pipelines</title>
|
* <title>Example pipelines</title>
|
||||||
* <para>
|
* <para>
|
||||||
* <programlisting>
|
* <programlisting>
|
||||||
* gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
|
|
||||||
* </programlisting>
|
* </programlisting>
|
||||||
* </para>
|
* </para>
|
||||||
* </refsect2>
|
* </refsect2>
|
||||||
|
|
Loading…
Reference in a new issue