* @author Kai Vehmanen <kai.vehmanen@nokia.com>
*
* Loosely based on GStreamer gstdecodebin
- * Copyright (C) <2004> Wim Taymans <wim@fluendo.com>
+ * Copyright (C) <2004> Wim Taymans <wim.taymans@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*/
/**
* SECTION:element-gstrtpptdemux
- * @short_description: separate RTP payloads based on the payload type
*
- * <refsect2>
- * <para>
- * gstrtpptdemux acts as a demuxer for RTP packets based on the payload type of the
- * packets. Its main purpose is to allow an application to easily receive and
- * decode an RTP stream with multiple payload types.
- * </para>
- * <para>
+ * gstrtpptdemux acts as a demuxer for RTP packets based on the payload type of
+ * the packets. Its main purpose is to allow an application to easily receive
+ * and decode an RTP stream with multiple payload types.
+ *
* For each payload type that is detected, a new pad will be created and the
- * ::new-payload-type signal will be emitted. When the payload for the RTP
- * stream changes, the ::payload-type-change signal will be emitted.
- * </para>
- * <para>
+ * #GstRtpPtDemux::new-payload-type signal will be emitted. When the payload for
+ * the RTP stream changes, the #GstRtpPtDemux::payload-type-change signal will be
+ * emitted.
+ *
* The element will try to set complete and unique application/x-rtp caps on the
- * outgoing buffers and pads based on the result of the ::request-pt-map signal.
- * </para>
+ * outgoing buffers and pads based on the result of the
+ * #GstRtpPtDemux::request-pt-map signal.
+ *
+ * <refsect2>
* <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * gst-launch udpsrc caps="application/x-rtp" ! gstrtpptdemux ! fakesink
- * </programlisting>
- * Takes an RTP stream and send the RTP packets with the first detected payload
- * type to fakesink, discarding the other payload types.
- * </para>
+ * |[
+ * gst-launch-1.0 udpsrc caps="application/x-rtp" ! gstrtpptdemux ! fakesink
+ * ]| Takes an RTP stream and send the RTP packets with the first detected
+ * payload type to fakesink, discarding the other payload types.
* </refsect2>
*
* Last reviewed on 2007-05-28 (0.10.5)
);
static GstStaticPadTemplate rtp_pt_demux_src_template =
-GST_STATIC_PAD_TEMPLATE ("src_%d",
+GST_STATIC_PAD_TEMPLATE ("src_%u",
GST_PAD_SRC,
GST_PAD_SOMETIMES,
GST_STATIC_CAPS ("application/x-rtp, " "payload = (int) [ 0, 255 ]")
GST_DEBUG_CATEGORY_STATIC (gst_rtp_pt_demux_debug);
#define GST_CAT_DEFAULT gst_rtp_pt_demux_debug
-/**
+/*
* Item for storing GstPad<->pt pairs.
*/
-struct _GstRTPPtDemuxPad
+struct _GstRtpPtDemuxPad
{
GstPad *pad; /**< pointer to the actual pad */
gint pt; /**< RTP payload-type attached to pad */
+ gboolean newcaps;
};
/* signals */
LAST_SIGNAL
};
-GST_BOILERPLATE (GstRTPPtDemux, gst_rtp_pt_demux, GstElement, GST_TYPE_ELEMENT);
+#define gst_rtp_pt_demux_parent_class parent_class
+G_DEFINE_TYPE (GstRtpPtDemux, gst_rtp_pt_demux, GST_TYPE_ELEMENT);
static void gst_rtp_pt_demux_finalize (GObject * object);
-static void gst_rtp_pt_demux_release (GstElement * element);
-static gboolean gst_rtp_pt_demux_setup (GstElement * element);
+static void gst_rtp_pt_demux_release (GstRtpPtDemux * ptdemux);
+static gboolean gst_rtp_pt_demux_setup (GstRtpPtDemux * ptdemux);
-static GstFlowReturn gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_rtp_pt_demux_sink_event (GstPad * pad, GstObject * parent,
+ GstEvent * event);
+static GstFlowReturn gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent,
+ GstBuffer * buf);
static GstStateChangeReturn gst_rtp_pt_demux_change_state (GstElement * element,
GstStateChange transition);
-static void gst_rtp_pt_demux_clear_pt_map (GstRTPPtDemux * rtpdemux);
+static void gst_rtp_pt_demux_clear_pt_map (GstRtpPtDemux * rtpdemux);
-static GstPad *find_pad_for_pt (GstRTPPtDemux * rtpdemux, guint8 pt);
+static GstPad *find_pad_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt);
-static guint gst_rtp_pt_demux_signals[LAST_SIGNAL] = { 0 };
+static gboolean gst_rtp_pt_demux_src_event (GstPad * pad, GstObject * parent,
+ GstEvent * event);
-static GstElementDetails gst_rtp_pt_demux_details = {
- "RTP Demux",
- "Demux/Network/RTP",
- "Parses codec streams transmitted in the same RTP session",
- "Kai Vehmanen <kai.vehmanen@nokia.com>"
-};
-static void
-gst_rtp_pt_demux_base_init (gpointer g_class)
-{
- GstElementClass *gstelement_klass = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (gstelement_klass,
- gst_static_pad_template_get (&rtp_pt_demux_sink_template));
- gst_element_class_add_pad_template (gstelement_klass,
- gst_static_pad_template_get (&rtp_pt_demux_src_template));
-
- gst_element_class_set_details (gstelement_klass, &gst_rtp_pt_demux_details);
-}
+static guint gst_rtp_pt_demux_signals[LAST_SIGNAL] = { 0 };
static void
-gst_rtp_pt_demux_class_init (GstRTPPtDemuxClass * klass)
+gst_rtp_pt_demux_class_init (GstRtpPtDemuxClass * klass)
{
GObjectClass *gobject_klass;
GstElementClass *gstelement_klass;
gstelement_klass = (GstElementClass *) klass;
/**
- * GstRTPPtDemux::request-pt-map:
+ * GstRtpPtDemux::request-pt-map:
* @demux: the object which received the signal
* @pt: the payload type
*
*/
gst_rtp_pt_demux_signals[SIGNAL_REQUEST_PT_MAP] =
g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass, request_pt_map),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass, request_pt_map),
NULL, NULL, gst_rtp_bin_marshal_BOXED__UINT, GST_TYPE_CAPS, 1,
G_TYPE_UINT);
/**
- * GstRTPPtDemux::new-payload-type:
+ * GstRtpPtDemux::new-payload-type:
* @demux: the object which received the signal
* @pt: the payload type
* @pad: the pad with the new payload
*/
gst_rtp_pt_demux_signals[SIGNAL_NEW_PAYLOAD_TYPE] =
g_signal_new ("new-payload-type", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass, new_payload_type),
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass, new_payload_type),
NULL, NULL, gst_rtp_bin_marshal_VOID__UINT_OBJECT, G_TYPE_NONE, 2,
G_TYPE_UINT, GST_TYPE_PAD);
/**
- * GstRTPPtDemux::payload-type-change:
+ * GstRtpPtDemux::payload-type-change:
* @demux: the object which received the signal
* @pt: the new payload type
*
*/
gst_rtp_pt_demux_signals[SIGNAL_PAYLOAD_TYPE_CHANGE] =
g_signal_new ("payload-type-change", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass,
+ G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass,
payload_type_change), NULL, NULL, g_cclosure_marshal_VOID__UINT,
G_TYPE_NONE, 1, G_TYPE_UINT);
/**
- * GstRTPPtDemux::clear-pt-map:
+ * GstRtpPtDemux::clear-pt-map:
* @demux: the object which received the signal
*
* The application can call this signal to instruct the element to discard the
*/
gst_rtp_pt_demux_signals[SIGNAL_CLEAR_PT_MAP] =
g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTPPtDemuxClass,
+ G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass,
clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0, G_TYPE_NONE);
- gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_finalize);
+ gobject_klass->finalize = gst_rtp_pt_demux_finalize;
gstelement_klass->change_state =
GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_change_state);
klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_clear_pt_map);
+ gst_element_class_add_pad_template (gstelement_klass,
+ gst_static_pad_template_get (&rtp_pt_demux_sink_template));
+ gst_element_class_add_pad_template (gstelement_klass,
+ gst_static_pad_template_get (&rtp_pt_demux_src_template));
+
+ gst_element_class_set_static_metadata (gstelement_klass, "RTP Demux",
+ "Demux/Network/RTP",
+ "Parses codec streams transmitted in the same RTP session",
+ "Kai Vehmanen <kai.vehmanen@nokia.com>");
+
GST_DEBUG_CATEGORY_INIT (gst_rtp_pt_demux_debug,
"rtpptdemux", 0, "RTP codec demuxer");
}
static void
-gst_rtp_pt_demux_init (GstRTPPtDemux * ptdemux, GstRTPPtDemuxClass * g_class)
+gst_rtp_pt_demux_init (GstRtpPtDemux * ptdemux)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (ptdemux);
g_assert (ptdemux->sink != NULL);
gst_pad_set_chain_function (ptdemux->sink, gst_rtp_pt_demux_chain);
+ gst_pad_set_event_function (ptdemux->sink, gst_rtp_pt_demux_sink_event);
gst_element_add_pad (GST_ELEMENT (ptdemux), ptdemux->sink);
}
static void
gst_rtp_pt_demux_finalize (GObject * object)
{
- gst_rtp_pt_demux_release (GST_ELEMENT (object));
+ gst_rtp_pt_demux_release (GST_RTP_PT_DEMUX (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);
+
+ g_value_unset (&args[0]);
+ g_value_unset (&args[1]);
+ caps = g_value_dup_boxed (&ret);
+ g_value_unset (&ret);
+ if (caps == NULL) {
+ caps = gst_pad_get_current_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)
+{
+ 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 gboolean
+need_caps_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt)
+{
+ GSList *walk;
+ gboolean ret = FALSE;
+
+ GST_OBJECT_LOCK (rtpdemux);
+ for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) {
+ GstRtpPtDemuxPad *pad = walk->data;
+
+ if (pad->pt == pt) {
+ ret = pad->newcaps;
+ }
+ }
+ GST_OBJECT_UNLOCK (rtpdemux);
+
+ return ret;
+}
+
+
static void
-gst_rtp_pt_demux_clear_pt_map (GstRTPPtDemux * rtpdemux)
+clear_newcaps_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt)
{
- /* FIXME, do something */
+ GSList *walk;
+
+ GST_OBJECT_LOCK (rtpdemux);
+ for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) {
+ GstRtpPtDemuxPad *pad = walk->data;
+
+ if (pad->pt == pt) {
+ pad->newcaps = FALSE;
+ break;
+ }
+ }
+ GST_OBJECT_UNLOCK (rtpdemux);
+}
+
+static gboolean
+forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
+{
+ GstPad *srcpad = GST_PAD_CAST (user_data);
+
+ gst_pad_push_event (srcpad, gst_event_ref (*event));
+
+ return TRUE;
}
static GstFlowReturn
-gst_rtp_pt_demux_chain (GstPad * pad, GstBuffer * buf)
+gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
GstFlowReturn ret = GST_FLOW_OK;
- GstRTPPtDemux *rtpdemux;
- GstElement *element = GST_ELEMENT (GST_OBJECT_PARENT (pad));
+ GstRtpPtDemux *rtpdemux;
guint8 pt;
GstPad *srcpad;
+ GstCaps *caps;
+ GstRTPBuffer rtp = { NULL };
- rtpdemux = GST_RTP_PT_DEMUX (GST_OBJECT_PARENT (pad));
+ rtpdemux = GST_RTP_PT_DEMUX (parent);
- if (!gst_rtp_buffer_validate (buf))
+ if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp))
goto invalid_buffer;
- pt = gst_rtp_buffer_get_payload_type (buf);
+ pt = gst_rtp_buffer_get_payload_type (&rtp);
+ gst_rtp_buffer_unmap (&rtp);
GST_DEBUG_OBJECT (rtpdemux, "received buffer for pt %d", pt);
srcpad = find_pad_for_pt (rtpdemux, pt);
if (srcpad == NULL) {
/* new PT, create a src pad */
+ GstRtpPtDemuxPad *rtpdemuxpad;
GstElementClass *klass;
GstPadTemplate *templ;
gchar *padname;
- GstCaps *caps;
- GstRTPPtDemuxPad *rtpdemuxpad;
- GValue ret = { 0 };
- GValue args[2] = { {0}
- , {0}
- };
+ caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt);
+ if (!caps)
+ goto no_caps;
klass = GST_ELEMENT_GET_CLASS (rtpdemux);
- templ = gst_element_class_get_pad_template (klass, "src_%d");
- padname = g_strdup_printf ("src_%d", pt);
+ templ = gst_element_class_get_pad_template (klass, "src_%u");
+ padname = g_strdup_printf ("src_%u", pt);
srcpad = gst_pad_new_from_template (templ, padname);
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);
- 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);
+ gst_pad_set_event_function (srcpad, gst_rtp_pt_demux_src_event);
GST_DEBUG ("Adding pt=%d to the list.", pt);
- rtpdemuxpad = g_new0 (GstRTPPtDemuxPad, 1);
+ rtpdemuxpad = g_slice_new0 (GstRtpPtDemuxPad);
rtpdemuxpad->pt = pt;
+ rtpdemuxpad->newcaps = FALSE;
rtpdemuxpad->pad = srcpad;
+ gst_object_ref (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);
- GST_DEBUG ("emitting new-payload_type for pt %d", pt);
+ caps = gst_caps_make_writable (caps);
+ gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
+ gst_pad_set_caps (srcpad, caps);
+ gst_caps_unref (caps);
+
+ gst_pad_sticky_events_foreach (rtpdemux->sink, forward_sticky_events,
+ srcpad);
+ gst_element_add_pad (GST_ELEMENT_CAST (rtpdemux), srcpad);
+
+ GST_DEBUG ("emitting new-payload-type for pt %d", pt);
g_signal_emit (G_OBJECT (rtpdemux),
gst_rtp_pt_demux_signals[SIGNAL_NEW_PAYLOAD_TYPE], 0, pt, srcpad);
}
gst_rtp_pt_demux_signals[SIGNAL_PAYLOAD_TYPE_CHANGE], 0, emit_pt);
}
- gst_buffer_set_caps (buf, GST_PAD_CAPS (srcpad));
+ while (need_caps_for_pt (rtpdemux, pt)) {
+ GST_DEBUG ("need new caps for %d", pt);
+ caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt);
+ if (!caps)
+ goto no_caps;
+
+ clear_newcaps_for_pt (rtpdemux, pt);
+
+ caps = gst_caps_make_writable (caps);
+ gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
+ gst_pad_set_caps (srcpad, caps);
+ gst_caps_unref (caps);
+ }
/* push to srcpad */
- if (srcpad)
- ret = gst_pad_push (srcpad, GST_BUFFER (buf));
+ ret = gst_pad_push (srcpad, buf);
+
+ gst_object_unref (srcpad);
return ret;
GST_ELEMENT_ERROR (rtpdemux, STREAM, DECODE, (NULL),
("Could not get caps for payload"));
gst_buffer_unref (buf);
+ if (srcpad)
+ gst_object_unref (srcpad);
return GST_FLOW_ERROR;
}
}
static GstPad *
-find_pad_for_pt (GstRTPPtDemux * rtpdemux, guint8 pt)
+find_pad_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt)
{
GstPad *respad = NULL;
- GSList *item = rtpdemux->srcpads;
+ GSList *walk;
- for (; item; item = g_slist_next (item)) {
- GstRTPPtDemuxPad *pad = item->data;
+ GST_OBJECT_LOCK (rtpdemux);
+ for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) {
+ GstRtpPtDemuxPad *pad = walk->data;
if (pad->pt == pt) {
- respad = pad->pad;
+ respad = gst_object_ref (pad->pad);
break;
}
}
+ GST_OBJECT_UNLOCK (rtpdemux);
return respad;
}
-/**
- * Reserves resources for the object.
- */
static gboolean
-gst_rtp_pt_demux_setup (GstElement * element)
+gst_rtp_pt_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
- GstRTPPtDemux *ptdemux = GST_RTP_PT_DEMUX (element);
- gboolean res = TRUE;
+ GstRtpPtDemux *rtpdemux;
+ gboolean res = FALSE;
+
+ rtpdemux = GST_RTP_PT_DEMUX (parent);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ gst_rtp_pt_demux_clear_pt_map (rtpdemux);
+ /* don't forward the event, we cleared the ptmap and on the next buffer we
+ * will add the pt to the caps and push a new caps event */
+ gst_event_unref (event);
+ res = TRUE;
+ break;
+ }
+ case GST_EVENT_CUSTOM_DOWNSTREAM:
+ {
+ const GstStructure *s;
- if (ptdemux) {
- ptdemux->srcpads = NULL;
- ptdemux->last_pt = 0xFFFF;
+ s = gst_event_get_structure (event);
+
+ if (gst_structure_has_name (s, "GstRTPPacketLost")) {
+ GstPad *srcpad = find_pad_for_pt (rtpdemux, rtpdemux->last_pt);
+
+ if (srcpad) {
+ res = gst_pad_push_event (srcpad, event);
+ gst_object_unref (srcpad);
+ } else {
+ gst_event_unref (event);
+ }
+
+ } else {
+ res = gst_pad_event_default (pad, parent, event);
+ }
+ break;
+ }
+ default:
+ res = gst_pad_event_default (pad, parent, event);
+ break;
}
return res;
}
-/**
+
+static gboolean
+gst_rtp_pt_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
+{
+ GstRtpPtDemux *demux;
+ const GstStructure *s;
+
+ demux = GST_RTP_PT_DEMUX (parent);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CUSTOM_UPSTREAM:
+ case GST_EVENT_CUSTOM_BOTH:
+ case GST_EVENT_CUSTOM_BOTH_OOB:
+ s = gst_event_get_structure (event);
+ if (s && !gst_structure_has_field (s, "payload")) {
+ GSList *walk;
+
+ GST_OBJECT_LOCK (demux);
+ for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
+ GstRtpPtDemuxPad *dpad = (GstRtpPtDemuxPad *) walk->data;
+
+ if (dpad->pad == pad) {
+ GstStructure *ws;
+
+ event =
+ GST_EVENT_CAST (gst_mini_object_make_writable
+ (GST_MINI_OBJECT_CAST (event)));
+ ws = gst_event_writable_structure (event);
+ gst_structure_set (ws, "payload", G_TYPE_UINT, dpad->pt, NULL);
+ break;
+ }
+ }
+ GST_OBJECT_UNLOCK (demux);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return gst_pad_event_default (pad, parent, event);
+}
+
+/*
+ * Reserves resources for the object.
+ */
+static gboolean
+gst_rtp_pt_demux_setup (GstRtpPtDemux * ptdemux)
+{
+ ptdemux->srcpads = NULL;
+ ptdemux->last_pt = 0xFFFF;
+
+ return TRUE;
+}
+
+/*
* Free resources for the object.
*/
static void
-gst_rtp_pt_demux_release (GstElement * element)
+gst_rtp_pt_demux_release (GstRtpPtDemux * ptdemux)
{
- GstRTPPtDemux *ptdemux = GST_RTP_PT_DEMUX (element);
+ GSList *tmppads;
+ GSList *walk;
+
+ GST_OBJECT_LOCK (ptdemux);
+ tmppads = ptdemux->srcpads;
+ ptdemux->srcpads = NULL;
+ GST_OBJECT_UNLOCK (ptdemux);
+
+ for (walk = tmppads; walk; walk = g_slist_next (walk)) {
+ GstRtpPtDemuxPad *pad = walk->data;
- if (ptdemux) {
- /* note: GstElement's dispose() will handle the pads */
- g_slist_free (ptdemux->srcpads);
- ptdemux->srcpads = NULL;
+ gst_pad_set_active (pad->pad, FALSE);
+ gst_element_remove_pad (GST_ELEMENT_CAST (ptdemux), pad->pad);
+ g_slice_free (GstRtpPtDemuxPad, pad);
}
+ g_slist_free (tmppads);
}
static GstStateChangeReturn
gst_rtp_pt_demux_change_state (GstElement * element, GstStateChange transition)
{
GstStateChangeReturn ret;
- GstRTPPtDemux *ptdemux;
+ GstRtpPtDemux *ptdemux;
ptdemux = GST_RTP_PT_DEMUX (element);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
- if (gst_rtp_pt_demux_setup (element) != TRUE)
+ if (gst_rtp_pt_demux_setup (ptdemux) != TRUE)
ret = GST_STATE_CHANGE_FAILURE;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
case GST_STATE_CHANGE_PAUSED_TO_READY:
break;
case GST_STATE_CHANGE_READY_TO_NULL:
- gst_rtp_pt_demux_release (element);
+ gst_rtp_pt_demux_release (ptdemux);
break;
default:
break;