rtpssrcdemux: Release lock before signalling new pad

This prevents a deadlock where something would try to push an event
through the SSRC demux from the callback, causing the pads to be iterated
and the lock taken.
This commit is contained in:
Olivier Crête 2012-08-03 16:13:52 +01:00
parent c074bfd0b9
commit 2aa360c936

View file

@ -86,6 +86,12 @@ GST_STATIC_PAD_TEMPLATE ("rtcp_src_%u",
#define GST_PAD_LOCK(obj) (g_rec_mutex_lock (&(obj)->padlock)) #define GST_PAD_LOCK(obj) (g_rec_mutex_lock (&(obj)->padlock))
#define GST_PAD_UNLOCK(obj) (g_rec_mutex_unlock (&(obj)->padlock)) #define GST_PAD_UNLOCK(obj) (g_rec_mutex_unlock (&(obj)->padlock))
typedef enum
{
RTP_PAD,
RTCP_PAD
} PadType;
/* signals */ /* signals */
enum enum
{ {
@ -207,9 +213,9 @@ forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
} }
/* with PAD_LOCK */ static GstPad *
static GstRtpSsrcDemuxPad * find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc) PadType padtype)
{ {
GstPad *rtp_pad, *rtcp_pad; GstPad *rtp_pad, *rtcp_pad;
GstElementClass *klass; GstElementClass *klass;
@ -218,12 +224,26 @@ find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc)
GstRtpSsrcDemuxPad *demuxpad; GstRtpSsrcDemuxPad *demuxpad;
GstCaps *caps; GstCaps *caps;
struct ForwardEventData fdata; struct ForwardEventData fdata;
GstPad *retpad;
GST_DEBUG_OBJECT (demux, "creating pad for SSRC %08x", ssrc); GST_DEBUG_OBJECT (demux, "creating pad for SSRC %08x", ssrc);
GST_PAD_LOCK (demux);
demuxpad = find_demux_pad_for_ssrc (demux, ssrc); demuxpad = find_demux_pad_for_ssrc (demux, ssrc);
if (demuxpad != NULL) { 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); klass = GST_ELEMENT_GET_CLASS (demux);
@ -281,10 +301,27 @@ find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc)
gst_element_add_pad (GST_ELEMENT_CAST (demux), rtp_pad); gst_element_add_pad (GST_ELEMENT_CAST (demux), rtp_pad);
gst_element_add_pad (GST_ELEMENT_CAST (demux), rtcp_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), g_signal_emit (G_OBJECT (demux),
gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD], 0, ssrc, rtp_pad); gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD], 0, ssrc, rtp_pad);
return demuxpad; gst_object_unref (rtp_pad);
return retpad;
} }
static void static void
@ -574,7 +611,6 @@ gst_rtp_ssrc_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
GstFlowReturn ret; GstFlowReturn ret;
GstRtpSsrcDemux *demux; GstRtpSsrcDemux *demux;
guint32 ssrc; guint32 ssrc;
GstRtpSsrcDemuxPad *dpad;
GstRTPBuffer rtp = { NULL }; GstRTPBuffer rtp = { NULL };
GstPad *srcpad; GstPad *srcpad;
@ -588,14 +624,9 @@ gst_rtp_ssrc_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc); GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc);
GST_PAD_LOCK (demux); srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTP_PAD);
dpad = find_or_create_demux_pad_for_ssrc (demux, ssrc); if (srcpad == NULL)
if (dpad == NULL) {
GST_PAD_UNLOCK (demux);
goto create_failed; goto create_failed;
}
srcpad = gst_object_ref (dpad->rtp_pad);
GST_PAD_UNLOCK (demux);
/* push to srcpad */ /* push to srcpad */
ret = gst_pad_push (srcpad, buf); ret = gst_pad_push (srcpad, buf);
@ -629,7 +660,6 @@ gst_rtp_ssrc_demux_rtcp_chain (GstPad * pad, GstObject * parent,
GstFlowReturn ret; GstFlowReturn ret;
GstRtpSsrcDemux *demux; GstRtpSsrcDemux *demux;
guint32 ssrc; guint32 ssrc;
GstRtpSsrcDemuxPad *dpad;
GstRTCPPacket packet; GstRTCPPacket packet;
GstRTCPBuffer rtcp = { NULL, }; GstRTCPBuffer rtcp = { NULL, };
GstPad *srcpad; GstPad *srcpad;
@ -659,14 +689,9 @@ gst_rtp_ssrc_demux_rtcp_chain (GstPad * pad, GstObject * parent,
GST_DEBUG_OBJECT (demux, "received RTCP of SSRC %08x", ssrc); GST_DEBUG_OBJECT (demux, "received RTCP of SSRC %08x", ssrc);
GST_PAD_LOCK (demux); srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTCP_PAD);
dpad = find_or_create_demux_pad_for_ssrc (demux, ssrc); if (srcpad == NULL)
if (dpad == NULL) {
GST_PAD_UNLOCK (demux);
goto create_failed; goto create_failed;
}
srcpad = gst_object_ref (dpad->rtcp_pad);
GST_PAD_UNLOCK (demux);
/* push to srcpad */ /* push to srcpad */
ret = gst_pad_push (srcpad, buf); ret = gst_pad_push (srcpad, buf);