fourcc: remove fourcc from caps
[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, "colorspace", G_TYPE_STRING, "sYUV", NULL);
201   res = gst_pad_set_caps (depayload->srcpad, outcaps);
202   gst_caps_unref (outcaps);
203
204   return res;
205 }
206
207 static void
208 gst_rtp_j2k_depay_clear_pu (GstRtpJ2KDepay * rtpj2kdepay)
209 {
210   gst_adapter_clear (rtpj2kdepay->pu_adapter);
211   rtpj2kdepay->have_sync = FALSE;
212 }
213
214 static GstFlowReturn
215 gst_rtp_j2k_depay_flush_pu (GstBaseRTPDepayload * depayload)
216 {
217   GstRtpJ2KDepay *rtpj2kdepay;
218   GstBuffer *mheader;
219   guint avail, MHF, mh_id;
220
221   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
222
223   /* take all available buffers */
224   avail = gst_adapter_available (rtpj2kdepay->pu_adapter);
225   if (avail == 0)
226     goto done;
227
228   MHF = rtpj2kdepay->pu_MHF;
229   mh_id = rtpj2kdepay->last_mh_id;
230
231   GST_DEBUG_OBJECT (rtpj2kdepay, "flushing PU of size %u", avail);
232
233   if (MHF == 0) {
234     GList *packets, *walk;
235
236     packets = gst_adapter_take_list (rtpj2kdepay->pu_adapter, avail);
237     /* append packets */
238     for (walk = packets; walk; walk = g_list_next (walk)) {
239       GstBuffer *buf = GST_BUFFER_CAST (walk->data);
240       GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u",
241           gst_buffer_get_size (buf));
242       gst_adapter_push (rtpj2kdepay->t_adapter, buf);
243     }
244     g_list_free (packets);
245   } else {
246     /* we have a header */
247     GST_DEBUG_OBJECT (rtpj2kdepay, "keeping header %u", mh_id);
248     /* we managed to see the start and end of the header, take all from
249      * adapter and keep in header  */
250     mheader = gst_adapter_take_buffer (rtpj2kdepay->pu_adapter, avail);
251
252     store_mheader (rtpj2kdepay, mh_id, mheader);
253   }
254
255 done:
256   rtpj2kdepay->have_sync = FALSE;
257
258   return GST_FLOW_OK;
259 }
260
261 static GstFlowReturn
262 gst_rtp_j2k_depay_flush_tile (GstBaseRTPDepayload * depayload)
263 {
264   GstRtpJ2KDepay *rtpj2kdepay;
265   guint avail, mh_id;
266   GList *packets, *walk;
267   guint8 end[2];
268   GstFlowReturn ret = GST_FLOW_OK;
269   guint8 *data;
270   gsize size;
271   GstBuffer *buf;
272
273   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
274
275   /* flush pending PU */
276   gst_rtp_j2k_depay_flush_pu (depayload);
277
278   /* take all available buffers */
279   avail = gst_adapter_available (rtpj2kdepay->t_adapter);
280   if (avail == 0)
281     goto done;
282
283   mh_id = rtpj2kdepay->last_mh_id;
284
285   GST_DEBUG_OBJECT (rtpj2kdepay, "flushing tile of size %u", avail);
286
287   if (gst_adapter_available (rtpj2kdepay->f_adapter) == 0) {
288     GstBuffer *mheader;
289
290     /* we need a header now */
291     if ((mheader = rtpj2kdepay->MH[mh_id]) == NULL)
292       goto waiting_header;
293
294     /* push header in the adapter */
295     GST_DEBUG_OBJECT (rtpj2kdepay, "pushing header %u", mh_id);
296     gst_adapter_push (rtpj2kdepay->f_adapter, gst_buffer_ref (mheader));
297   }
298
299   /* check for last bytes */
300   gst_adapter_copy (rtpj2kdepay->t_adapter, end, avail - 2, 2);
301
302   /* now append the tile packets to the frame */
303   packets = gst_adapter_take_list (rtpj2kdepay->t_adapter, avail);
304   for (walk = packets; walk; walk = g_list_next (walk)) {
305     buf = GST_BUFFER_CAST (walk->data);
306
307     if (walk == packets) {
308       /* first buffer should contain the SOT */
309       data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
310
311       if (size < 12)
312         goto invalid_tile;
313
314       if (data[0] == 0xff && data[1] == J2K_MARKER_SOT) {
315         guint Psot, nPsot;
316
317         if (end[0] == 0xff && end[1] == J2K_MARKER_EOC)
318           nPsot = avail - 2;
319         else
320           nPsot = avail;
321
322         Psot = GST_READ_UINT32_BE (&data[6]);
323         if (Psot != nPsot && Psot != 0) {
324           /* Psot must match the size of the tile */
325           GST_DEBUG_OBJECT (rtpj2kdepay, "set Psot from %u to %u", Psot, nPsot);
326           gst_buffer_unmap (buf, data, size);
327
328           buf = gst_buffer_make_writable (buf);
329
330           data = gst_buffer_map (buf, &size, NULL, GST_MAP_WRITE);
331           GST_WRITE_UINT32_BE (&data[6], nPsot);
332         }
333       }
334       gst_buffer_unmap (buf, data, size);
335     }
336
337     GST_DEBUG_OBJECT (rtpj2kdepay, "append pu packet of size %u",
338         gst_buffer_get_size (buf));
339     gst_adapter_push (rtpj2kdepay->f_adapter, buf);
340   }
341   g_list_free (packets);
342
343 done:
344   rtpj2kdepay->last_tile = -1;
345
346   return ret;
347
348   /* errors */
349 waiting_header:
350   {
351     GST_DEBUG_OBJECT (rtpj2kdepay, "waiting for header %u", mh_id);
352     gst_adapter_clear (rtpj2kdepay->t_adapter);
353     rtpj2kdepay->last_tile = -1;
354     return ret;
355   }
356 invalid_tile:
357   {
358     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE, ("Invalid tile"), (NULL));
359     gst_buffer_unmap (buf, data, size);
360     gst_adapter_clear (rtpj2kdepay->t_adapter);
361     rtpj2kdepay->last_tile = -1;
362     return ret;
363   }
364 }
365
366 static GstFlowReturn
367 gst_rtp_j2k_depay_flush_frame (GstBaseRTPDepayload * depayload)
368 {
369   GstRtpJ2KDepay *rtpj2kdepay;
370   guint8 end[2];
371   guint avail;
372
373   GstFlowReturn ret = GST_FLOW_OK;
374
375   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
376
377   /* flush pending tile */
378   gst_rtp_j2k_depay_flush_tile (depayload);
379
380   /* last buffer take all data out of the adapter */
381   avail = gst_adapter_available (rtpj2kdepay->f_adapter);
382   if (avail == 0)
383     goto done;
384
385   if (avail > 2) {
386     GstBuffer *outbuf;
387
388     /* take the last bytes of the JPEG 2000 data to see if there is an EOC
389      * marker */
390     gst_adapter_copy (rtpj2kdepay->f_adapter, end, avail - 2, 2);
391
392     if (end[0] != 0xff && end[1] != 0xd9) {
393       end[0] = 0xff;
394       end[1] = 0xd9;
395
396       GST_DEBUG_OBJECT (rtpj2kdepay, "no EOC marker, adding one");
397
398       /* no EOI marker, add one */
399       outbuf = gst_buffer_new_and_alloc (2);
400       gst_buffer_fill (outbuf, 0, end, 2);
401
402       gst_adapter_push (rtpj2kdepay->f_adapter, outbuf);
403       avail += 2;
404     }
405 #if 0
406     if (rtpj2kdepay->buffer_list) {
407       GList *list;
408       GstBufferList *buflist;
409       GstBufferListIterator *it;
410
411       GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer list of %u bytes", avail);
412       list = gst_adapter_take_list (rtpj2kdepay->f_adapter, avail);
413
414       buflist = gst_buffer_list_new ();
415       it = gst_buffer_list_iterate (buflist);
416       gst_buffer_list_iterator_add_group (it);
417       gst_buffer_list_iterator_add_list (it, list);
418       gst_buffer_list_iterator_free (it);
419
420       ret = gst_base_rtp_depayload_push_list (depayload, buflist);
421     } else
422 #endif
423     {
424       GST_DEBUG_OBJECT (rtpj2kdepay, "pushing buffer of %u bytes", avail);
425       outbuf = gst_adapter_take_buffer (rtpj2kdepay->f_adapter, avail);
426       ret = gst_base_rtp_depayload_push (depayload, outbuf);
427     }
428   } else {
429     GST_WARNING_OBJECT (rtpj2kdepay, "empty packet");
430     gst_adapter_clear (rtpj2kdepay->f_adapter);
431   }
432
433   /* we accept any mh_id now */
434   rtpj2kdepay->last_mh_id = -1;
435
436   /* reset state */
437   rtpj2kdepay->next_frag = 0;
438   rtpj2kdepay->have_sync = FALSE;
439
440 done:
441   /* we can't keep headers with mh_id of 0 */
442   store_mheader (rtpj2kdepay, 0, NULL);
443
444   return ret;
445 }
446
447 static GstBuffer *
448 gst_rtp_j2k_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
449 {
450   GstRtpJ2KDepay *rtpj2kdepay;
451   guint8 *payload;
452   guint MHF, mh_id, frag_offset, tile, payload_len, j2klen;
453   gint gap;
454   guint32 rtptime;
455   GstRTPBuffer rtp = { NULL };
456
457   rtpj2kdepay = GST_RTP_J2K_DEPAY (depayload);
458
459   gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp);
460
461   payload = gst_rtp_buffer_get_payload (&rtp);
462   payload_len = gst_rtp_buffer_get_payload_len (&rtp);
463
464   /* we need at least a header */
465   if (payload_len < 8)
466     goto empty_packet;
467
468   rtptime = gst_rtp_buffer_get_timestamp (&rtp);
469
470   /* new timestamp marks new frame */
471   if (rtpj2kdepay->last_rtptime != rtptime) {
472     rtpj2kdepay->last_rtptime = rtptime;
473     /* flush pending frame */
474     gst_rtp_j2k_depay_flush_frame (depayload);
475   }
476
477   /*
478    *  0                   1                   2                   3
479    *  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
480    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
481    * |tp |MHF|mh_id|T|     priority  |           tile number         |
482    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
483    * |reserved       |             fragment offset                   |
484    * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
485    */
486   MHF = (payload[0] & 0x30) >> 4;
487   mh_id = (payload[0] & 0xe) >> 1;
488
489   if (rtpj2kdepay->last_mh_id == -1)
490     rtpj2kdepay->last_mh_id = mh_id;
491   else if (rtpj2kdepay->last_mh_id != mh_id)
492     goto wrong_mh_id;
493
494   tile = (payload[2] << 8) | payload[3];
495   frag_offset = (payload[5] << 16) | (payload[6] << 8) | payload[7];
496   j2klen = payload_len - 8;
497
498   GST_DEBUG_OBJECT (rtpj2kdepay, "MHF %u, tile %u, frag %u, expected %u", MHF,
499       tile, frag_offset, rtpj2kdepay->next_frag);
500
501   /* calculate the gap between expected frag */
502   gap = frag_offset - rtpj2kdepay->next_frag;
503   /* calculate next frag */
504   rtpj2kdepay->next_frag = frag_offset + j2klen;
505
506   if (gap != 0) {
507     GST_DEBUG_OBJECT (rtpj2kdepay, "discont of %d, clear PU", gap);
508     /* discont, clear pu adapter and resync */
509     gst_rtp_j2k_depay_clear_pu (rtpj2kdepay);
510   }
511
512   /* check for sync code */
513   if (j2klen > 2 && payload[8] == 0xff) {
514     guint marker = payload[9];
515
516     /* packets must start with SOC, SOT or SOP */
517     switch (marker) {
518       case J2K_MARKER_SOC:
519         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOC packet");
520         /* flush the previous frame, should have happened when the timestamp
521          * changed above. */
522         gst_rtp_j2k_depay_flush_frame (depayload);
523         rtpj2kdepay->have_sync = TRUE;
524         break;
525       case J2K_MARKER_SOT:
526         /* flush the previous tile */
527         gst_rtp_j2k_depay_flush_tile (depayload);
528         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOT packet");
529         rtpj2kdepay->have_sync = TRUE;
530         /* we sync on the tile now */
531         rtpj2kdepay->last_tile = tile;
532         break;
533       case J2K_MARKER_SOP:
534         GST_DEBUG_OBJECT (rtpj2kdepay, "found SOP packet");
535         /* flush the previous PU */
536         gst_rtp_j2k_depay_flush_pu (depayload);
537         if (rtpj2kdepay->last_tile != tile) {
538           /* wrong tile, we lose sync and we need a new SOT or SOC to regain
539            * sync. First flush out the previous tile if we have one. */
540           if (rtpj2kdepay->last_tile != -1)
541             gst_rtp_j2k_depay_flush_tile (depayload);
542           /* now we have no more valid tile and no sync */
543           rtpj2kdepay->last_tile = -1;
544           rtpj2kdepay->have_sync = FALSE;
545         } else {
546           rtpj2kdepay->have_sync = TRUE;
547         }
548         break;
549       default:
550         GST_DEBUG_OBJECT (rtpj2kdepay, "no sync packet 0x%02d", marker);
551         break;
552     }
553   }
554
555   if (rtpj2kdepay->have_sync) {
556     GstBuffer *pu_frag;
557
558     if (gst_adapter_available (rtpj2kdepay->pu_adapter) == 0) {
559       /* first part of pu, record state */
560       GST_DEBUG_OBJECT (rtpj2kdepay, "first PU");
561       rtpj2kdepay->pu_MHF = MHF;
562     }
563     /* and push in pu adapter */
564     GST_DEBUG_OBJECT (rtpj2kdepay, "push pu of size %u in adapter", j2klen);
565     pu_frag = gst_rtp_buffer_get_payload_subbuffer (&rtp, 8, -1);
566     gst_adapter_push (rtpj2kdepay->pu_adapter, pu_frag);
567
568     if (MHF & 2) {
569       /* last part of main header received, we can flush it */
570       GST_DEBUG_OBJECT (rtpj2kdepay, "header end, flush pu");
571       gst_rtp_j2k_depay_flush_pu (depayload);
572     }
573   } else {
574     GST_DEBUG_OBJECT (rtpj2kdepay, "discard packet, no sync");
575   }
576
577   /* marker bit finishes the frame */
578   if (gst_rtp_buffer_get_marker (&rtp)) {
579     GST_DEBUG_OBJECT (rtpj2kdepay, "marker set, last buffer");
580     /* then flush frame */
581     gst_rtp_j2k_depay_flush_frame (depayload);
582   }
583   gst_rtp_buffer_unmap (&rtp);
584
585   return NULL;
586
587   /* ERRORS */
588 empty_packet:
589   {
590     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE,
591         ("Empty Payload."), (NULL));
592     gst_rtp_buffer_unmap (&rtp);
593     return NULL;
594   }
595 wrong_mh_id:
596   {
597     GST_ELEMENT_WARNING (rtpj2kdepay, STREAM, DECODE,
598         ("Invalid mh_id %u, expected %u", mh_id, rtpj2kdepay->last_mh_id),
599         (NULL));
600     gst_rtp_j2k_depay_clear_pu (rtpj2kdepay);
601     gst_rtp_buffer_unmap (&rtp);
602     return NULL;
603   }
604 }
605
606 static void
607 gst_rtp_j2k_depay_set_property (GObject * object, guint prop_id,
608     const GValue * value, GParamSpec * pspec)
609 {
610   GstRtpJ2KDepay *rtpj2kdepay;
611
612   rtpj2kdepay = GST_RTP_J2K_DEPAY (object);
613
614   switch (prop_id) {
615     case PROP_BUFFER_LIST:
616       rtpj2kdepay->buffer_list = g_value_get_boolean (value);
617       break;
618     default:
619       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
620       break;
621   }
622 }
623
624 static void
625 gst_rtp_j2k_depay_get_property (GObject * object, guint prop_id,
626     GValue * value, GParamSpec * pspec)
627 {
628   GstRtpJ2KDepay *rtpj2kdepay;
629
630   rtpj2kdepay = GST_RTP_J2K_DEPAY (object);
631
632   switch (prop_id) {
633     case PROP_BUFFER_LIST:
634       g_value_set_boolean (value, rtpj2kdepay->buffer_list);
635       break;
636     default:
637       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
638       break;
639   }
640 }
641
642 static GstStateChangeReturn
643 gst_rtp_j2k_depay_change_state (GstElement * element, GstStateChange transition)
644 {
645   GstRtpJ2KDepay *rtpj2kdepay;
646   GstStateChangeReturn ret;
647
648   rtpj2kdepay = GST_RTP_J2K_DEPAY (element);
649
650   switch (transition) {
651     case GST_STATE_CHANGE_NULL_TO_READY:
652       break;
653     case GST_STATE_CHANGE_READY_TO_PAUSED:
654       gst_rtp_j2k_depay_reset (rtpj2kdepay);
655       break;
656     default:
657       break;
658   }
659
660   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
661
662   switch (transition) {
663     case GST_STATE_CHANGE_PAUSED_TO_READY:
664       gst_rtp_j2k_depay_reset (rtpj2kdepay);
665       break;
666     case GST_STATE_CHANGE_READY_TO_NULL:
667       break;
668     default:
669       break;
670   }
671   return ret;
672 }
673
674 gboolean
675 gst_rtp_j2k_depay_plugin_init (GstPlugin * plugin)
676 {
677   return gst_element_register (plugin, "rtpj2kdepay",
678       GST_RANK_SECONDARY, GST_TYPE_RTP_J2K_DEPAY);
679 }