mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
rtpssrcdemux: Only forward stick events while holding the sinkpad stream lock
Otherwise we get a race where if the RTCP packet comes in first and while it is added the pads, the segment event arrives on the RTP stream, the event may be lost completely and never forwarded.
This commit is contained in:
parent
76679f9ae9
commit
6f3734c305
1 changed files with 53 additions and 12 deletions
|
@ -145,6 +145,9 @@ struct _GstRtpSsrcDemuxPad
|
|||
GstPad *rtp_pad;
|
||||
GstCaps *caps;
|
||||
GstPad *rtcp_pad;
|
||||
|
||||
gboolean pushed_initial_rtp_events;
|
||||
gboolean pushed_initial_rtcp_events;
|
||||
};
|
||||
|
||||
/* find a src pad for a given SSRC, returns NULL if the SSRC was not found
|
||||
|
@ -210,6 +213,25 @@ forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
forward_initial_events (GstRtpSsrcDemux * demux, guint32 ssrc, GstPad * pad,
|
||||
PadType padtype)
|
||||
{
|
||||
struct ForwardStickyEventData fdata;
|
||||
GstPad *sinkpad;
|
||||
|
||||
if (padtype == RTP_PAD)
|
||||
sinkpad = demux->rtp_sink;
|
||||
else if (padtype == RTCP_PAD)
|
||||
sinkpad = demux->rtcp_sink;
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
fdata.ssrc = ssrc;
|
||||
fdata.pad = pad;
|
||||
|
||||
gst_pad_sticky_events_foreach (sinkpad, forward_sticky_events, &fdata);
|
||||
}
|
||||
|
||||
static GstPad *
|
||||
find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
|
||||
|
@ -220,31 +242,44 @@ find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
|
|||
GstPadTemplate *templ;
|
||||
gchar *padname;
|
||||
GstRtpSsrcDemuxPad *demuxpad;
|
||||
struct ForwardStickyEventData fdata;
|
||||
GstPad *retpad;
|
||||
gulong rtp_block, rtcp_block;
|
||||
|
||||
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) {
|
||||
gboolean forward = FALSE;
|
||||
|
||||
switch (padtype) {
|
||||
case RTP_PAD:
|
||||
retpad = gst_object_ref (demuxpad->rtp_pad);
|
||||
if (!demuxpad->pushed_initial_rtp_events) {
|
||||
forward = TRUE;
|
||||
demuxpad->pushed_initial_rtp_events = TRUE;
|
||||
}
|
||||
break;
|
||||
case RTCP_PAD:
|
||||
retpad = gst_object_ref (demuxpad->rtcp_pad);
|
||||
if (!demuxpad->pushed_initial_rtcp_events) {
|
||||
forward = TRUE;
|
||||
demuxpad->pushed_initial_rtcp_events = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
retpad = NULL;
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
GST_PAD_UNLOCK (demux);
|
||||
|
||||
if (forward)
|
||||
forward_initial_events (demux, ssrc, retpad, padtype);
|
||||
return retpad;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "creating new pad for SSRC %08x", ssrc);
|
||||
|
||||
klass = GST_ELEMENT_GET_CLASS (demux);
|
||||
templ = gst_element_class_get_pad_template (klass, "src_%u");
|
||||
padname = g_strdup_printf ("src_%u", ssrc);
|
||||
|
@ -262,8 +297,6 @@ find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
|
|||
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);
|
||||
|
||||
|
@ -275,18 +308,22 @@ find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
|
|||
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);
|
||||
|
||||
if (padtype == RTP_PAD) {
|
||||
demuxpad->pushed_initial_rtp_events = TRUE;
|
||||
forward_initial_events (demux, ssrc, rtp_pad, padtype);
|
||||
} else if (padtype == RTCP_PAD) {
|
||||
demuxpad->pushed_initial_rtcp_events = TRUE;
|
||||
forward_initial_events (demux, ssrc, rtcp_pad, padtype);
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
gst_element_add_pad (GST_ELEMENT_CAST (demux), rtp_pad);
|
||||
gst_element_add_pad (GST_ELEMENT_CAST (demux), rtcp_pad);
|
||||
|
@ -531,7 +568,11 @@ forward_event (GstPad * pad, gpointer user_data)
|
|||
for (walk = fdata->demux->srcpads; walk; walk = walk->next) {
|
||||
GstRtpSsrcDemuxPad *dpad = (GstRtpSsrcDemuxPad *) walk->data;
|
||||
|
||||
if (pad == dpad->rtp_pad || pad == dpad->rtcp_pad) {
|
||||
/* Only forward the event if the initial events have been through first,
|
||||
* the initial events should be forwarded before any other event
|
||||
* or buffer is pushed */
|
||||
if ((pad == dpad->rtp_pad && dpad->pushed_initial_rtp_events) ||
|
||||
(pad == dpad->rtcp_pad && dpad->pushed_initial_rtcp_events)) {
|
||||
newevent = add_ssrc_and_ref (fdata->event, dpad->ssrc);
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue