summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2007-10-08 10:39:35 +0000
committerTim-Philipp Müller <tim.muller@collabora.co.uk>2009-08-11 02:30:31 +0100
commit4556ccb666b0179a5adb3eddcaf28278f565250f (patch)
tree3a1d2493d269b14f031ae2814c98f3a0c500fd12
parent76a89b5e500952afb6d8d0c544848c7c99bb0427 (diff)
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.
-rw-r--r--gst/rtpmanager/gstrtpbin.c29
-rw-r--r--gst/rtpmanager/gstrtpptdemux.c104
-rw-r--r--gst/rtpmanager/gstrtpsession.c1
-rw-r--r--gst/rtpmanager/gstrtpssrcdemux.c2
4 files changed, 90 insertions, 46 deletions
diff --git a/gst/rtpmanager/gstrtpbin.c b/gst/rtpmanager/gstrtpbin.c
index 59ad01559..eddd137c3 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 b16426d19..8fd0ff4ce 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 8bf7adc47..85b8a55aa 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 472f5f55d..96e82ac2c 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;
}
}