GST_STATIC_CAPS ("application/x-rtcp")
);
-#define GST_PAD_LOCK(obj) (g_static_rec_mutex_lock (&(obj)->padlock))
-#define GST_PAD_UNLOCK(obj) (g_static_rec_mutex_unlock (&(obj)->padlock))
+#define GST_PAD_LOCK(obj) (g_rec_mutex_lock (&(obj)->padlock))
+#define GST_PAD_UNLOCK(obj) (g_rec_mutex_unlock (&(obj)->padlock))
+
+typedef enum
+{
+ RTP_PAD,
+ RTCP_PAD
+} PadType;
/* signals */
enum
return NULL;
}
-/* with PAD_LOCK */
-static GstRtpSsrcDemuxPad *
-find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc)
+static GstEvent *
+add_ssrc_and_ref (GstEvent * event, guint32 ssrc)
+{
+ /* Set the ssrc on the output caps */
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+ GstCaps *newcaps;
+ GstStructure *s;
+
+ gst_event_parse_caps (event, &caps);
+ newcaps = gst_caps_copy (caps);
+
+ s = gst_caps_get_structure (newcaps, 0);
+ gst_structure_set (s, "ssrc", G_TYPE_UINT, ssrc, NULL);
+ event = gst_event_new_caps (newcaps);
+ gst_caps_unref (newcaps);
+ break;
+ }
+ default:
+ gst_event_ref (event);
+ break;
+ }
+
+ return event;
+}
+
+struct ForwardEventData
+{
+ GstPad *pad;
+ guint32 ssrc;
+};
+
+static gboolean
+forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
+{
+ struct ForwardEventData *data = user_data;
+ GstEvent *newevent;
+
+ newevent = add_ssrc_and_ref (*event, data->ssrc);
+
+ gst_pad_push_event (data->pad, newevent);
+
+ return TRUE;
+}
+
+
+static GstPad *
+find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
+ PadType padtype)
{
GstPad *rtp_pad, *rtcp_pad;
GstElementClass *klass;
gchar *padname;
GstRtpSsrcDemuxPad *demuxpad;
GstCaps *caps;
+ struct ForwardEventData fdata;
+ GstPad *retpad;
GST_DEBUG_OBJECT (demux, "creating pad for SSRC %08x", ssrc);
+ GST_PAD_LOCK (demux);
+
demuxpad = find_demux_pad_for_ssrc (demux, ssrc);
if (demuxpad != NULL) {
- return demuxpad;
+ switch (padtype) {
+ case RTP_PAD:
+ retpad = gst_object_ref (demuxpad->rtp_pad);
+ break;
+ case RTCP_PAD:
+ retpad = gst_object_ref (demuxpad->rtcp_pad);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ GST_PAD_UNLOCK (demux);
+ return retpad;
}
klass = GST_ELEMENT_GET_CLASS (demux);
demuxpad->rtp_pad = rtp_pad;
demuxpad->rtcp_pad = rtcp_pad;
+ fdata.ssrc = ssrc;
+
gst_pad_set_element_private (rtp_pad, demuxpad);
gst_pad_set_element_private (rtcp_pad, demuxpad);
demux->srcpads = g_slist_prepend (demux->srcpads, demuxpad);
- /* copy caps from input */
- caps = gst_pad_get_current_caps (demux->rtp_sink);
- gst_pad_set_caps (rtp_pad, caps);
- gst_caps_unref (caps);
- gst_pad_use_fixed_caps (rtp_pad);
- caps = gst_pad_get_current_caps (demux->rtcp_sink);
- gst_pad_set_caps (rtcp_pad, caps);
- gst_caps_unref (caps);
- gst_pad_use_fixed_caps (rtcp_pad);
-
- gst_pad_set_event_function (rtp_pad, gst_rtp_ssrc_demux_src_event);
gst_pad_set_query_function (rtp_pad, gst_rtp_ssrc_demux_src_query);
gst_pad_set_iterate_internal_links_function (rtp_pad,
gst_rtp_ssrc_demux_iterate_internal_links_src);
+ gst_pad_set_event_function (rtp_pad, gst_rtp_ssrc_demux_src_event);
+ gst_pad_use_fixed_caps (rtp_pad);
gst_pad_set_active (rtp_pad, TRUE);
+ fdata.pad = rtp_pad;
+ gst_pad_sticky_events_foreach (demux->rtp_sink, forward_sticky_events,
+ &fdata);
gst_pad_set_event_function (rtcp_pad, gst_rtp_ssrc_demux_src_event);
gst_pad_set_iterate_internal_links_function (rtcp_pad,
gst_rtp_ssrc_demux_iterate_internal_links_src);
+ gst_pad_use_fixed_caps (rtcp_pad);
gst_pad_set_active (rtcp_pad, TRUE);
+ fdata.pad = rtcp_pad;
+ gst_pad_sticky_events_foreach (demux->rtcp_sink, forward_sticky_events,
+ &fdata);
+ /* copy caps from input */
+ if ((caps = gst_pad_get_current_caps (demux->rtp_sink))) {
+ gst_pad_set_caps (rtp_pad, caps);
+ gst_caps_unref (caps);
+ }
+ if ((caps = gst_pad_get_current_caps (demux->rtcp_sink))) {
+ gst_pad_set_caps (rtcp_pad, caps);
+ gst_caps_unref (caps);
+ }
gst_element_add_pad (GST_ELEMENT_CAST (demux), rtp_pad);
gst_element_add_pad (GST_ELEMENT_CAST (demux), rtcp_pad);
+ switch (padtype) {
+ case RTP_PAD:
+ retpad = gst_object_ref (demuxpad->rtp_pad);
+ break;
+ case RTCP_PAD:
+ retpad = gst_object_ref (demuxpad->rtcp_pad);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ gst_object_ref (rtp_pad);
+
+ GST_PAD_UNLOCK (demux);
+
g_signal_emit (G_OBJECT (demux),
gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD], 0, ssrc, rtp_pad);
- return demuxpad;
+ gst_object_unref (rtp_pad);
+
+ return retpad;
}
static void
gst_element_class_add_pad_template (gstelement_klass,
gst_static_pad_template_get (&rtp_ssrc_demux_rtcp_src_template));
- gst_element_class_set_details_simple (gstelement_klass, "RTP SSRC Demux",
+ gst_element_class_set_static_metadata (gstelement_klass, "RTP SSRC Demux",
"Demux/Network/RTP",
"Splits RTP streams based on the SSRC",
"Wim Taymans <wim.taymans@gmail.com>");
gst_rtp_ssrc_demux_iterate_internal_links_sink);
gst_element_add_pad (GST_ELEMENT_CAST (demux), demux->rtcp_sink);
- g_static_rec_mutex_init (&demux->padlock);
+ g_rec_mutex_init (&demux->padlock);
gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
}
GstRtpSsrcDemux *demux;
demux = GST_RTP_SSRC_DEMUX (object);
- g_static_rec_mutex_free (&demux->padlock);
+ g_rec_mutex_clear (&demux->padlock);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_STOP:
gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
+ /* fallthrough */
default:
{
GSList *walk;
for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
GstRtpSsrcDemuxPad *pad = (GstRtpSsrcDemuxPad *) walk->data;
- pads = g_slist_prepend (pads, gst_object_ref (pad->rtp_pad));
+ pad = g_slice_dup (GstRtpSsrcDemuxPad, pad);
+ gst_object_ref (pad->rtp_pad);
+
+ pads = g_slist_prepend (pads, pad);
}
GST_PAD_UNLOCK (demux);
+
for (walk = pads; walk; walk = g_slist_next (walk)) {
- GstPad *pad = (GstPad *) walk->data;
+ GstRtpSsrcDemuxPad *dpad = walk->data;
+ GstEvent *newevent;
+
+ newevent = add_ssrc_and_ref (event, dpad->ssrc);
- gst_event_ref (event);
- res &= gst_pad_push_event (pad, event);
- gst_object_unref (pad);
+ res &= gst_pad_push_event (dpad->rtp_pad, newevent);
+ gst_object_unref (dpad->rtp_pad);
+ g_slice_free (GstRtpSsrcDemuxPad, dpad);
}
g_slist_free (pads);
gst_event_unref (event);
GstEvent * event)
{
GstRtpSsrcDemux *demux;
- gboolean res = FALSE;
+ gboolean res = TRUE;
+ GSList *walk;
+ GSList *pads = NULL;
demux = GST_RTP_SSRC_DEMUX (parent);
- switch (GST_EVENT_TYPE (event)) {
- default:
- {
- GSList *walk;
- GSList *pads = NULL;
+ GST_PAD_LOCK (demux);
+ for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
+ GstRtpSsrcDemuxPad *pad = (GstRtpSsrcDemuxPad *) walk->data;
- res = TRUE;
- GST_PAD_LOCK (demux);
- for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
- GstRtpSsrcDemuxPad *pad = (GstRtpSsrcDemuxPad *) walk->data;
+ pad = g_slice_dup (GstRtpSsrcDemuxPad, pad);
+ gst_object_ref (pad->rtcp_pad);
- pads = g_slist_prepend (pads, gst_object_ref (pad->rtcp_pad));
- }
- GST_PAD_UNLOCK (demux);
- for (walk = pads; walk; walk = g_slist_next (walk)) {
- GstPad *pad = (GstPad *) walk->data;
+ pads = g_slist_prepend (pads, pad);
+ }
+ GST_PAD_UNLOCK (demux);
- gst_event_ref (event);
- res &= gst_pad_push_event (pad, event);
- gst_object_unref (pad);
- }
- g_slist_free (pads);
- gst_event_unref (event);
- break;
- }
+ for (walk = pads; walk; walk = g_slist_next (walk)) {
+ GstRtpSsrcDemuxPad *dpad = walk->data;
+ GstEvent *newevent;
+
+ newevent = add_ssrc_and_ref (event, dpad->ssrc);
+
+ res &= gst_pad_push_event (dpad->rtcp_pad, newevent);
+ gst_object_unref (dpad->rtcp_pad);
+ g_slice_free (GstRtpSsrcDemuxPad, dpad);
}
+ g_slist_free (pads);
+ gst_event_unref (event);
+
return res;
}
GstFlowReturn ret;
GstRtpSsrcDemux *demux;
guint32 ssrc;
- GstRtpSsrcDemuxPad *dpad;
- GstRTPBuffer rtp;
+ GstRTPBuffer rtp = { NULL };
GstPad *srcpad;
demux = GST_RTP_SSRC_DEMUX (parent);
- if (!gst_rtp_buffer_validate (buf))
+ if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp))
goto invalid_payload;
- gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
ssrc = gst_rtp_buffer_get_ssrc (&rtp);
gst_rtp_buffer_unmap (&rtp);
GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc);
- GST_PAD_LOCK (demux);
- dpad = find_or_create_demux_pad_for_ssrc (demux, ssrc);
- if (dpad == NULL) {
- GST_PAD_UNLOCK (demux);
+ srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTP_PAD);
+ if (srcpad == NULL)
goto create_failed;
- }
- srcpad = gst_object_ref (dpad->rtp_pad);
- GST_PAD_UNLOCK (demux);
/* push to srcpad */
ret = gst_pad_push (srcpad, buf);
GstFlowReturn ret;
GstRtpSsrcDemux *demux;
guint32 ssrc;
- GstRtpSsrcDemuxPad *dpad;
GstRTCPPacket packet;
- GstRTCPBuffer rtcp;
+ GstRTCPBuffer rtcp = { NULL, };
GstPad *srcpad;
demux = GST_RTP_SSRC_DEMUX (parent);
GST_DEBUG_OBJECT (demux, "received RTCP of SSRC %08x", ssrc);
- GST_PAD_LOCK (demux);
- dpad = find_or_create_demux_pad_for_ssrc (demux, ssrc);
- if (dpad == NULL) {
- GST_PAD_UNLOCK (demux);
+ srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTCP_PAD);
+ if (srcpad == NULL)
goto create_failed;
- }
- srcpad = gst_object_ref (dpad->rtcp_pad);
- GST_PAD_UNLOCK (demux);
/* push to srcpad */
ret = gst_pad_push (srcpad, buf);
}
}
+static GstRtpSsrcDemuxPad *
+find_demux_pad_for_pad (GstRtpSsrcDemux * demux, GstPad * pad)
+{
+ GSList *walk;
+
+ for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
+ GstRtpSsrcDemuxPad *dpad = (GstRtpSsrcDemuxPad *) walk->data;
+ if (dpad->rtp_pad == pad || dpad->rtcp_pad == pad) {
+ return dpad;
+ }
+ }
+
+ return NULL;
+}
+
+
static gboolean
gst_rtp_ssrc_demux_src_event (GstPad * pad, GstObject * parent,
GstEvent * event)
case GST_EVENT_CUSTOM_BOTH_OOB:
s = gst_event_get_structure (event);
if (s && !gst_structure_has_field (s, "ssrc")) {
- GSList *walk;
+ GstRtpSsrcDemuxPad *dpad = find_demux_pad_for_pad (demux, pad);
- for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
- GstRtpSsrcDemuxPad *dpad = (GstRtpSsrcDemuxPad *) walk->data;
+ if (dpad) {
+ GstStructure *ws;
- if (dpad->rtp_pad == pad || dpad->rtcp_pad == pad) {
- GstStructure *ws;
-
- event =
- GST_EVENT_CAST (gst_mini_object_make_writable
- (GST_MINI_OBJECT_CAST (event)));
- ws = gst_event_writable_structure (event);
- gst_structure_set (ws, "ssrc", G_TYPE_UINT, dpad->ssrc, NULL);
- break;
- }
+ event = gst_event_make_writable (event);
+ ws = gst_event_writable_structure (event);
+ gst_structure_set (ws, "ssrc", G_TYPE_UINT, dpad->ssrc, NULL);
}
}
break;
g_value_set_object (&val, otherpad);
it = gst_iterator_new_single (GST_TYPE_PAD, &val);
g_value_unset (&val);
- gst_object_unref (otherpad);
+
}
GST_PAD_UNLOCK (demux);
static gint
src_pad_compare_func (gconstpointer a, gconstpointer b)
{
- GstPad *pad = GST_PAD (a);
- const gchar *prefix = b;
+ GstPad *pad = GST_PAD (g_value_get_object (a));
+ const gchar *prefix = g_value_get_string (b);
gint res = 1;
GST_OBJECT_LOCK (pad);
g_assert_not_reached ();
it = gst_element_iterate_src_pads (GST_ELEMENT_CAST (demux));
-
it = gst_iterator_filter (it, src_pad_compare_func, &gval);
return it;