f63e0c1eb95215dcc01902645a015535bb63ddb9
[platform/upstream/gst-plugins-good.git] / gst / rtp / gstrtpj2kdepay.c
1 /* GStreamer
2  * Copyright (C) <2009> Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <gst/rtp/gstrtpbuffer.h>
25
26 #include <string.h>
27 #include "gstrtpj2kdepay.h"
28
29 GST_DEBUG_CATEGORY_STATIC (rtpj2kdepay_debug);
30 #define GST_CAT_DEFAULT (rtpj2kdepay_debug)
31
32 static GstStaticPadTemplate gst_rtp_j2k_depay_src_template =
33 GST_STATIC_PAD_TEMPLATE ("src",
34     GST_PAD_SRC,
35     GST_PAD_ALWAYS,
36     GST_STATIC_CAPS ("image/x-jpc")
37     );
38
39 static GstStaticPadTemplate gst_rtp_j2k_depay_sink_template =
40 GST_STATIC_PAD_TEMPLATE ("sink",
41     GST_PAD_SINK,
42     GST_PAD_ALWAYS,
43     GST_STATIC_CAPS ("application/x-rtp, "
44         "media = (string) \"video\", "
45         "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
46         "clock-rate = (int) 90000, " "encoding-name = (string) \"JPEG2000\"")
47     );
48
49 typedef enum
50 {
51   J2K_MARKER = 0xFF,
52   J2K_MARKER_SOC = 0x4F,
53   J2K_MARKER_SOT = 0x90,
54   J2K_MARKER_SOP = 0x91,
55   J2K_MARKER_SOD = 0x93,
56   J2K_MARKER_EOC = 0xD9
57 } RtpJ2KMarker;
58
59 #define DEFAULT_BUFFER_LIST             TRUE
60
61 enum
62 {
63   PROP_0,
64   PROP_BUFFER_LIST,
65   PROP_LAST
66 };
67
68 #define gst_rtp_j2k_depay_parent_class parent_class
69 G_DEFINE_TYPE (GstRtpJ2KDepay, gst_rtp_j2k_depay, GST_TYPE_BASE_RTP_DEPAYLOAD);
70
71 static void gst_rtp_j2k_depay_finalize (GObject * object);
72
73 static void gst_rtp_j2k_depay_set_property (GObject * object, guint prop_id,
74     const GValue * value, GParamSpec * pspec);
75 static void gst_rtp_j2k_depay_get_property (GObject * object, guint prop_id,
76     GValue * value, GParamSpec * pspec);
77
78 static GstStateChangeReturn
79 gst_rtp_j2k_depay_change_state (GstElement * element,
80     GstStateChange transition);
81
82 static gboolean gst_rtp_j2k_depay_setcaps (GstBaseRTPDepayload * depayload,
83     GstCaps * caps);
84 static GstBuffer *gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload,
85     GstBuffer * buf);
86
87 static void
88 gst_rtp_j2k_depay_class_init (GstRtpJ2KDepayClass * klass)
89 {
90   GObjectClass *gobject_class;
91   GstElementClass *gstelement_class;
92   GstBaseRTPDepayloadClass *gstbasertpdepayload_class;
93
94   gobject_class = (GObjectClass *) klass;
95   gstelement_class = (GstElementClass *) klass;
96   gstbasertpdepayload_class = (GstBaseRTPDepayloadClass *) klass;
97
98   gobject_class->finalize = gst_rtp_j2k_depay_finalize;
99
100   gobject_class->set_property = gst_rtp_j2k_depay_set_property;
101   gobject_class->get_property = gst_rtp_j2k_depay_get_property;
102
103   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_LIST,
104       g_param_spec_boolean ("buffer-list", "Buffer List",
105           "Use Buffer Lists",
106           DEFAULT_BUFFER_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
107
108   gst_element_class_add_pad_template (gstelement_class,
109       gst_static_pad_template_get (&gst_rtp_j2k_depay_src_template));
110   gst_element_class_add_pad_template (gstelement_class,
111       gst_static_pad_template_get (&gst_rtp_j2k_depay_sink_template));
112
113   gst_element_class_set_details_simple (gstelement_class,
114       "RTP JPEG 2000 depayloader", "Codec/Depayloader/Network/RTP",
115       "Extracts JPEG 2000 video from RTP packets (RFC 5371)",
116       "Wim Taymans <wim.taymans@gmail.com>");
117
118   gstelement_class->change_state = gst_rtp_j2k_depay_change_state;
119
120   gstbasertpdepayload_class->set_caps = gst_rtp_j2k_depay_setcaps;
121   gstbasertpdepayload_class->process = gst_rtp_j2k_depay_process;
122
123   GST_DEBUG_CATEGORY_INIT (rtpj2kdepay_debug, "rtpj2kdepay", 0,
124       "J2K Video RTP Depayloader");
125 }
126
127 static void
128 gst_rtp_j2k_depay_init (GstRtpJ2KDepay * rtpj2kdepay)
129 {
130   rtpj2kdepay->buffer_list = DEFAULT_BUFFER_LIST;
131
132   rtpj2kdepay->pu_adapter = gst_adapter_new ();
133   rtpj2kdepay->t_adapter = gst_adapter_new ();
134   rtpj2kdepay->f_adapter = gst_adapter_new ();
135 }
136
137 static void
138 store_mheader (GstRtpJ2KDepay * rtpj2kdepay, guint idx, GstBuffer * buf)
139 {
140   GstBuffer *old;
141
142   GST_DEBUG_OBJECT (rtpj2kdepay, "storing main header %p at index %u", buf,
143       idx);
144   if ((old = rtpj2kdepay->MH[idx]))
145     gst_buffer_unref (old);
146   rtpj2kdepay->MH[idx] = buf;
147 }
148
149 static void
150 clear_mheaders (GstRtpJ2KDepay * rtpj2kdepay)
151 {
152   guint i;
153
154   for (i = 0; i < 8; i++)
155     store_mheader (rtpj2kdepay, i, NULL);
156 }
157
158 static void
159 gst_rtp_j2k_depay_reset (GstRtpJ2KDepay * rtpj2kdepay)
160 {
161   clear_mheaders (rtpj2kdepay);
162   gst_adapter_clear (rtpj2kdepay->pu_adapter);
163   gst_adapter_clear (rtpj2kdepay->t_adapter);
164   gst_adapter_clear (rtpj2kdepay->f_adapter);
165   rtpj2kdepay->next_frag = 0;
166 }
167
168 static void
169 gst_rtp_j2k_depay_finalize (GObject * object)
170 {
171   GstRtpJ2KDepay *rtpj2kdepay;
172
173   rtpj2kdepay = GST_RTP_J2K_DEPAY (object);
174
175   clear_mheaders (rtpj2kdepay);
176
177   g_object_unref (rtpj2kdepay->pu_adapter);
178   g_object_unref (rtpj2kdepay->t_adapter);
179   g_object_unref (rtpj2kdepay->f_adapter);
180
181   G_OBJECT_CLASS (parent_class)->finalize (object);
182 }
183
184 static gboolean
185 gst_rtp_j2k_depay_setcaps (GstBaseRTPDepayload * depayload, GstCaps * caps)
186 {
187   GstStructure *structure;
188   gint clock_rate;
189   GstCaps *outcaps;
190   gboolean res;
191
192   structure = gst_caps_get_structure (caps, 0);
193
194   if (!gst_structure_get_int (structure, "clock-rate", &clock_rate))
195     clock_rate = 90000;
196   depayload->clock_rate = clock_rate;
197
198   outcaps =
199       gst_caps_new_simple ("image/x-jpc", "framerate", GST_TYPE_FRACTION, 0, 1,
200       "fields", G_TYPE_INT, 1, "fourcc", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('s',
201           'Y', 'U', 'V'), NULL);
202   res = gst_pad_set_caps (depayload->srcpad, outcaps);
203   gst_caps_unref (outcaps);
204
205   return res;
206 }
207
208 static void
209 gst_rtp_j2k_depay_clear_pu (GstRtpJ2KDepay * rtpj2kdepay)
210 {
211   gst_adapter_clear (rtpj2kdepay->pu_adapter);
212   rtpj2kdepay->have_sync = FALSE;
213 }
214
215 static GstFlowReturn
216 gst_rtp_j2k_depay_flush_pu (GstBaseRTPDepayload * depayload)
217 {
218   GstRtpJ2KDepay *rtpj2kdepay;
219   GstBuffer *mheader;
220   guint avail, MHF, mh_id;
221
222   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
223
224   /* take all available buffers */
225   avail = gst_adapter_available (rtpj2kdepay->pu_adapter);
226   if (avail == 0)
227     goto done;
228
229   MHF = rtpj2kdepay->pu_MHF;
230   mh_id = rtpj2kdepay->last_mh_id;
231
232   GST_DEBUG_OBJECT (rtpj2kdepay, "flushing PU of size %u", avail);
233
234   if (MHF == 0) {
235     GList *packets, *walk;
236
237     packets = gst_adapter_take_list (rtpj2kdepay->pu_adapter, avail);
238     /* append packets */
239     for (walk = packets; walk; walk = g_list_next (walk)) {
240       GstBuffer *buf = GST_BUFFER_CAST (walk->data);
241       GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u",
242           gst_buffer_get_size (buf));
243       gst_adapter_push (rtpj2kdepay->t_adapter, buf);
244     }
245     g_list_free (packets);
246   } else {
247     /* we have a header */
248     GST_DEBUG_OBJECT (rtpj2kdepay, "keeping header %u", mh_id);
249     /* we managed to see the start and end of the header, take all from
250      * adapter and keep in header  */
251     mheader = gst_adapter_take_buffer (rtpj2kdepay->pu_adapter, avail);
252
253     store_mheader (rtpj2kdepay, mh_id, mheader);
254   }
255
256 done:
257   rtpj2kdepay->have_sync = FALSE;
258
259   return GST_FLOW_OK;
260 }
261
262 static GstFlowReturn
263 gst_rtp_j2k_depay_flush_tile (GstBaseRTPDepayload * depayload)
264 {
265   GstRtpJ2KDepay *rtpj2kdepay;
266   guint avail, mh_id;
267   GList *packets, *walk;
268   guint8 end[2];
269   GstFlowReturn ret = GST_FLOW_OK;
270   guint8 *data;
271   gsize size;
272   GstBuffer *buf;
273
274   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
275
276   /* flush pending PU */
277   gst_rtp_j2k_depay_flush_pu (depayload);
278
279   /* take all available buffers */
280   avail = gst_adapter_available (rtpj2kdepay->t_adapter);
281   if (avail == 0)
282     goto done;
283
284   mh_id = rtpj2kdepay->last_mh_id;
285
286   GST_DEBUG_OBJECT (rtpj2kdepay, "flushing tile of size %u", avail);
287
288   if (gst_adapter_available (rtpj2kdepay->f_adapter) == 0) {
289     GstBuffer *mheader;
290
291     /* we need a header now */
292     if ((mheader = rtpj2kdepay->MH[mh_id]) == NULL)
293       goto waiting_header;
294
295     /* push header in the adapter */
296     GST_DEBUG_OBJECT (rtpj2kdepay, "pushing header %u", mh_id);
297     gst_adapter_push (rtpj2kdepay->f_adapter, gst_buffer_ref (mheader));
298   }
299
300   /* check for last bytes */
301   gst_adapter_copy (rtpj2kdepay->t_adapter, end, avail - 2, 2);
302
303   /* now append the tile packets to the frame */
304   packets = gst_adapter_take_list (rtpj2kdepay->t_adapter, avail);
305   for (walk = packets; walk; walk = g_list_next (walk)) {
306     buf = GST_BUFFER_CAST (walk->data);
307
308     if (walk == packets) {
309       /* first buffer should contain the SOT */
310       data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
311
312       if (size < 12)
313         goto invalid_tile;
314
315       if (data[0] == 0xff && data[1] == J2K_MARKER_SOT) {
316         guint Psot, nPsot;
317
318         if (end[0] == 0xff && end[1] == J2K_MARKER_EOC)
319           nPsot = avail - 2;
320         else
321           nPsot = avail;
322
323         Psot = GST_READ_UINT32_BE (&data[6]);
324         if (Psot != nPsot && Psot != 0) {
325           /* Psot must match the size of the tile */
326           GST_DEBUG_OBJECT (rtpj2kdepay, "set Psot from %u to %u", Psot, nPsot);
327           gst_buffer_unmap (buf, data, size);
328
329           buf = gst_buffer_make_writable (buf);
330
331           data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
332           GST_WRITE_UINT32_BE (&data[6], nPsot);
333         }
334       }
335       gst_buffer_unmap (buf, data, size);
336     }
337
338     GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u",
339         gst_buffer_get_size (buf));
340     gst_adapter_push (rtpj2kdepay->f_adapter, buf);
341   }
342   g_list_free (packets);
343
344 done:
345   rtpj2kdepay->last_tile = -1;
346
347   return ret;
348
349   /* errors */
350 waiting_header:
351   {
352     GST_DEBUG_OBJECT (rtpj2kdepay, "waiting for header %u", mh_id);
353     gst_adapter_clear (rtpj2kdepay->t_adapter);
354     rtpj2kdepay->last_tile = -1;
355     return ret;
356   }
357 invalid_tile:
358   {
359     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Invalid tile"), (NULL));
360     gst_buffer_unmap (buf, data, size);
361     gst_adapter_clear (rtpj2kdepay->t_adapter);
362     rtpj2kdepay->last_tile = -1;
363     return ret;
364   }
365 }
366
367 static GstFlowReturn
368 gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload)
369 {
370   GstRtpJ2KDepay *rtpj2kdepay;
371   guint8 end[2];
372   guint avail;
373
374   GstFlowReturn ret = GST_FLOW_OK;
375
376   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
377
378   /* flush pending tile */
379   gst_rtp_j2k_depay_flush_tile (depayload);
380
381   /* last buffer take all data out of the adapter */
382   avail = gst_adapter_available (rtpj2kdepay->f_adapter);
383   if (avail == 0)
384     goto done;
385
386   if (avail > 2) {
387     GstBuffer *outbuf;
388
389     /* take the last bytes of the JPEG 2000 data to see if there is an EOC
390      * marker */
391     gst_adapter_copy (rtpj2kdepay->f_adapter, end, avail - 2, 2);
392
393     if (end[0] != 0xff && end[1] != 0xd9) {
394       end[0] = 0xff;
395       end[1] = 0xd9;
396
397       GST_DEBUG_OBJECT (rtpj2kdepay, "no EOC marker, adding one");
398
399       /* no EOI marker, add one */
400       outbuf = gst_buffer_new_and_alloc (2);
401       gst_buffer_fill (outbuf, 0, end, 2);
402
403       gst_adapter_push (rtpj2kdepay->f_adapter, outbuf);
404       avail += 2;
405     }
406 #if 0
407     if (rtpj2kdepay->buffer_list) {
408       GList *list;
409       GstBufferList *buflist;
410       GstBufferListIterator *it;
411
412       GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer list of %u bytes", avail);
413       list = gst_adapter_take_list (rtpj2kdepay->f_adapter, avail);
414
415       buflist = gst_buffer_list_new ();
416       it = gst_buffer_list_iterate (buflist);
417       gst_buffer_list_iterator_add_group (it);
418       gst_buffer_list_iterator_add_list (it, list);
419       gst_buffer_list_iterator_free (it);
420
421       ret = gst_base_rtp_depayload_push_list (depayload, buflist);
422     } else
423 #endif
424     {
425       GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail);
426       outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail);
427       ret = gst_base_rtp_depayload_push (depayload, outbuf);
428     }
429   } else {
430     GST_WARNING_OBJECT (rtpj2kdepay, "empty packet");
431     gst_adapter_clear (rtpj2kdepay->f_adapter);
432   }
433
434   /* we accept any mh_id now */
435   rtpj2kdepay->last_mh_id = -1;
436
437   /* reset state */
438   rtpj2kdepay->next_frag = 0;
439   rtpj2kdepay->have_sync = FALSE;
440
441 done:
442   /* we can't keep headers with mh_id of 0 */
443   store_mheader (rtpj2kdepay, 0, NULL);
444
445   return ret;
446 }
447
448 static GstBuffer *
449 gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
450 {
451   GstRtpJ2KDepay *rtpj2kdepay;
452   guint8 *payload;
453   guint MHF, mh_id, frag_offset, tile, payload_len, j2klen;
454   gint gap;
455   guint32 rtptime;
456   GstRTPBuffer rtp = { NULL };
457
458   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
459
460   gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
461
462   payload = gst_rtp_buffer_get_payload (&rtp);
463   payload_len = gst_rtp_buffer_get_payload_len (&rtp);
464
465   /* we need at least a header */
466   if (payload_len < 8)
467     goto empty_packet;
468
469   rtptime = gst_rtp_buffer_get_timestamp (&rtp);
470
471   /* new timestamp marks new frame */
472   if (rtpj2kdepay->last_rtptime != rtptime) {
473     rtpj2kdepay->last_rtptime = rtptime;
474     /* flush pending frame */
475     gst_rtp_j2k_depay_flush_frame (depayload);
476   }
477
478   /*
479    *  0                   1                   2                   3
480    *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
481    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
482    * |tp |MHF|mh_id|T|     priority  |           tile number         |
483    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
484    * |reserved       |             fragment offset                   |
485    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
486    */
487   MHF = (payload[0] & 0x30) >> 4;
488   mh_id = (payload[0] & 0xe) >> 1;
489
490   if (rtpj2kdepay->last_mh_id == -1)
491     rtpj2kdepay->last_mh_id = mh_id;
492   else if (rtpj2kdepay->last_mh_id != mh_id)
493     goto wrong_mh_id;
494
495   tile = (payload[2] << 8) | payload[3];
496   frag_offset = (payload[5] << 16) | (payload[6] << 8) | payload[7];
497   j2klen = payload_len - 8;
498
499   GST_DEBUG_OBJECT (rtpj2kdepay, "MHF %u, tile %u, frag %u, expected %u", MHF,
500       tile, frag_offset, rtpj2kdepay->next_frag);
501
502   /* calculate the gap between expected frag */
503   gap = frag_offset - rtpj2kdepay->next_frag;
504   /* calculate next frag */
505   rtpj2kdepay->next_frag = frag_offset + j2klen;
506
507   if (gap != 0) {
508     GST_DEBUG_OBJECT (rtpj2kdepay, "discont of %d, clear PU", gap);
509     /* discont, clear pu adapter and resync */
510     gst_rtp_j2k_depay_clear_pu (rtpj2kdepay);
511   }
512
513   /* check for sync code */
514   if (j2klen > 2 && payload[8] == 0xff) {
515     guint marker = payload[9];
516
517     /* packets must start with SOC, SOT or SOP */
518     switch (marker) {
519       case J2K_MARKER_SOC:
520         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOC packet");
521         /* flush the previous frame, should have happened when the timestamp
522          * changed above. */
523         gst_rtp_j2k_depay_flush_frame (depayload);
524         rtpj2kdepay->have_sync = TRUE;
525         break;
526       case J2K_MARKER_SOT:
527         /* flush the previous tile */
528         gst_rtp_j2k_depay_flush_tile (depayload);
529         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOT packet");
530         rtpj2kdepay->have_sync = TRUE;
531         /* we sync on the tile now */
532         rtpj2kdepay->last_tile = tile;
533         break;
534       case J2K_MARKER_SOP:
535         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOP packet");
536         /* flush the previous PU */
537         gst_rtp_j2k_depay_flush_pu (depayload);
538         if (rtpj2kdepay->last_tile != tile) {
539           /* wrong tile, we lose sync and we need a new SOT or SOC to regain
540            * sync. First flush out the previous tile if we have one. */
541           if (rtpj2kdepay->last_tile != -1)
542             gst_rtp_j2k_depay_flush_tile (depayload);
543           /* now we have no more valid tile and no sync */
544           rtpj2kdepay->last_tile = -1;
545           rtpj2kdepay->have_sync = FALSE;
546         } else {
547           rtpj2kdepay->have_sync = TRUE;
548         }
549         break;
550       default:
551         GST_DEBUG_OBJECT (rtpj2kdepay, "no sync packet 0x%02d", marker);
552         break;
553     }
554   }
555
556   if (rtpj2kdepay->have_sync) {
557     GstBuffer *pu_frag;
558
559     if (gst_adapter_available (rtpj2kdepay->pu_adapter) == 0) {
560       /* first part of pu, record state */
561       GST_DEBUG_OBJECT (rtpj2kdepay, "first PU");
562       rtpj2kdepay->pu_MHF = MHF;
563     }
564     /* and push in pu adapter */
565     GST_DEBUG_OBJECT (rtpj2kdepay, "push pu of size %u in adapter", j2klen);
566     pu_frag = gst_rtp_buffer_get_payload_subbuffer (&rtp, 8, -1);
567     gst_adapter_push (rtpj2kdepay->pu_adapter, pu_frag);
568
569     if (MHF & 2) {
570       /* last part of main header received, we can flush it */
571       GST_DEBUG_OBJECT (rtpj2kdepay, "header end, flush pu");
572       gst_rtp_j2k_depay_flush_pu (depayload);
573     }
574   } else {
575     GST_DEBUG_OBJECT (rtpj2kdepay, "discard packet, no sync");
576   }
577
578   /* marker bit finishes the frame */
579   if (gst_rtp_buffer_get_marker (&rtp)) {
580     GST_DEBUG_OBJECT (rtpj2kdepay, "marker set, last buffer");
581     /* then flush frame */
582     gst_rtp_j2k_depay_flush_frame (depayload);
583   }
584   gst_rtp_buffer_unmap (&rtp);
585
586   return NULL;
587
588   /* ERRORS */
589 empty_packet:
590   {
591     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE,
592         ("Empty Payload."), (NULL));
593     gst_rtp_buffer_unmap (&rtp);
594     return NULL;
595   }
596 wrong_mh_id:
597   {
598     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE,
599         ("Invalid mh_id %u, expected %u", mh_id, rtpj2kdepay->last_mh_id),
600         (NULL));
601     gst_rtp_j2k_depay_clear_pu (rtpj2kdepay);
602     gst_rtp_buffer_unmap (&rtp);
603     return NULL;
604   }
605 }
606
607 static void
608 gst_rtp_j2k_depay_set_property (GObject * object, guint prop_id,
609     const GValue * value, GParamSpec * pspec)
610 {
611   GstRtpJ2KDepay *rtpj2kdepay;
612
613   rtpj2kdepay = GST_RTP_J2K_DEPAY (object);
614
615   switch (prop_id) {
616     case PROP_BUFFER_LIST:
617       rtpj2kdepay->buffer_list = g_value_get_boolean (value);
618       break;
619     default:
620       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
621       break;
622   }
623 }
624
625 static void
626 gst_rtp_j2k_depay_get_property (GObject * object, guint prop_id,
627     GValue * value, GParamSpec * pspec)
628 {
629   GstRtpJ2KDepay *rtpj2kdepay;
630
631   rtpj2kdepay = GST_RTP_J2K_DEPAY (object);
632
633   switch (prop_id) {
634     case PROP_BUFFER_LIST:
635       g_value_set_boolean (value, rtpj2kdepay->buffer_list);
636       break;
637     default:
638       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
639       break;
640   }
641 }
642
643 static GstStateChangeReturn
644 gst_rtp_j2k_depay_change_state (GstElement * element, GstStateChange transition)
645 {
646   GstRtpJ2KDepay *rtpj2kdepay;
647   GstStateChangeReturn ret;
648
649   rtpj2kdepay = GST_RTP_J2K_DEPAY (element);
650
651   switch (transition) {
652     case GST_STATE_CHANGE_NULL_TO_READY:
653       break;
654     case GST_STATE_CHANGE_READY_TO_PAUSED:
655       gst_rtp_j2k_depay_reset (rtpj2kdepay);
656       break;
657     default:
658       break;
659   }
660
661   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
662
663   switch (transition) {
664     case GST_STATE_CHANGE_PAUSED_TO_READY:
665       gst_rtp_j2k_depay_reset (rtpj2kdepay);
666       break;
667     case GST_STATE_CHANGE_READY_TO_NULL:
668       break;
669     default:
670       break;
671   }
672   return ret;
673 }
674
675 gboolean
676 gst_rtp_j2k_depay_plugin_init (GstPlugin * plugin)
677 {
678   return gst_element_register (plugin, "rtpj2kdepay",
679       GST_RANK_SECONDARY, GST_TYPE_RTP_J2K_DEPAY);
680 }