From 4865b3bf146fe7392aed1a9e2df2efcb63d19ead Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 8 Oct 2007 10:39:35 +0000 Subject: gst/rtpmanager/gstrtpbin.c: Fix caps refcounting for payload maps. Original commit message from CVS: * gst/rtpmanager/gstrtpbin.c: (get_pt_map), (gst_rtp_bin_clear_pt_map), (gst_rtp_bin_class_init): Fix caps refcounting for payload maps. When clearing payload maps, also clear sessions and streams payload maps. * gst/rtpmanager/gstrtpptdemux.c: (gst_rtp_pt_demux_get_caps), (gst_rtp_pt_demux_clear_pt_map), (gst_rtp_pt_demux_chain), (find_pad_for_pt): Implement clearing the payload map. * gst/rtpmanager/gstrtpsession.c: (gst_rtp_session_event_send_rtp_sink): Forward flush events instead of leaking them. * gst/rtpmanager/gstrtpssrcdemux.c: (gst_rtp_ssrc_demux_rtcp_sink_event): Correctly refcount events before pushing them. --- gst/rtpmanager/gstrtpbin.c | 29 ++++++----- gst/rtpmanager/gstrtpptdemux.c | 104 ++++++++++++++++++++++++++------------- gst/rtpmanager/gstrtpsession.c | 1 + gst/rtpmanager/gstrtpssrcdemux.c | 2 + 4 files changed, 90 insertions(+), 46 deletions(-) (limited to 'gst') diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c index 59ad0155..eddd137c 100644 --- a/gst/rtpmanager/gstrtpbin.c +++ b/gst/rtpmanager/gstrtpbin.c @@ -140,7 +140,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_rtp_bin_debug); #define GST_CAT_DEFAULT gst_rtp_bin_debug - /* elementfactory information */ static const GstElementDetails rtpbin_details = GST_ELEMENT_DETAILS ("RTP Bin", "Filter/Network/RTP", @@ -562,6 +561,7 @@ get_pt_map (GstRtpBinSession * session, guint pt) g_hash_table_insert (session->ptmap, GINT_TO_POINTER (pt), caps); done: + gst_caps_ref (caps); GST_RTP_SESSION_UNLOCK (session); return caps; @@ -584,20 +584,26 @@ return_true (gpointer key, gpointer value, gpointer user_data) static void gst_rtp_bin_clear_pt_map (GstRtpBin * bin) { - GSList *walk; + GSList *sessions, *streams; GST_RTP_BIN_LOCK (bin); GST_DEBUG_OBJECT (bin, "clearing pt map"); - for (walk = bin->sessions; walk; walk = g_slist_next (walk)) { - GstRtpBinSession *session = (GstRtpBinSession *) walk->data; + for (sessions = bin->sessions; sessions; sessions = g_slist_next (sessions)) { + GstRtpBinSession *session = (GstRtpBinSession *) sessions->data; + + GST_DEBUG_OBJECT (bin, "clearing session %p", session); + g_signal_emit_by_name (session->session, "clear-pt-map", NULL); GST_RTP_SESSION_LOCK (session); -#if 0 - /* This requires GLib 2.12 */ - g_hash_table_remove_all (session->ptmap); -#else g_hash_table_foreach_remove (session->ptmap, return_true, NULL); -#endif + + for (streams = session->streams; streams; streams = g_slist_next (streams)) { + GstRtpBinStream *stream = (GstRtpBinStream *) streams->data; + + GST_DEBUG_OBJECT (bin, "clearing stream %p", stream); + g_signal_emit_by_name (stream->buffer, "clear-pt-map", NULL); + g_signal_emit_by_name (stream->demux, "clear-pt-map", NULL); + } GST_RTP_SESSION_UNLOCK (session); } GST_RTP_BIN_UNLOCK (bin); @@ -1049,8 +1055,9 @@ gst_rtp_bin_class_init (GstRtpBinClass * klass) */ gst_rtp_bin_signals[SIGNAL_CLEAR_PT_MAP] = g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, clear_pt_map), - NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstRtpBinClass, + clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, + 0, G_TYPE_NONE); /** * GstRtpBin::on-new-ssrc: diff --git a/gst/rtpmanager/gstrtpptdemux.c b/gst/rtpmanager/gstrtpptdemux.c index b16426d1..8fd0ff4c 100644 --- a/gst/rtpmanager/gstrtpptdemux.c +++ b/gst/rtpmanager/gstrtpptdemux.c @@ -109,6 +109,7 @@ struct _GstRtpPtDemuxPad { GstPad *pad; /**< pointer to the actual pad */ gint pt; /**< RTP payload-type attached to pad */ + gboolean newcaps; }; /* signals */ @@ -133,7 +134,7 @@ static GstStateChangeReturn gst_rtp_pt_demux_change_state (GstElement * element, GstStateChange transition); static void gst_rtp_pt_demux_clear_pt_map (GstRtpPtDemux * rtpdemux); -static GstPad *find_pad_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt); +static GstRtpPtDemuxPad *find_pad_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt); static guint gst_rtp_pt_demux_signals[LAST_SIGNAL] = { 0 }; @@ -253,10 +254,47 @@ gst_rtp_pt_demux_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static GstCaps * +gst_rtp_pt_demux_get_caps (GstRtpPtDemux * rtpdemux, guint pt) +{ + GstCaps *caps; + GValue ret = { 0 }; + GValue args[2] = { {0}, {0} }; + + /* figure out the caps */ + g_value_init (&args[0], GST_TYPE_ELEMENT); + g_value_set_object (&args[0], rtpdemux); + g_value_init (&args[1], G_TYPE_UINT); + g_value_set_uint (&args[1], pt); + + g_value_init (&ret, GST_TYPE_CAPS); + g_value_set_boxed (&ret, NULL); + + g_signal_emitv (args, gst_rtp_pt_demux_signals[SIGNAL_REQUEST_PT_MAP], 0, + &ret); + + caps = g_value_get_boxed (&ret); + if (caps == NULL) + caps = GST_PAD_CAPS (rtpdemux->sink); + + GST_DEBUG ("pt %d, got caps %" GST_PTR_FORMAT, pt, caps); + + return caps; +} + static void gst_rtp_pt_demux_clear_pt_map (GstRtpPtDemux * rtpdemux) { - /* FIXME, do something */ + GSList *walk; + + GST_OBJECT_LOCK (rtpdemux); + GST_DEBUG ("clearing pt map"); + for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) { + GstRtpPtDemuxPad *pad = walk->data; + + pad->newcaps = TRUE; + } + GST_OBJECT_UNLOCK (rtpdemux); } static GstFlowReturn @@ -267,6 +305,8 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf) GstElement *element = GST_ELEMENT (GST_OBJECT_PARENT (pad)); guint8 pt; GstPad *srcpad; + GstRtpPtDemuxPad *rtpdemuxpad; + GstCaps *caps; rtpdemux = GST_RTP_PT_DEMUX (GST_OBJECT_PARENT (pad)); @@ -277,19 +317,12 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf) GST_DEBUG_OBJECT (rtpdemux, "received buffer for pt %d", pt); - srcpad = find_pad_for_pt (rtpdemux, pt); - if (srcpad == NULL) { + rtpdemuxpad = find_pad_for_pt (rtpdemux, pt); + if (rtpdemuxpad == NULL) { /* new PT, create a src pad */ GstElementClass *klass; GstPadTemplate *templ; gchar *padname; - GstCaps *caps; - GstRtpPtDemuxPad *rtpdemuxpad; - GValue ret = { 0 }; - GValue args[2] = { {0} - , {0} - }; - klass = GST_ELEMENT_GET_CLASS (rtpdemux); templ = gst_element_class_get_pad_template (klass, "src_%d"); @@ -298,21 +331,7 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf) gst_pad_use_fixed_caps (srcpad); g_free (padname); - /* figure out the caps */ - g_value_init (&args[0], GST_TYPE_ELEMENT); - g_value_set_object (&args[0], rtpdemux); - g_value_init (&args[1], G_TYPE_UINT); - g_value_set_uint (&args[1], pt); - - g_value_init (&ret, GST_TYPE_CAPS); - g_value_set_boxed (&ret, NULL); - - g_signal_emitv (args, gst_rtp_pt_demux_signals[SIGNAL_REQUEST_PT_MAP], 0, - &ret); - - caps = g_value_get_boxed (&ret); - if (caps == NULL) - caps = GST_PAD_CAPS (rtpdemux->sink); + caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt); if (!caps) goto no_caps; @@ -323,8 +342,11 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf) GST_DEBUG ("Adding pt=%d to the list.", pt); rtpdemuxpad = g_new0 (GstRtpPtDemuxPad, 1); rtpdemuxpad->pt = pt; + rtpdemuxpad->newcaps = FALSE; rtpdemuxpad->pad = srcpad; + GST_OBJECT_LOCK (rtpdemux); rtpdemux->srcpads = g_slist_append (rtpdemux->srcpads, rtpdemuxpad); + GST_OBJECT_UNLOCK (rtpdemux); gst_pad_set_active (srcpad, TRUE); gst_element_add_pad (element, srcpad); @@ -334,6 +356,8 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf) gst_rtp_pt_demux_signals[SIGNAL_NEW_PAYLOAD_TYPE], 0, pt, srcpad); } + srcpad = rtpdemuxpad->pad; + if (pt != rtpdemux->last_pt) { gint emit_pt = pt; @@ -344,11 +368,22 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf) gst_rtp_pt_demux_signals[SIGNAL_PAYLOAD_TYPE_CHANGE], 0, emit_pt); } + if (rtpdemuxpad->newcaps) { + GST_DEBUG ("need new caps"); + caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt); + if (!caps) + goto no_caps; + + caps = gst_caps_make_writable (caps); + gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL); + gst_pad_set_caps (srcpad, caps); + rtpdemuxpad->newcaps = FALSE; + } + gst_buffer_set_caps (buf, GST_PAD_CAPS (srcpad)); /* push to srcpad */ - if (srcpad) - ret = gst_pad_push (srcpad, GST_BUFFER (buf)); + ret = gst_pad_push (srcpad, buf); return ret; @@ -370,21 +405,20 @@ no_caps: } } -static GstPad * +static GstRtpPtDemuxPad * find_pad_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt) { - GstPad *respad = NULL; - GSList *item = rtpdemux->srcpads; + GstRtpPtDemuxPad *respad = NULL; + GSList *walk; - for (; item; item = g_slist_next (item)) { - GstRtpPtDemuxPad *pad = item->data; + for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) { + GstRtpPtDemuxPad *pad = walk->data; if (pad->pt == pt) { - respad = pad->pad; + respad = pad; break; } } - return respad; } diff --git a/gst/rtpmanager/gstrtpsession.c b/gst/rtpmanager/gstrtpsession.c index 8bf7adc4..85b8a55a 100644 --- a/gst/rtpmanager/gstrtpsession.c +++ b/gst/rtpmanager/gstrtpsession.c @@ -1219,6 +1219,7 @@ gst_rtp_session_event_send_rtp_sink (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: gst_segment_init (&rtpsession->send_rtp_seg, GST_FORMAT_UNDEFINED); + ret = gst_pad_push_event (rtpsession->send_rtp_src, event); break; case GST_EVENT_NEWSEGMENT: { diff --git a/gst/rtpmanager/gstrtpssrcdemux.c b/gst/rtpmanager/gstrtpssrcdemux.c index 472f5f55..96e82ac2 100644 --- a/gst/rtpmanager/gstrtpssrcdemux.c +++ b/gst/rtpmanager/gstrtpssrcdemux.c @@ -386,9 +386,11 @@ gst_rtp_ssrc_demux_rtcp_sink_event (GstPad * pad, GstEvent * event) for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) { GstRtpSsrcDemuxPad *pad = (GstRtpSsrcDemuxPad *) walk->data; + gst_event_ref (event); res &= gst_pad_push_event (pad->rtcp_pad, event); } GST_PAD_UNLOCK (demux); + gst_event_unref (event); break; } } -- cgit v1.2.1