gst/rtpmanager/gstrtpbin.c: Fix caps refcounting for payload maps.
authorWim Taymans <wim.taymans@gmail.com>
Mon, 8 Oct 2007 10:39:35 +0000 (10:39 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Tue, 11 Aug 2009 01:30:31 +0000 (02:30 +0100)
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
gst/rtpmanager/gstrtpptdemux.c
gst/rtpmanager/gstrtpsession.c
gst/rtpmanager/gstrtpssrcdemux.c

index 59ad015..eddd137 100644 (file)
 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:
index b16426d..8fd0ff4 100644 (file)
@@ -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;
 }
 
index 8bf7adc..85b8a55 100644 (file)
@@ -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:
     {
index 472f5f5..96e82ac 100644 (file)
@@ -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;
     }
   }