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
This commit is contained in:
Mathieu Duponchelle 2017-11-28 01:11:54 +01:00
parent 36b991f0b3
commit 82d0950254
2 changed files with 87 additions and 0 deletions

View file

@ -114,6 +114,12 @@ enum
LAST_SIGNAL LAST_SIGNAL
}; };
enum
{
PROP_0,
PROP_IGNORED_PTS,
};
#define gst_rtp_pt_demux_parent_class parent_class #define gst_rtp_pt_demux_parent_class parent_class
G_DEFINE_TYPE (GstRtpPtDemux, gst_rtp_pt_demux, GST_TYPE_ELEMENT); G_DEFINE_TYPE (GstRtpPtDemux, gst_rtp_pt_demux, GST_TYPE_ELEMENT);
@ -138,6 +144,38 @@ static gboolean gst_rtp_pt_demux_src_event (GstPad * pad, GstObject * parent,
static guint gst_rtp_pt_demux_signals[LAST_SIGNAL] = { 0 }; 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 static void
gst_rtp_pt_demux_class_init (GstRtpPtDemuxClass * klass) gst_rtp_pt_demux_class_init (GstRtpPtDemuxClass * klass)
{ {
@ -199,6 +237,19 @@ gst_rtp_pt_demux_class_init (GstRtpPtDemuxClass * klass)
clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID, clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0, G_TYPE_NONE); 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; gobject_klass->finalize = gst_rtp_pt_demux_finalize;
gstelement_klass->change_state = gstelement_klass->change_state =
@ -234,6 +285,8 @@ gst_rtp_pt_demux_init (GstRtpPtDemux * ptdemux)
gst_pad_set_event_function (ptdemux->sink, gst_rtp_pt_demux_sink_event); gst_pad_set_event_function (ptdemux->sink, gst_rtp_pt_demux_sink_event);
gst_element_add_pad (GST_ELEMENT (ptdemux), ptdemux->sink); gst_element_add_pad (GST_ELEMENT (ptdemux), ptdemux->sink);
g_value_init (&ptdemux->ignored_pts, GST_TYPE_ARRAY);
} }
static void static void
@ -241,6 +294,8 @@ gst_rtp_pt_demux_finalize (GObject * object)
{ {
gst_rtp_pt_demux_release (GST_RTP_PT_DEMUX (object)); 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); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -356,6 +411,24 @@ forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
return TRUE; 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 static GstFlowReturn
gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{ {
@ -374,6 +447,9 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
pt = gst_rtp_buffer_get_payload_type (&rtp); pt = gst_rtp_buffer_get_payload_type (&rtp);
gst_rtp_buffer_unmap (&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); GST_DEBUG_OBJECT (rtpdemux, "received buffer for pt %d", pt);
srcpad = find_pad_for_pt (rtpdemux, pt); srcpad = find_pad_for_pt (rtpdemux, pt);
@ -388,6 +464,9 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
if (!caps) if (!caps)
goto no_caps; goto no_caps;
if (gst_rtp_pt_demux_pt_is_ignored (rtpdemux, pt))
goto ignored;
klass = GST_ELEMENT_GET_CLASS (rtpdemux); klass = GST_ELEMENT_GET_CLASS (rtpdemux);
templ = gst_element_class_get_pad_template (klass, "src_%u"); templ = gst_element_class_get_pad_template (klass, "src_%u");
padname = g_strdup_printf ("src_%u", pt); padname = g_strdup_printf ("src_%u", pt);
@ -461,6 +540,13 @@ gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
return ret; return ret;
ignored:
{
GST_DEBUG_OBJECT (rtpdemux, "Dropped buffer for pt %d", pt);
gst_buffer_unref (buf);
return GST_FLOW_OK;
}
/* ERRORS */ /* ERRORS */
invalid_buffer: invalid_buffer:
{ {

View file

@ -39,6 +39,7 @@ struct _GstRtpPtDemux
GstPad *sink; /**< the sink pad */ GstPad *sink; /**< the sink pad */
guint16 last_pt; /**< pt of the last packet 0xFFFF if none */ guint16 last_pt; /**< pt of the last packet 0xFFFF if none */
GSList *srcpads; /**< a linked list of GstRtpPtDemuxPad objects */ 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 struct _GstRtpPtDemuxClass