summaryrefslogtreecommitdiffstats
path: root/gst/rtpmanager/gstrtpbin.c
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2007-04-03 11:35:39 +0000
committerWim Taymans <wim.taymans@gmail.com>2007-04-03 11:35:39 +0000
commit909a0e333992f6cfae4c9896b4974db1b5373259 (patch)
tree64a5f6c7521e61bbbe4276d6ab95c1d725f104d8 /gst/rtpmanager/gstrtpbin.c
parentd99773bc390ff590d10865982270e649494f952b (diff)
downloadgst-plugins-bad-909a0e333992f6cfae4c9896b4974db1b5373259.tar.gz
gst-plugins-bad-909a0e333992f6cfae4c9896b4974db1b5373259.tar.bz2
gst-plugins-bad-909a0e333992f6cfae4c9896b4974db1b5373259.zip
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.
Diffstat (limited to 'gst/rtpmanager/gstrtpbin.c')
-rw-r--r--gst/rtpmanager/gstrtpbin.c348
1 files changed, 344 insertions, 4 deletions
diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c
index 629f098d..c1ec7130 100644
--- a/gst/rtpmanager/gstrtpbin.c
+++ b/gst/rtpmanager/gstrtpbin.c
@@ -79,8 +79,8 @@ GST_STATIC_PAD_TEMPLATE ("recv_rtp_src_%d_%d_%d",
GST_STATIC_CAPS ("application/x-rtp")
);
-static GstStaticPadTemplate rtpbin_send_rtcp_src_template =
-GST_STATIC_PAD_TEMPLATE ("send_rtcp_src_%d",
+static GstStaticPadTemplate rtpbin_rtcp_src_template =
+GST_STATIC_PAD_TEMPLATE ("rtcp_src_%d",
GST_PAD_SRC,
GST_PAD_REQUEST,
GST_STATIC_CAPS ("application/x-rtcp")
@@ -112,6 +112,63 @@ enum
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 */
static void gst_rtp_bin_finalize (GObject * object);
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_static_pad_template_get (&rtpbin_recv_rtp_src_template));
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_static_pad_template_get (&rtpbin_send_rtp_src_template));
@@ -255,6 +312,267 @@ gst_rtp_bin_change_state (GstElement * element, GstStateChange transition)
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 *
@@ -263,6 +581,7 @@ gst_rtp_bin_request_new_pad (GstElement * element,
{
GstRTPBin *rtpbin;
GstElementClass *klass;
+ GstPad *result;
g_return_val_if_fail (templ != NULL, 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);
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