rtpptdemux: Add ignored-payload-types property

Packets with these payload types will be dropped. A use case
for this is FEC, where we want FEC packets to go through the
jitterbuffer, but not be output by rtpbin.

https://bugzilla.gnome.org/show_bug.cgi?id=792696
diff --git a/gst/rtpmanager/gstrtpptdemux.c b/gst/rtpmanager/gstrtpptdemux.c
index f7d1e68..7a7fc6e 100644
--- a/gst/rtpmanager/gstrtpptdemux.c
+++ b/gst/rtpmanager/gstrtpptdemux.c
@@ -114,6 +114,12 @@
   LAST_SIGNAL
 };
 
+enum
+{
+  PROP_0,
+  PROP_IGNORED_PTS,
+};
+
 #define gst_rtp_pt_demux_parent_class parent_class
 G_DEFINE_TYPE (GstRtpPtDemux, gst_rtp_pt_demux, GST_TYPE_ELEMENT);
 
@@ -139,6 +145,38 @@
 static guint gst_rtp_pt_demux_signals[LAST_SIGNAL] = { 0 };
 
 static void
+gst_rtp_pt_demux_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstRtpPtDemux *rtpptdemux = GST_RTP_PT_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_IGNORED_PTS:
+      g_value_copy (value, &rtpptdemux->ignored_pts);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_rtp_pt_demux_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstRtpPtDemux *rtpptdemux = GST_RTP_PT_DEMUX (object);
+
+  switch (prop_id) {
+    case PROP_IGNORED_PTS:
+      g_value_copy (&rtpptdemux->ignored_pts, value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
 gst_rtp_pt_demux_class_init (GstRtpPtDemuxClass * klass)
 {
   GObjectClass *gobject_klass;
@@ -199,6 +237,19 @@
           clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID,
       G_TYPE_NONE, 0, G_TYPE_NONE);
 
+  gobject_klass->set_property = gst_rtp_pt_demux_set_property;
+  gobject_klass->get_property = gst_rtp_pt_demux_get_property;
+
+
+  g_object_class_install_property (gobject_klass, PROP_IGNORED_PTS,
+      gst_param_spec_array ("ignored-payload-types",
+          "Ignored payload types",
+          "Packets with these payload types will be dropped",
+          g_param_spec_int ("payload-types", "payload-types", "Payload types",
+              0, G_MAXINT, 0,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   gobject_klass->finalize = gst_rtp_pt_demux_finalize;
 
   gstelement_klass->change_state =
@@ -234,6 +285,8 @@
   gst_pad_set_event_function (ptdemux->sink, gst_rtp_pt_demux_sink_event);
 
   gst_element_add_pad (GST_ELEMENT (ptdemux), ptdemux->sink);
+
+  g_value_init (&ptdemux->ignored_pts, GST_TYPE_ARRAY);
 }
 
 static void
@@ -241,6 +294,8 @@
 {
   gst_rtp_pt_demux_release (GST_RTP_PT_DEMUX (object));
 
+  g_value_unset (&GST_RTP_PT_DEMUX (object)->ignored_pts);
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -356,6 +411,24 @@
   return TRUE;
 }
 
+static gboolean
+gst_rtp_pt_demux_pt_is_ignored (GstRtpPtDemux * ptdemux, guint8 pt)
+{
+  gboolean ret = FALSE;
+  guint i;
+
+  for (i = 0; i < gst_value_array_get_size (&ptdemux->ignored_pts); i++) {
+    const GValue *tmp = gst_value_array_get_value (&ptdemux->ignored_pts, i);
+
+    if (g_value_get_int (tmp) == pt) {
+      ret = TRUE;
+      break;
+    }
+  }
+
+  return ret;
+}
+
 static GstFlowReturn
 gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
@@ -374,6 +447,9 @@
   pt = gst_rtp_buffer_get_payload_type (&rtp);
   gst_rtp_buffer_unmap (&rtp);
 
+  if (gst_rtp_pt_demux_pt_is_ignored (rtpdemux, pt))
+    goto ignored;
+
   GST_DEBUG_OBJECT (rtpdemux, "received buffer for pt %d", pt);
 
   srcpad = find_pad_for_pt (rtpdemux, pt);
@@ -388,6 +464,9 @@
     if (!caps)
       goto no_caps;
 
+    if (gst_rtp_pt_demux_pt_is_ignored (rtpdemux, pt))
+      goto ignored;
+
     klass = GST_ELEMENT_GET_CLASS (rtpdemux);
     templ = gst_element_class_get_pad_template (klass, "src_%u");
     padname = g_strdup_printf ("src_%u", pt);
@@ -461,6 +540,13 @@
 
   return ret;
 
+ignored:
+  {
+    GST_DEBUG_OBJECT (rtpdemux, "Dropped buffer for pt %d", pt);
+    gst_buffer_unref (buf);
+    return GST_FLOW_OK;
+  }
+
   /* ERRORS */
 invalid_buffer:
   {
diff --git a/gst/rtpmanager/gstrtpptdemux.h b/gst/rtpmanager/gstrtpptdemux.h
index aa1bb7f..578e489 100644
--- a/gst/rtpmanager/gstrtpptdemux.h
+++ b/gst/rtpmanager/gstrtpptdemux.h
@@ -39,6 +39,7 @@
   GstPad *sink;       /**< the sink pad */
   guint16 last_pt;    /**< pt of the last packet 0xFFFF if none */
   GSList *srcpads;    /**< a linked list of GstRtpPtDemuxPad objects */
+  GValue ignored_pts; /**< a GstValueArray of payload types that will not have pads created for */
 };
 
 struct _GstRtpPtDemuxClass