rtpmanager: use generic marshaller
[platform/upstream/gst-plugins-good.git] / gst / rtpmanager / gstrtpptdemux.c
1 /* 
2  * RTP Demux element
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  * @author Kai Vehmanen <kai.vehmanen@nokia.com>
6  *
7  * Loosely based on GStreamer gstdecodebin
8  * Copyright (C) <2004> Wim Taymans <wim.taymans@gmail.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the
22  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 /**
27  * SECTION:element-gstrtpptdemux
28  *
29  * gstrtpptdemux acts as a demuxer for RTP packets based on the payload type of
30  * the packets. Its main purpose is to allow an application to easily receive
31  * and decode an RTP stream with multiple payload types.
32  * 
33  * For each payload type that is detected, a new pad will be created and the
34  * #GstRtpPtDemux::new-payload-type signal will be emitted. When the payload for
35  * the RTP stream changes, the #GstRtpPtDemux::payload-type-change signal will be
36  * emitted.
37  * 
38  * The element will try to set complete and unique application/x-rtp caps on the
39  * outgoing buffers and pads based on the result of the
40  * #GstRtpPtDemux::request-pt-map signal.
41  * 
42  * <refsect2>
43  * <title>Example pipelines</title>
44  * |[
45  * gst-launch-1.0 udpsrc caps="application/x-rtp" ! gstrtpptdemux ! fakesink
46  * ]| Takes an RTP stream and send the RTP packets with the first detected
47  * payload type to fakesink, discarding the other payload types.
48  * </refsect2>
49  *
50  * Last reviewed on 2007-05-28 (0.10.5)
51  */
52
53 /*
54  * Contributors:
55  * Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>
56  */
57 /*
58  * Status:
59  *  - works with the test_rtpdemux.c tool
60  *
61  * Check:
62  *  - is emitting a signal enough, or should we
63  *    use GstEvent to notify downstream elements
64  *    of the new packet... no?
65  *
66  * Notes:
67  *  - emits event both for new PTs, and whenever
68  *    a PT is changed
69  */
70
71 #ifdef HAVE_CONFIG_H
72 #include "config.h"
73 #endif
74
75 #include <string.h>
76 #include <gst/gst.h>
77 #include <gst/rtp/gstrtpbuffer.h>
78
79 #include "gstrtpptdemux.h"
80
81 /* generic templates */
82 static GstStaticPadTemplate rtp_pt_demux_sink_template =
83 GST_STATIC_PAD_TEMPLATE ("sink",
84     GST_PAD_SINK,
85     GST_PAD_ALWAYS,
86     GST_STATIC_CAPS ("application/x-rtp")
87     );
88
89 static GstStaticPadTemplate rtp_pt_demux_src_template =
90 GST_STATIC_PAD_TEMPLATE ("src_%u",
91     GST_PAD_SRC,
92     GST_PAD_SOMETIMES,
93     GST_STATIC_CAPS ("application/x-rtp, " "payload = (int) [ 0, 255 ]")
94     );
95
96 GST_DEBUG_CATEGORY_STATIC (gst_rtp_pt_demux_debug);
97 #define GST_CAT_DEFAULT gst_rtp_pt_demux_debug
98
99 /*
100  * Item for storing GstPad<->pt pairs.
101  */
102 struct _GstRtpPtDemuxPad
103 {
104   GstPad *pad;        /**< pointer to the actual pad */
105   gint pt;             /**< RTP payload-type attached to pad */
106   gboolean newcaps;
107 };
108
109 /* signals */
110 enum
111 {
112   SIGNAL_REQUEST_PT_MAP,
113   SIGNAL_NEW_PAYLOAD_TYPE,
114   SIGNAL_PAYLOAD_TYPE_CHANGE,
115   SIGNAL_CLEAR_PT_MAP,
116   LAST_SIGNAL
117 };
118
119 #define gst_rtp_pt_demux_parent_class parent_class
120 G_DEFINE_TYPE (GstRtpPtDemux, gst_rtp_pt_demux, GST_TYPE_ELEMENT);
121
122 static void gst_rtp_pt_demux_finalize (GObject * object);
123
124 static void gst_rtp_pt_demux_release (GstRtpPtDemux * ptdemux);
125 static gboolean gst_rtp_pt_demux_setup (GstRtpPtDemux * ptdemux);
126
127 static gboolean gst_rtp_pt_demux_sink_event (GstPad * pad, GstObject * parent,
128     GstEvent * event);
129 static GstFlowReturn gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent,
130     GstBuffer * buf);
131 static GstStateChangeReturn gst_rtp_pt_demux_change_state (GstElement * element,
132     GstStateChange transition);
133 static void gst_rtp_pt_demux_clear_pt_map (GstRtpPtDemux * rtpdemux);
134
135 static GstPad *find_pad_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt);
136
137 static gboolean gst_rtp_pt_demux_src_event (GstPad * pad, GstObject * parent,
138     GstEvent * event);
139
140
141 static guint gst_rtp_pt_demux_signals[LAST_SIGNAL] = { 0 };
142
143 static void
144 gst_rtp_pt_demux_class_init (GstRtpPtDemuxClass * klass)
145 {
146   GObjectClass *gobject_klass;
147   GstElementClass *gstelement_klass;
148
149   gobject_klass = (GObjectClass *) klass;
150   gstelement_klass = (GstElementClass *) klass;
151
152   /**
153    * GstRtpPtDemux::request-pt-map:
154    * @demux: the object which received the signal
155    * @pt: the payload type
156    *
157    * Request the payload type as #GstCaps for @pt.
158    */
159   gst_rtp_pt_demux_signals[SIGNAL_REQUEST_PT_MAP] =
160       g_signal_new ("request-pt-map", G_TYPE_FROM_CLASS (klass),
161       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass, request_pt_map),
162       NULL, NULL, g_cclosure_marshal_generic, GST_TYPE_CAPS, 1, G_TYPE_UINT);
163
164   /**
165    * GstRtpPtDemux::new-payload-type:
166    * @demux: the object which received the signal
167    * @pt: the payload type
168    * @pad: the pad with the new payload
169    *
170    * Emited when a new payload type pad has been created in @demux.
171    */
172   gst_rtp_pt_demux_signals[SIGNAL_NEW_PAYLOAD_TYPE] =
173       g_signal_new ("new-payload-type", G_TYPE_FROM_CLASS (klass),
174       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass, new_payload_type),
175       NULL, NULL, g_cclosure_marshal_generic, G_TYPE_NONE, 2, G_TYPE_UINT,
176       GST_TYPE_PAD);
177
178   /**
179    * GstRtpPtDemux::payload-type-change:
180    * @demux: the object which received the signal
181    * @pt: the new payload type
182    *
183    * Emited when the payload type changed.
184    */
185   gst_rtp_pt_demux_signals[SIGNAL_PAYLOAD_TYPE_CHANGE] =
186       g_signal_new ("payload-type-change", G_TYPE_FROM_CLASS (klass),
187       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass,
188           payload_type_change), NULL, NULL, g_cclosure_marshal_VOID__UINT,
189       G_TYPE_NONE, 1, G_TYPE_UINT);
190
191   /**
192    * GstRtpPtDemux::clear-pt-map:
193    * @demux: the object which received the signal
194    *
195    * The application can call this signal to instruct the element to discard the
196    * currently cached payload type map.
197    */
198   gst_rtp_pt_demux_signals[SIGNAL_CLEAR_PT_MAP] =
199       g_signal_new ("clear-pt-map", G_TYPE_FROM_CLASS (klass),
200       G_SIGNAL_ACTION | G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRtpPtDemuxClass,
201           clear_pt_map), NULL, NULL, g_cclosure_marshal_VOID__VOID,
202       G_TYPE_NONE, 0, G_TYPE_NONE);
203
204   gobject_klass->finalize = gst_rtp_pt_demux_finalize;
205
206   gstelement_klass->change_state =
207       GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_change_state);
208
209   klass->clear_pt_map = GST_DEBUG_FUNCPTR (gst_rtp_pt_demux_clear_pt_map);
210
211   gst_element_class_add_pad_template (gstelement_klass,
212       gst_static_pad_template_get (&rtp_pt_demux_sink_template));
213   gst_element_class_add_pad_template (gstelement_klass,
214       gst_static_pad_template_get (&rtp_pt_demux_src_template));
215
216   gst_element_class_set_static_metadata (gstelement_klass, "RTP Demux",
217       "Demux/Network/RTP",
218       "Parses codec streams transmitted in the same RTP session",
219       "Kai Vehmanen <kai.vehmanen@nokia.com>");
220
221   GST_DEBUG_CATEGORY_INIT (gst_rtp_pt_demux_debug,
222       "rtpptdemux", 0, "RTP codec demuxer");
223 }
224
225 static void
226 gst_rtp_pt_demux_init (GstRtpPtDemux * ptdemux)
227 {
228   GstElementClass *klass = GST_ELEMENT_GET_CLASS (ptdemux);
229
230   ptdemux->sink =
231       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
232           "sink"), "sink");
233   g_assert (ptdemux->sink != NULL);
234
235   gst_pad_set_chain_function (ptdemux->sink, gst_rtp_pt_demux_chain);
236   gst_pad_set_event_function (ptdemux->sink, gst_rtp_pt_demux_sink_event);
237
238   gst_element_add_pad (GST_ELEMENT (ptdemux), ptdemux->sink);
239 }
240
241 static void
242 gst_rtp_pt_demux_finalize (GObject * object)
243 {
244   gst_rtp_pt_demux_release (GST_RTP_PT_DEMUX (object));
245
246   G_OBJECT_CLASS (parent_class)->finalize (object);
247 }
248
249 static GstCaps *
250 gst_rtp_pt_demux_get_caps (GstRtpPtDemux * rtpdemux, guint pt)
251 {
252   GstCaps *caps;
253   GValue ret = { 0 };
254   GValue args[2] = { {0}, {0} };
255
256   /* figure out the caps */
257   g_value_init (&args[0], GST_TYPE_ELEMENT);
258   g_value_set_object (&args[0], rtpdemux);
259   g_value_init (&args[1], G_TYPE_UINT);
260   g_value_set_uint (&args[1], pt);
261
262   g_value_init (&ret, GST_TYPE_CAPS);
263   g_value_set_boxed (&ret, NULL);
264
265   g_signal_emitv (args, gst_rtp_pt_demux_signals[SIGNAL_REQUEST_PT_MAP], 0,
266       &ret);
267
268   g_value_unset (&args[0]);
269   g_value_unset (&args[1]);
270   caps = g_value_dup_boxed (&ret);
271   g_value_unset (&ret);
272   if (caps == NULL) {
273     caps = gst_pad_get_current_caps (rtpdemux->sink);
274   }
275
276   GST_DEBUG ("pt %d, got caps %" GST_PTR_FORMAT, pt, caps);
277
278   return caps;
279 }
280
281 static void
282 gst_rtp_pt_demux_clear_pt_map (GstRtpPtDemux * rtpdemux)
283 {
284   GSList *walk;
285
286   GST_OBJECT_LOCK (rtpdemux);
287   GST_DEBUG ("clearing pt map");
288   for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) {
289     GstRtpPtDemuxPad *pad = walk->data;
290
291     pad->newcaps = TRUE;
292   }
293   GST_OBJECT_UNLOCK (rtpdemux);
294 }
295
296 static gboolean
297 need_caps_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt)
298 {
299   GSList *walk;
300   gboolean ret = FALSE;
301
302   GST_OBJECT_LOCK (rtpdemux);
303   for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) {
304     GstRtpPtDemuxPad *pad = walk->data;
305
306     if (pad->pt == pt) {
307       ret = pad->newcaps;
308     }
309   }
310   GST_OBJECT_UNLOCK (rtpdemux);
311
312   return ret;
313 }
314
315
316 static void
317 clear_newcaps_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt)
318 {
319   GSList *walk;
320
321   GST_OBJECT_LOCK (rtpdemux);
322   for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) {
323     GstRtpPtDemuxPad *pad = walk->data;
324
325     if (pad->pt == pt) {
326       pad->newcaps = FALSE;
327       break;
328     }
329   }
330   GST_OBJECT_UNLOCK (rtpdemux);
331 }
332
333 static gboolean
334 forward_sticky_events (GstPad * pad, GstEvent ** event, gpointer user_data)
335 {
336   GstPad *srcpad = GST_PAD_CAST (user_data);
337
338   /* Stream start and caps have already been pushed */
339   if (GST_EVENT_TYPE (*event) >= GST_EVENT_SEGMENT)
340     gst_pad_push_event (srcpad, gst_event_ref (*event));
341
342   return TRUE;
343 }
344
345 static GstFlowReturn
346 gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
347 {
348   GstFlowReturn ret = GST_FLOW_OK;
349   GstRtpPtDemux *rtpdemux;
350   guint8 pt;
351   GstPad *srcpad;
352   GstCaps *caps;
353   GstRTPBuffer rtp = { NULL };
354
355   rtpdemux = GST_RTP_PT_DEMUX (parent);
356
357   if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp))
358     goto invalid_buffer;
359
360   pt = gst_rtp_buffer_get_payload_type (&rtp);
361   gst_rtp_buffer_unmap (&rtp);
362
363   GST_DEBUG_OBJECT (rtpdemux, "received buffer for pt %d", pt);
364
365   srcpad = find_pad_for_pt (rtpdemux, pt);
366   if (srcpad == NULL) {
367     /* new PT, create a src pad */
368     GstRtpPtDemuxPad *rtpdemuxpad;
369     GstElementClass *klass;
370     GstPadTemplate *templ;
371     gchar *padname;
372
373     caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt);
374     if (!caps)
375       goto no_caps;
376
377     klass = GST_ELEMENT_GET_CLASS (rtpdemux);
378     templ = gst_element_class_get_pad_template (klass, "src_%u");
379     padname = g_strdup_printf ("src_%u", pt);
380     srcpad = gst_pad_new_from_template (templ, padname);
381     gst_pad_use_fixed_caps (srcpad);
382     g_free (padname);
383     gst_pad_set_event_function (srcpad, gst_rtp_pt_demux_src_event);
384
385     GST_DEBUG ("Adding pt=%d to the list.", pt);
386     rtpdemuxpad = g_slice_new0 (GstRtpPtDemuxPad);
387     rtpdemuxpad->pt = pt;
388     rtpdemuxpad->newcaps = FALSE;
389     rtpdemuxpad->pad = srcpad;
390     gst_object_ref (srcpad);
391     GST_OBJECT_LOCK (rtpdemux);
392     rtpdemux->srcpads = g_slist_append (rtpdemux->srcpads, rtpdemuxpad);
393     GST_OBJECT_UNLOCK (rtpdemux);
394
395     gst_pad_set_active (srcpad, TRUE);
396
397
398     /* First push the stream-start event, it must always come first */
399     gst_pad_push_event (srcpad,
400         gst_pad_get_sticky_event (rtpdemux->sink, GST_EVENT_STREAM_START, 0));
401
402     /* Then caps event is sent */
403     caps = gst_caps_make_writable (caps);
404     gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
405     gst_pad_set_caps (srcpad, caps);
406     gst_caps_unref (caps);
407
408     /* First sticky events on sink pad are forwarded to the new src pad */
409     gst_pad_sticky_events_foreach (rtpdemux->sink, forward_sticky_events,
410         srcpad);
411
412     gst_element_add_pad (GST_ELEMENT_CAST (rtpdemux), srcpad);
413
414     GST_DEBUG ("emitting new-payload-type for pt %d", pt);
415     g_signal_emit (G_OBJECT (rtpdemux),
416         gst_rtp_pt_demux_signals[SIGNAL_NEW_PAYLOAD_TYPE], 0, pt, srcpad);
417   }
418
419   if (pt != rtpdemux->last_pt) {
420     gint emit_pt = pt;
421
422     /* our own signal with an extra flag that this is the only pad */
423     rtpdemux->last_pt = pt;
424     GST_DEBUG ("emitting payload-type-changed for pt %d", emit_pt);
425     g_signal_emit (G_OBJECT (rtpdemux),
426         gst_rtp_pt_demux_signals[SIGNAL_PAYLOAD_TYPE_CHANGE], 0, emit_pt);
427   }
428
429   while (need_caps_for_pt (rtpdemux, pt)) {
430     GST_DEBUG ("need new caps for %d", pt);
431     caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt);
432     if (!caps)
433       goto no_caps;
434
435     clear_newcaps_for_pt (rtpdemux, pt);
436
437     caps = gst_caps_make_writable (caps);
438     gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
439     gst_pad_set_caps (srcpad, caps);
440     gst_caps_unref (caps);
441   }
442
443   /* push to srcpad */
444   ret = gst_pad_push (srcpad, buf);
445
446   gst_object_unref (srcpad);
447
448   return ret;
449
450   /* ERRORS */
451 invalid_buffer:
452   {
453     /* this is fatal and should be filtered earlier */
454     GST_ELEMENT_ERROR (rtpdemux, STREAM, DECODE, (NULL),
455         ("Dropping invalid RTP payload"));
456     gst_buffer_unref (buf);
457     return GST_FLOW_ERROR;
458   }
459 no_caps:
460   {
461     GST_ELEMENT_ERROR (rtpdemux, STREAM, DECODE, (NULL),
462         ("Could not get caps for payload"));
463     gst_buffer_unref (buf);
464     if (srcpad)
465       gst_object_unref (srcpad);
466     return GST_FLOW_ERROR;
467   }
468 }
469
470 static GstPad *
471 find_pad_for_pt (GstRtpPtDemux * rtpdemux, guint8 pt)
472 {
473   GstPad *respad = NULL;
474   GSList *walk;
475
476   GST_OBJECT_LOCK (rtpdemux);
477   for (walk = rtpdemux->srcpads; walk; walk = g_slist_next (walk)) {
478     GstRtpPtDemuxPad *pad = walk->data;
479
480     if (pad->pt == pt) {
481       respad = gst_object_ref (pad->pad);
482       break;
483     }
484   }
485   GST_OBJECT_UNLOCK (rtpdemux);
486
487   return respad;
488 }
489
490 static gboolean
491 gst_rtp_pt_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
492 {
493   GstRtpPtDemux *rtpdemux;
494   gboolean res = FALSE;
495
496   rtpdemux = GST_RTP_PT_DEMUX (parent);
497
498   switch (GST_EVENT_TYPE (event)) {
499     case GST_EVENT_CAPS:
500     {
501       gst_rtp_pt_demux_clear_pt_map (rtpdemux);
502       /* don't forward the event, we cleared the ptmap and on the next buffer we
503        * will add the pt to the caps and push a new caps event */
504       gst_event_unref (event);
505       res = TRUE;
506       break;
507     }
508     case GST_EVENT_CUSTOM_DOWNSTREAM:
509     {
510       const GstStructure *s;
511
512       s = gst_event_get_structure (event);
513
514       if (gst_structure_has_name (s, "GstRTPPacketLost")) {
515         GstPad *srcpad = find_pad_for_pt (rtpdemux, rtpdemux->last_pt);
516
517         if (srcpad) {
518           res = gst_pad_push_event (srcpad, event);
519           gst_object_unref (srcpad);
520         } else {
521           gst_event_unref (event);
522         }
523
524       } else {
525         res = gst_pad_event_default (pad, parent, event);
526       }
527       break;
528     }
529     default:
530       res = gst_pad_event_default (pad, parent, event);
531       break;
532   }
533
534   return res;
535 }
536
537
538 static gboolean
539 gst_rtp_pt_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
540 {
541   GstRtpPtDemux *demux;
542   const GstStructure *s;
543
544   demux = GST_RTP_PT_DEMUX (parent);
545
546   switch (GST_EVENT_TYPE (event)) {
547     case GST_EVENT_CUSTOM_UPSTREAM:
548     case GST_EVENT_CUSTOM_BOTH:
549     case GST_EVENT_CUSTOM_BOTH_OOB:
550       s = gst_event_get_structure (event);
551       if (s && !gst_structure_has_field (s, "payload")) {
552         GSList *walk;
553
554         GST_OBJECT_LOCK (demux);
555         for (walk = demux->srcpads; walk; walk = g_slist_next (walk)) {
556           GstRtpPtDemuxPad *dpad = (GstRtpPtDemuxPad *) walk->data;
557
558           if (dpad->pad == pad) {
559             GstStructure *ws;
560
561             event =
562                 GST_EVENT_CAST (gst_mini_object_make_writable
563                 (GST_MINI_OBJECT_CAST (event)));
564             ws = gst_event_writable_structure (event);
565             gst_structure_set (ws, "payload", G_TYPE_UINT, dpad->pt, NULL);
566             break;
567           }
568         }
569         GST_OBJECT_UNLOCK (demux);
570       }
571       break;
572     default:
573       break;
574   }
575
576   return gst_pad_event_default (pad, parent, event);
577 }
578
579 /*
580  * Reserves resources for the object.
581  */
582 static gboolean
583 gst_rtp_pt_demux_setup (GstRtpPtDemux * ptdemux)
584 {
585   ptdemux->srcpads = NULL;
586   ptdemux->last_pt = 0xFFFF;
587
588   return TRUE;
589 }
590
591 /*
592  * Free resources for the object.
593  */
594 static void
595 gst_rtp_pt_demux_release (GstRtpPtDemux * ptdemux)
596 {
597   GSList *tmppads;
598   GSList *walk;
599
600   GST_OBJECT_LOCK (ptdemux);
601   tmppads = ptdemux->srcpads;
602   ptdemux->srcpads = NULL;
603   GST_OBJECT_UNLOCK (ptdemux);
604
605   for (walk = tmppads; walk; walk = g_slist_next (walk)) {
606     GstRtpPtDemuxPad *pad = walk->data;
607
608     gst_pad_set_active (pad->pad, FALSE);
609     gst_element_remove_pad (GST_ELEMENT_CAST (ptdemux), pad->pad);
610     g_slice_free (GstRtpPtDemuxPad, pad);
611   }
612   g_slist_free (tmppads);
613 }
614
615 static GstStateChangeReturn
616 gst_rtp_pt_demux_change_state (GstElement * element, GstStateChange transition)
617 {
618   GstStateChangeReturn ret;
619   GstRtpPtDemux *ptdemux;
620
621   ptdemux = GST_RTP_PT_DEMUX (element);
622
623   switch (transition) {
624     case GST_STATE_CHANGE_NULL_TO_READY:
625       if (gst_rtp_pt_demux_setup (ptdemux) != TRUE)
626         ret = GST_STATE_CHANGE_FAILURE;
627       break;
628     case GST_STATE_CHANGE_READY_TO_PAUSED:
629     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
630     default:
631       break;
632   }
633
634   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
635
636   switch (transition) {
637     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
638     case GST_STATE_CHANGE_PAUSED_TO_READY:
639       break;
640     case GST_STATE_CHANGE_READY_TO_NULL:
641       gst_rtp_pt_demux_release (ptdemux);
642       break;
643     default:
644       break;
645   }
646
647   return ret;
648 }