1 /* GStreamer
2  * Copyright (C) 2010 Oblong Industries, Inc.
3  * Copyright (C) 2010 Collabora Multimedia
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "jp2kcodestream.h"
26 
27 GST_DEBUG_CATEGORY_EXTERN (gst_jp2k_decimator_debug);
28 #define GST_CAT_DEFAULT gst_jp2k_decimator_debug
29 
30 /* Delimiting markers and marker segments */
31 #define MARKER_SOC 0xFF4F
32 #define MARKER_SOT 0xFF90
33 #define MARKER_SOD 0xFF93
34 #define MARKER_EOC 0xFFD9
35 
36 /* Fixed information marker segments */
37 #define MARKER_SIZ 0xFF51
38 
39 /* Functional marker segments */
40 #define MARKER_COD 0xFF52
41 #define MARKER_COC 0xFF53
42 #define MARKER_RGN 0xFF5E
43 #define MARKER_QCD 0xFF5C
44 #define MARKER_QCC 0xFF5D
45 #define MARKER_POC 0xFF5F
46 
47 /* Pointer marker segments */
48 #define MARKER_PLM 0xFF57
49 #define MARKER_PLT 0xFF58
50 #define MARKER_PPM 0xFF60
51 #define MARKER_PPT 0xFF61
52 #define MARKER_TLM 0xFF55
53 
54 /* In-bit-stream markers and marker segments */
55 #define MARKER_SOP 0xFF91
56 #define MARKER_EPH 0xFF92
57 
58 /* Informational marker segments */
59 #define MARKER_CRG 0xFF63
60 #define MARKER_COM 0xFF64
61 
62 static void
packet_iterator_changed_resolution_or_component(PacketIterator * it)63 packet_iterator_changed_resolution_or_component (PacketIterator * it)
64 {
65   gint tx0, tx1, ty0, ty1;
66   gint tcx0, tcx1, tcy0, tcy1;
67   gint trx0, trx1, try0, try1;
68   gint tpx0, tpx1, tpy0, tpy1;
69   gint two_nl_r;
70   gint two_ppx, two_ppy;
71   gint xr, yr;
72   guint8 *PPx, *PPy;
73 
74   tx0 = it->tile->tx0;
75   tx1 = it->tile->tx1;
76   ty0 = it->tile->ty0;
77   ty1 = it->tile->ty1;
78 
79   it->two_nl_r = two_nl_r = (1 << (it->n_resolutions - it->cur_resolution - 1));
80 
81   PPx = it->tile->cod ? it->tile->cod->PPx : it->header->cod.PPx;
82   PPy = it->tile->cod ? it->tile->cod->PPy : it->header->cod.PPy;
83   it->two_ppx = two_ppx = (1 << (PPx ? PPx[it->cur_resolution] : 15));
84   it->two_ppy = two_ppy = (1 << (PPy ? PPy[it->cur_resolution] : 15));
85 
86   it->xr = xr = it->header->siz.components[it->cur_component].xr;
87   it->yr = yr = it->header->siz.components[it->cur_component].yr;
88 
89   it->tcx0 = tcx0 = (tx0 + xr - 1) / xr;
90   it->tcx1 = tcx1 = (tx1 + xr - 1) / xr;
91   it->tcy0 = tcy0 = (ty0 + yr - 1) / yr;
92   it->tcy1 = tcy1 = (ty1 + yr - 1) / yr;
93 
94   it->trx0 = trx0 = (tcx0 + two_nl_r - 1) / two_nl_r;
95   it->trx1 = trx1 = (tcx1 + two_nl_r - 1) / two_nl_r;
96   it->try0 = try0 = (tcy0 + two_nl_r - 1) / two_nl_r;
97   it->try1 = try1 = (tcy1 + two_nl_r - 1) / two_nl_r;
98 
99   it->tpx0 = tpx0 = two_ppx * (trx0 / two_ppx);
100   it->tpx1 = tpx1 = two_ppx * ((trx1 + two_ppx - 1) / two_ppx);
101   it->tpy0 = tpy0 = two_ppy * (try0 / two_ppy);
102   it->tpy1 = tpy1 = two_ppy * ((try1 + two_ppy - 1) / two_ppy);
103 
104   it->n_precincts_w = (trx0 == trx1) ? 0 : (tpx1 - tpx0) / two_ppx;
105   it->n_precincts_h = (try0 == try1) ? 0 : (tpy1 - tpy0) / two_ppy;
106   it->n_precincts = it->n_precincts_w * it->n_precincts_h;
107 }
108 
109 static gboolean
packet_iterator_next_lrcp(PacketIterator * it)110 packet_iterator_next_lrcp (PacketIterator * it)
111 {
112   g_return_val_if_fail (it->cur_layer < it->n_layers, FALSE);
113 
114   if (it->first) {
115     packet_iterator_changed_resolution_or_component (it);
116     it->first = FALSE;
117     return TRUE;
118   }
119 
120   it->cur_precinct += 1;
121   if (it->cur_precinct >= it->n_precincts) {
122     it->cur_precinct = 0;
123 
124     it->cur_component += 1;
125     if (it->cur_component >= it->n_components) {
126       it->cur_component = 0;
127 
128       it->cur_resolution += 1;
129       if (it->cur_resolution >= it->n_resolutions) {
130         it->cur_resolution = 0;
131         it->cur_layer += 1;
132         if (it->cur_layer >= it->n_layers) {
133           it->cur_packet++;
134           return FALSE;
135         }
136       }
137     }
138     packet_iterator_changed_resolution_or_component (it);
139   }
140 
141   it->cur_packet++;
142 
143   return TRUE;
144 }
145 
146 static gboolean
packet_iterator_next_rlcp(PacketIterator * it)147 packet_iterator_next_rlcp (PacketIterator * it)
148 {
149   g_return_val_if_fail (it->cur_resolution < it->n_resolutions, FALSE);
150 
151   if (it->first) {
152     packet_iterator_changed_resolution_or_component (it);
153     it->first = FALSE;
154     return TRUE;
155   }
156 
157   it->cur_precinct += 1;
158   if (it->cur_precinct >= it->n_precincts) {
159     it->cur_precinct = 0;
160 
161     it->cur_component += 1;
162     if (it->cur_component >= it->n_components) {
163       it->cur_component = 0;
164 
165       it->cur_layer += 1;
166       if (it->cur_layer >= it->n_layers) {
167         it->cur_layer = 0;
168         it->cur_resolution += 1;
169         if (it->cur_resolution >= it->n_resolutions) {
170           it->cur_packet++;
171           return FALSE;
172         }
173       }
174     }
175     packet_iterator_changed_resolution_or_component (it);
176   }
177 
178   it->cur_packet++;
179 
180   return TRUE;
181 }
182 
183 static gboolean
packet_iterator_next_rpcl(PacketIterator * it)184 packet_iterator_next_rpcl (PacketIterator * it)
185 {
186   g_return_val_if_fail (it->cur_resolution < it->n_resolutions, FALSE);
187 
188   if (it->first) {
189     packet_iterator_changed_resolution_or_component (it);
190     it->first = FALSE;
191     return TRUE;
192   }
193 
194   it->cur_layer += 1;
195   if (it->cur_layer >= it->n_layers) {
196     it->cur_layer = 0;
197 
198     /* Loop and advance the position and resolution until
199      * we find the next precinct
200      */
201     while (TRUE) {
202       it->cur_component += 1;
203       if (it->cur_component >= it->n_components) {
204         it->cur_component = 0;
205 
206         it->cur_x += it->x_step - (it->cur_x % it->x_step);
207         if (it->cur_x >= it->tx1) {
208           it->cur_x = it->tx0;
209 
210           it->cur_y += it->y_step - (it->cur_y % it->y_step);
211           if (it->cur_y >= it->ty1) {
212             it->cur_y = it->ty0;
213 
214             it->cur_resolution += 1;
215 
216             if (it->cur_resolution >= it->n_resolutions) {
217               it->cur_packet++;
218               return FALSE;
219             }
220           }
221         }
222       }
223 
224       packet_iterator_changed_resolution_or_component (it);
225 
226       if (((it->cur_y % (it->yr * it->two_ppy * it->two_nl_r) == 0)
227               || (it->cur_y == it->ty0
228                   && ((it->try0 * it->two_nl_r) %
229                       (it->two_ppy * it->two_nl_r) != 0)))
230           && ((it->cur_x % (it->xr * it->two_ppx * it->two_nl_r) == 0)
231               || (it->cur_x == it->tx0
232                   && ((it->trx0 * it->two_nl_r) %
233                       (it->two_ppx * it->two_nl_r) != 0)))) {
234         gint k;
235 
236         k = (((it->cur_x + it->xr * it->two_nl_r - 1) /
237                 (it->xr * it->two_nl_r)) / it->two_ppx) -
238             (it->trx0 / it->two_ppx) +
239             it->n_precincts_w *
240             (((it->cur_y + it->yr * it->two_nl_r - 1) /
241                 (it->yr * it->two_nl_r)) / it->two_ppy);
242 
243         g_assert (k < it->n_precincts);
244 
245         it->cur_precinct = k;
246         break;
247       }
248     }
249   }
250 
251   it->cur_packet++;
252 
253   return TRUE;
254 }
255 
256 static gboolean
packet_iterator_next_pcrl(PacketIterator * it)257 packet_iterator_next_pcrl (PacketIterator * it)
258 {
259   g_return_val_if_fail (it->cur_resolution < it->n_resolutions, FALSE);
260 
261   if (it->first) {
262     it->first = FALSE;
263     return TRUE;
264   }
265 
266   it->cur_layer += 1;
267   if (it->cur_layer >= it->n_layers) {
268     it->cur_layer = 0;
269 
270     /* Loop and advance the position and resolution until
271      * we find the next precinct
272      */
273     while (TRUE) {
274       it->cur_resolution += 1;
275       if (it->cur_resolution >= it->n_resolutions) {
276         it->cur_resolution = 0;
277 
278         it->cur_component += 1;
279         if (it->cur_component >= it->n_components) {
280 
281           it->cur_x += it->x_step - (it->cur_x % it->x_step);
282           if (it->cur_x >= it->tx1) {
283             it->cur_x = it->tx0;
284 
285             it->cur_y += it->y_step - (it->cur_y % it->y_step);
286             if (it->cur_y >= it->ty1) {
287               it->cur_packet++;
288               return FALSE;
289             }
290           }
291         }
292       }
293 
294       packet_iterator_changed_resolution_or_component (it);
295 
296       if (((it->cur_y % (it->yr * it->two_ppy * it->two_nl_r) == 0)
297               || (it->cur_y == it->ty0
298                   && ((it->try0 * it->two_nl_r) %
299                       (it->two_ppy * it->two_nl_r) != 0)))
300           && ((it->cur_x % (it->xr * it->two_ppx * it->two_nl_r) == 0)
301               || (it->cur_x == it->tx0
302                   && ((it->trx0 * it->two_nl_r) %
303                       (it->two_ppx * it->two_nl_r) != 0)))) {
304         gint k;
305 
306         k = (((it->cur_x + it->xr * it->two_nl_r - 1) /
307                 (it->xr * it->two_nl_r)) / it->two_ppx) -
308             (it->trx0 / it->two_ppx) +
309             it->n_precincts_w *
310             (((it->cur_y + it->yr * it->two_nl_r - 1) /
311                 (it->yr * it->two_nl_r)) / it->two_ppy);
312 
313         g_assert (k < it->n_precincts);
314 
315         it->cur_precinct = k;
316         break;
317       }
318     }
319   }
320 
321   it->cur_packet++;
322 
323   return TRUE;
324 }
325 
326 static gboolean
packet_iterator_next_cprl(PacketIterator * it)327 packet_iterator_next_cprl (PacketIterator * it)
328 {
329   g_return_val_if_fail (it->cur_resolution < it->n_resolutions, FALSE);
330 
331   if (it->first) {
332     packet_iterator_changed_resolution_or_component (it);
333     it->first = FALSE;
334     return TRUE;
335   }
336 
337   it->cur_layer += 1;
338   if (it->cur_layer >= it->n_layers) {
339     it->cur_layer = 0;
340 
341     /* Loop and advance the position and resolution until
342      * we find the next precinct
343      */
344     while (TRUE) {
345       it->cur_resolution += 1;
346       if (it->cur_resolution >= it->n_resolutions) {
347         it->cur_resolution = 0;
348 
349         it->cur_x += it->x_step - (it->cur_x % it->x_step);
350         if (it->cur_x >= it->tx1) {
351           it->cur_x = it->tx0;
352 
353           it->cur_y += it->y_step - (it->cur_y % it->y_step);
354           if (it->cur_y >= it->ty1) {
355             it->cur_y = it->ty0;
356 
357             it->cur_component += 1;
358 
359             if (it->cur_component >= it->n_components) {
360               it->cur_packet++;
361               return FALSE;
362             }
363           }
364         }
365       }
366 
367       packet_iterator_changed_resolution_or_component (it);
368 
369       if (((it->cur_y % (it->yr * it->two_ppy * it->two_nl_r) == 0)
370               || (it->cur_y == it->ty0
371                   && ((it->try0 * it->two_nl_r) %
372                       (it->two_ppy * it->two_nl_r) != 0)))
373           && ((it->cur_x % (it->xr * it->two_ppx * it->two_nl_r) == 0)
374               || (it->cur_x == it->tx0
375                   && ((it->trx0 * it->two_nl_r) %
376                       (it->two_ppx * it->two_nl_r) != 0)))) {
377         gint k;
378 
379         k = (((it->cur_x + it->xr * it->two_nl_r - 1) /
380                 (it->xr * it->two_nl_r)) / it->two_ppx) -
381             (it->trx0 / it->two_ppx) +
382             it->n_precincts_w *
383             (((it->cur_y + it->yr * it->two_nl_r - 1) /
384                 (it->yr * it->two_nl_r)) / it->two_ppy);
385 
386         g_assert (k < it->n_precincts);
387 
388         it->cur_precinct = k;
389         break;
390       }
391     }
392   }
393 
394   it->cur_packet++;
395 
396   return TRUE;
397 }
398 
399 static GstFlowReturn
init_packet_iterator(GstJP2kDecimator * self,PacketIterator * it,const MainHeader * header,const Tile * tile)400 init_packet_iterator (GstJP2kDecimator * self, PacketIterator * it,
401     const MainHeader * header, const Tile * tile)
402 {
403   ProgressionOrder order;
404   gint i, j;
405 
406   memset (it, 0, sizeof (PacketIterator));
407 
408   it->header = header;
409   it->tile = tile;
410 
411   it->first = TRUE;
412 
413   it->n_layers = (tile->cod) ? tile->cod->n_layers : header->cod.n_layers;
414   it->n_resolutions =
415       1 +
416       ((tile->cod) ? tile->cod->n_decompositions : header->cod.
417       n_decompositions);
418   it->n_components = header->siz.n_components;
419 
420   it->tx0 = tile->tx0;
421   it->tx1 = tile->tx1;
422   it->ty0 = tile->ty0;
423   it->ty1 = tile->ty1;
424 
425   it->cur_x = it->tx0;
426   it->cur_y = it->ty0;
427 
428   /* Calculate the step sizes for the position-dependent progression orders */
429   it->x_step = it->y_step = 0;
430   for (i = 0; i < it->n_components; i++) {
431     gint xr, yr;
432 
433     xr = header->siz.components[i].xr;
434     yr = header->siz.components[i].yr;
435 
436 
437     for (j = 0; j < it->n_resolutions; j++) {
438       gint xs, ys;
439       guint8 PPx, PPy;
440 
441       if (tile->cod) {
442         PPx = (tile->cod->PPx) ? tile->cod->PPx[j] : 15;
443         PPy = (tile->cod->PPy) ? tile->cod->PPy[j] : 15;
444       } else {
445         PPx = (header->cod.PPx) ? header->cod.PPx[j] : 15;
446         PPy = (header->cod.PPy) ? header->cod.PPy[j] : 15;
447       }
448 
449       xs = xr * (1 << (PPx + it->n_resolutions - j - 1));
450       ys = yr * (1 << (PPy + it->n_resolutions - j - 1));
451 
452       if (it->x_step == 0 || it->x_step > xs)
453         it->x_step = xs;
454       if (it->y_step == 0 || it->y_step > ys)
455         it->y_step = ys;
456     }
457   }
458 
459   order =
460       (tile->cod) ? tile->cod->progression_order : header->cod.
461       progression_order;
462   if (order == PROGRESSION_ORDER_LRCP) {
463     it->next = packet_iterator_next_lrcp;
464   } else if (order == PROGRESSION_ORDER_RLCP) {
465     it->next = packet_iterator_next_rlcp;
466   } else if (order == PROGRESSION_ORDER_RPCL) {
467     it->next = packet_iterator_next_rpcl;
468   } else if (order == PROGRESSION_ORDER_PCRL) {
469     it->next = packet_iterator_next_pcrl;
470   } else if (order == PROGRESSION_ORDER_CPRL) {
471     it->next = packet_iterator_next_cprl;
472   } else {
473     GST_ERROR_OBJECT (self, "Progression order %d not supported", order);
474     return GST_FLOW_ERROR;
475   }
476 
477   return GST_FLOW_OK;
478 }
479 
480 static GstFlowReturn
parse_siz(GstJP2kDecimator * self,GstByteReader * reader,ImageSize * siz,guint16 length)481 parse_siz (GstJP2kDecimator * self, GstByteReader * reader,
482     ImageSize * siz, guint16 length)
483 {
484   gint i;
485 
486   if (length < 38) {
487     GST_ERROR_OBJECT (self, "Invalid SIZ marker");
488     return GST_FLOW_ERROR;
489   }
490 
491   siz->caps = gst_byte_reader_get_uint16_be_unchecked (reader);
492   siz->x = gst_byte_reader_get_uint32_be_unchecked (reader);
493   siz->y = gst_byte_reader_get_uint32_be_unchecked (reader);
494   siz->xo = gst_byte_reader_get_uint32_be_unchecked (reader);
495   siz->yo = gst_byte_reader_get_uint32_be_unchecked (reader);
496   siz->xt = gst_byte_reader_get_uint32_be_unchecked (reader);
497   siz->yt = gst_byte_reader_get_uint32_be_unchecked (reader);
498   siz->xto = gst_byte_reader_get_uint32_be_unchecked (reader);
499   siz->yto = gst_byte_reader_get_uint32_be_unchecked (reader);
500   siz->n_components = gst_byte_reader_get_uint16_be_unchecked (reader);
501 
502   if (length < 38 + 3 * siz->n_components) {
503     GST_ERROR_OBJECT (self, "Invalid SIZ marker");
504     return GST_FLOW_ERROR;
505   }
506 
507   siz->components = g_slice_alloc (sizeof (ComponentSize) * siz->n_components);
508   for (i = 0; i < siz->n_components; i++) {
509     siz->components[i].s = gst_byte_reader_get_uint8_unchecked (reader);
510     siz->components[i].xr = gst_byte_reader_get_uint8_unchecked (reader);
511     siz->components[i].yr = gst_byte_reader_get_uint8_unchecked (reader);
512   }
513 
514   return GST_FLOW_OK;
515 }
516 
517 static guint
sizeof_siz(GstJP2kDecimator * self,const ImageSize * siz)518 sizeof_siz (GstJP2kDecimator * self, const ImageSize * siz)
519 {
520   return 2 + 38 + 3 * siz->n_components;
521 }
522 
523 static void
reset_siz(GstJP2kDecimator * self,ImageSize * siz)524 reset_siz (GstJP2kDecimator * self, ImageSize * siz)
525 {
526   if (siz->components)
527     g_slice_free1 (sizeof (ComponentSize) * siz->n_components, siz->components);
528   memset (siz, 0, sizeof (ImageSize));
529 }
530 
531 static GstFlowReturn
write_siz(GstJP2kDecimator * self,GstByteWriter * writer,const ImageSize * siz)532 write_siz (GstJP2kDecimator * self, GstByteWriter * writer,
533     const ImageSize * siz)
534 {
535   gint i;
536 
537   if (!gst_byte_writer_ensure_free_space (writer,
538           2 + 38 + 3 * siz->n_components)) {
539     GST_ERROR_OBJECT (self, "Could not ensure free space");
540     return GST_FLOW_ERROR;
541   }
542 
543   gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_SIZ);
544   gst_byte_writer_put_uint16_be_unchecked (writer, 38 + 3 * siz->n_components);
545   gst_byte_writer_put_uint16_be_unchecked (writer, siz->caps);
546   gst_byte_writer_put_uint32_be_unchecked (writer, siz->x);
547   gst_byte_writer_put_uint32_be_unchecked (writer, siz->y);
548   gst_byte_writer_put_uint32_be_unchecked (writer, siz->xo);
549   gst_byte_writer_put_uint32_be_unchecked (writer, siz->yo);
550   gst_byte_writer_put_uint32_be_unchecked (writer, siz->xt);
551   gst_byte_writer_put_uint32_be_unchecked (writer, siz->yt);
552   gst_byte_writer_put_uint32_be_unchecked (writer, siz->xto);
553   gst_byte_writer_put_uint32_be_unchecked (writer, siz->yto);
554   gst_byte_writer_put_uint16_be_unchecked (writer, siz->n_components);
555 
556   for (i = 0; i < siz->n_components; i++) {
557     gst_byte_writer_put_uint8_unchecked (writer, siz->components[i].s);
558     gst_byte_writer_put_uint8_unchecked (writer, siz->components[i].xr);
559     gst_byte_writer_put_uint8_unchecked (writer, siz->components[i].yr);
560   }
561 
562   return GST_FLOW_OK;
563 }
564 
565 static GstFlowReturn
parse_cod(GstJP2kDecimator * self,GstByteReader * reader,CodingStyleDefault * cod,guint16 length)566 parse_cod (GstJP2kDecimator * self, GstByteReader * reader,
567     CodingStyleDefault * cod, guint16 length)
568 {
569   guint8 Scod;
570 
571   if (length < 12) {
572     GST_ERROR_OBJECT (self, "Invalid COD marker");
573     return GST_FLOW_ERROR;
574   }
575 
576   Scod = gst_byte_reader_get_uint8_unchecked (reader);
577   cod->sop = ! !(Scod & 0x02);
578   cod->eph = ! !(Scod & 0x04);
579 
580   /* SGcod */
581   cod->progression_order = gst_byte_reader_get_uint8_unchecked (reader);
582   cod->n_layers = gst_byte_reader_get_uint16_be_unchecked (reader);
583   cod->multi_component_transform = gst_byte_reader_get_uint8_unchecked (reader);
584 
585   /* SPcod */
586   cod->n_decompositions = gst_byte_reader_get_uint8_unchecked (reader);
587   cod->xcb = gst_byte_reader_get_uint8_unchecked (reader) + 2;
588   cod->ycb = gst_byte_reader_get_uint8_unchecked (reader) + 2;
589   cod->code_block_style = gst_byte_reader_get_uint8_unchecked (reader);
590   cod->transformation = gst_byte_reader_get_uint8_unchecked (reader);
591 
592   if ((Scod & 0x01)) {
593     gint i;
594     /* User defined precincts */
595 
596     if (length < 12 + (Scod & 0x01) * (cod->n_decompositions + 1)) {
597       GST_ERROR_OBJECT (self, "Invalid COD marker");
598       return GST_FLOW_ERROR;
599     }
600 
601     cod->PPx = g_slice_alloc (sizeof (guint8) * (cod->n_decompositions + 1));
602     for (i = 0; i < cod->n_decompositions + 1; i++) {
603       guint8 v = gst_byte_reader_get_uint8_unchecked (reader);
604       cod->PPx[i] = (v & 0x0f);
605       cod->PPy[i] = (v >> 4);
606     }
607   }
608 
609   return GST_FLOW_OK;
610 }
611 
612 static guint
sizeof_cod(GstJP2kDecimator * self,const CodingStyleDefault * cod)613 sizeof_cod (GstJP2kDecimator * self, const CodingStyleDefault * cod)
614 {
615   return 2 + 12 + (cod->PPx ? (cod->n_decompositions + 1) : 0);
616 }
617 
618 static void
reset_cod(GstJP2kDecimator * self,CodingStyleDefault * cod)619 reset_cod (GstJP2kDecimator * self, CodingStyleDefault * cod)
620 {
621   if (cod->PPx)
622     g_slice_free1 (sizeof (guint8) * (cod->n_decompositions + 1), cod->PPx);
623   if (cod->PPy)
624     g_slice_free1 (sizeof (guint8) * (cod->n_decompositions + 1), cod->PPy);
625   memset (cod, 0, sizeof (CodingStyleDefault));
626 }
627 
628 static GstFlowReturn
write_cod(GstJP2kDecimator * self,GstByteWriter * writer,const CodingStyleDefault * cod)629 write_cod (GstJP2kDecimator * self, GstByteWriter * writer,
630     const CodingStyleDefault * cod)
631 {
632   guint tmp;
633 
634   tmp = 12 + (cod->PPx ? (1 + cod->n_decompositions) : 0);
635   if (!gst_byte_writer_ensure_free_space (writer, tmp)) {
636     GST_ERROR_OBJECT (self, "Could not ensure free space");
637     return GST_FLOW_ERROR;
638   }
639 
640   gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_COD);
641   gst_byte_writer_put_uint16_be_unchecked (writer, tmp);
642 
643   /* Scod */
644   tmp =
645       (cod->PPx ? 0x01 : 0x00) | (cod->sop ? 0x02 : 0x00) | (cod->
646       eph ? 0x04 : 0x00);
647   gst_byte_writer_put_uint8_unchecked (writer, tmp);
648 
649   /* SGcod */
650   gst_byte_writer_put_uint8_unchecked (writer, cod->progression_order);
651   gst_byte_writer_put_uint16_be_unchecked (writer, cod->n_layers);
652   gst_byte_writer_put_uint8_unchecked (writer, cod->multi_component_transform);
653 
654   /* SPcod */
655   gst_byte_writer_put_uint8_unchecked (writer, cod->n_decompositions);
656   gst_byte_writer_put_uint8_unchecked (writer, cod->xcb - 2);
657   gst_byte_writer_put_uint8_unchecked (writer, cod->ycb - 2);
658   gst_byte_writer_put_uint8_unchecked (writer, cod->code_block_style);
659   gst_byte_writer_put_uint8_unchecked (writer, cod->transformation);
660 
661   if (cod->PPx) {
662     gint i;
663 
664     for (i = 0; i < cod->n_decompositions + 1; i++) {
665       tmp = (cod->PPx[i]) | (cod->PPy[i] << 4);
666       gst_byte_writer_put_uint8_unchecked (writer, tmp);
667     }
668   }
669 
670   return GST_FLOW_OK;
671 }
672 
673 static GstFlowReturn
parse_plt(GstJP2kDecimator * self,GstByteReader * reader,PacketLengthTilePart * plt,guint length)674 parse_plt (GstJP2kDecimator * self, GstByteReader * reader,
675     PacketLengthTilePart * plt, guint length)
676 {
677   guint32 n;
678   guint8 b = 0;
679   gint i;
680 
681   if (length < 3) {
682     GST_ERROR_OBJECT (self, "Invalid PLT");
683     return GST_FLOW_ERROR;
684   }
685 
686   plt->index = gst_byte_reader_get_uint8_unchecked (reader);
687   plt->packet_lengths = g_array_new (FALSE, FALSE, sizeof (guint32));
688 
689   length -= 3;
690 
691   n = 0;
692   for (i = 0; i < length; i++) {
693     b = gst_byte_reader_get_uint8_unchecked (reader);
694 
695     if ((n & 0xfe000000)) {
696       GST_ERROR_OBJECT (self, "PLT element overflow");
697       return GST_FLOW_ERROR;
698     }
699 
700     n = (n << 7) | (b & 0x7f);
701     if ((b & 0x80) == 0x00) {
702       g_array_append_val (plt->packet_lengths, n);
703       n = 0;
704     }
705   }
706 
707   if ((b & 0x80) != 0x00) {
708     GST_ERROR_OBJECT (self, "Truncated PLT");
709     return GST_FLOW_ERROR;
710   }
711   return GST_FLOW_OK;
712 }
713 
714 static guint
sizeof_plt(GstJP2kDecimator * self,const PacketLengthTilePart * plt)715 sizeof_plt (GstJP2kDecimator * self, const PacketLengthTilePart * plt)
716 {
717   guint size = 2 + 3;
718   gint i, n;
719 
720   n = plt->packet_lengths->len;
721   for (i = 0; i < n; i++) {
722     guint32 len = g_array_index (plt->packet_lengths, guint32, i);
723 
724     if (len < (1 << 7)) {
725       size += 1;
726     } else if (len < (1 << 14)) {
727       size += 2;
728     } else if (len < (1 << 21)) {
729       size += 3;
730     } else if (len < (1 << 28)) {
731       size += 4;
732     } else {
733       size += 5;
734     }
735   }
736 
737   return size;
738 }
739 
740 static void
reset_plt(GstJP2kDecimator * self,PacketLengthTilePart * plt)741 reset_plt (GstJP2kDecimator * self, PacketLengthTilePart * plt)
742 {
743   if (plt->packet_lengths)
744     g_array_free (plt->packet_lengths, TRUE);
745   memset (plt, 0, sizeof (PacketLengthTilePart));
746 }
747 
748 static GstFlowReturn
write_plt(GstJP2kDecimator * self,GstByteWriter * writer,const PacketLengthTilePart * plt)749 write_plt (GstJP2kDecimator * self, GstByteWriter * writer,
750     const PacketLengthTilePart * plt)
751 {
752   gint i, n;
753   guint plt_start_pos, plt_end_pos;
754 
755   if (!gst_byte_writer_ensure_free_space (writer, 2 + 2 + 1)) {
756     GST_ERROR_OBJECT (self, "Could not ensure free space");
757     return GST_FLOW_ERROR;
758   }
759 
760   gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_PLT);
761   plt_start_pos = gst_byte_writer_get_pos (writer);
762   gst_byte_writer_put_uint16_be_unchecked (writer, 0);
763 
764   gst_byte_writer_put_uint8_unchecked (writer, plt->index);
765 
766   n = plt->packet_lengths->len;
767   for (i = 0; i < n; i++) {
768     guint32 len = g_array_index (plt->packet_lengths, guint32, i);
769 
770     /* FIXME: Write multiple plt here */
771     if (gst_byte_writer_get_pos (writer) - plt_start_pos > 65535 - 5) {
772       GST_ERROR_OBJECT (self, "Too big PLT");
773       return GST_FLOW_ERROR;
774     }
775 
776     if (len < (1 << 7)) {
777       if (!gst_byte_writer_ensure_free_space (writer, 1)) {
778         GST_ERROR_OBJECT (self, "Could not ensure free space");
779         return GST_FLOW_ERROR;
780       }
781       gst_byte_writer_put_uint8_unchecked (writer, (0x00 | (len & 0x7f)));
782     } else if (len < (1 << 14)) {
783       if (!gst_byte_writer_ensure_free_space (writer, 2)) {
784         GST_ERROR_OBJECT (self, "Could not ensure free space");
785         return GST_FLOW_ERROR;
786       }
787       gst_byte_writer_put_uint8_unchecked (writer,
788           (0x80 | ((len >> 7) & 0x7f)));
789       gst_byte_writer_put_uint8_unchecked (writer, (0x00 | (len & 0x7f)));
790     } else if (len < (1 << 21)) {
791       if (!gst_byte_writer_ensure_free_space (writer, 3)) {
792         GST_ERROR_OBJECT (self, "Could not ensure free space");
793         return GST_FLOW_ERROR;
794       }
795       gst_byte_writer_put_uint8_unchecked (writer,
796           (0x80 | ((len >> 14) & 0x7f)));
797       gst_byte_writer_put_uint8_unchecked (writer,
798           (0x80 | ((len >> 7) & 0x7f)));
799       gst_byte_writer_put_uint8_unchecked (writer, (0x00 | (len & 0x7f)));
800     } else if (len < (1 << 28)) {
801       if (!gst_byte_writer_ensure_free_space (writer, 4)) {
802         GST_ERROR_OBJECT (self, "Could not ensure free space");
803         return GST_FLOW_ERROR;
804       }
805       gst_byte_writer_put_uint8_unchecked (writer,
806           (0x80 | ((len >> 21) & 0x7f)));
807       gst_byte_writer_put_uint8_unchecked (writer,
808           (0x80 | ((len >> 14) & 0x7f)));
809       gst_byte_writer_put_uint8_unchecked (writer,
810           (0x80 | ((len >> 7) & 0x7f)));
811       gst_byte_writer_put_uint8_unchecked (writer, (0x00 | (len & 0x7f)));
812     } else {
813       if (!gst_byte_writer_ensure_free_space (writer, 5)) {
814         GST_ERROR_OBJECT (self, "Could not ensure free space");
815         return GST_FLOW_ERROR;
816       }
817       gst_byte_writer_put_uint8_unchecked (writer,
818           (0x80 | ((len >> 28) & 0x7f)));
819       gst_byte_writer_put_uint8_unchecked (writer,
820           (0x80 | ((len >> 21) & 0x7f)));
821       gst_byte_writer_put_uint8_unchecked (writer,
822           (0x80 | ((len >> 14) & 0x7f)));
823       gst_byte_writer_put_uint8_unchecked (writer,
824           (0x80 | ((len >> 7) & 0x7f)));
825       gst_byte_writer_put_uint8_unchecked (writer, (0x00 | (len & 0x7f)));
826     }
827   }
828 
829   plt_end_pos = gst_byte_writer_get_pos (writer);
830   gst_byte_writer_set_pos (writer, plt_start_pos);
831   if (!gst_byte_writer_put_uint16_be (writer, plt_end_pos - plt_start_pos)) {
832     GST_ERROR_OBJECT (self, "Not enough space to write plt size");
833     return GST_FLOW_ERROR;
834   }
835 
836   gst_byte_writer_set_pos (writer, plt_end_pos);
837 
838   return GST_FLOW_OK;
839 }
840 
841 static GstFlowReturn
parse_packet(GstJP2kDecimator * self,GstByteReader * reader,const MainHeader * header,Tile * tile,const PacketIterator * it)842 parse_packet (GstJP2kDecimator * self, GstByteReader * reader,
843     const MainHeader * header, Tile * tile, const PacketIterator * it)
844 {
845   GstFlowReturn ret = GST_FLOW_OK;
846   guint16 marker = 0, length;
847   guint16 seqno = 0;
848   guint packet_start_pos;
849   const guint8 *packet_start_data;
850   gboolean sop, eph;
851   PacketLengthTilePart *plt = NULL;
852 
853   sop = (tile->cod) ? tile->cod->sop : header->cod.sop;
854   eph = (tile->cod) ? tile->cod->eph : header->cod.eph;
855   if (tile->plt) {
856     if (g_list_length (tile->plt) > 1) {
857       GST_ERROR_OBJECT (self,
858           "Only a single PLT per tile is supported currently");
859       ret = GST_FLOW_ERROR;
860       goto done;
861     }
862     plt = tile->plt->data;
863   }
864 
865   if (plt) {
866     guint32 length;
867     Packet *p;
868 
869     if (plt->packet_lengths->len <= it->cur_packet) {
870       GST_ERROR_OBJECT (self, "Truncated PLT");
871       ret = GST_FLOW_ERROR;
872       goto done;
873     }
874 
875     length = g_array_index (plt->packet_lengths, guint32, it->cur_packet);
876 
877     if (gst_byte_reader_get_remaining (reader) < length) {
878       GST_ERROR_OBJECT (self, "Truncated file");
879       ret = GST_FLOW_ERROR;
880       goto done;
881     }
882 
883     p = g_slice_new0 (Packet);
884 
885     /* If there is a SOP keep the seqno */
886     if (sop && length > 6) {
887       if (!gst_byte_reader_peek_uint16_be (reader, &marker)) {
888         GST_ERROR_OBJECT (self, "Truncated file");
889         ret = GST_FLOW_ERROR;
890         g_slice_free (Packet, p);
891         goto done;
892       }
893 
894       if (marker == MARKER_SOP) {
895         guint16 dummy;
896 
897         gst_byte_reader_skip_unchecked (reader, 2);
898 
899         if (!gst_byte_reader_get_uint16_be (reader, &dummy)) {
900           GST_ERROR_OBJECT (self, "Truncated file");
901           ret = GST_FLOW_ERROR;
902           g_slice_free (Packet, p);
903           goto done;
904         }
905 
906         if (!gst_byte_reader_get_uint16_be (reader, &seqno)) {
907           GST_ERROR_OBJECT (self, "Truncated file");
908           ret = GST_FLOW_ERROR;
909           g_slice_free (Packet, p);
910           goto done;
911         }
912         p->data = gst_byte_reader_peek_data_unchecked (reader);
913         p->length = length - 6;
914         p->sop = TRUE;
915         p->eph = eph;
916         p->seqno = seqno;
917         gst_byte_reader_skip_unchecked (reader, length - 6);
918       }
919     }
920 
921     if (!p->data) {
922       p->data = gst_byte_reader_peek_data_unchecked (reader);
923       p->length = length;
924       p->sop = FALSE;
925       p->eph = eph;
926       gst_byte_reader_skip_unchecked (reader, length);
927     }
928 
929     tile->packets = g_list_prepend (tile->packets, p);
930   } else if (sop) {
931     if (!gst_byte_reader_peek_uint16_be (reader, &marker)) {
932       GST_ERROR_OBJECT (self, "Truncated file");
933       ret = GST_FLOW_ERROR;
934       goto done;
935     }
936 
937     if (marker != MARKER_SOP) {
938       GST_ERROR_OBJECT (self, "No SOP marker");
939       ret = GST_FLOW_EOS;
940       goto done;
941     }
942 
943     gst_byte_reader_skip_unchecked (reader, 2);
944 
945     if (!gst_byte_reader_get_uint16_be (reader, &length)) {
946       GST_ERROR_OBJECT (self, "Truncated file");
947       ret = GST_FLOW_ERROR;
948       goto done;
949     }
950 
951     if (!gst_byte_reader_get_uint16_be (reader, &seqno)) {
952       GST_ERROR_OBJECT (self, "Truncated file");
953       ret = GST_FLOW_ERROR;
954       goto done;
955     }
956 
957     packet_start_data = reader->data + reader->byte;
958     packet_start_pos = gst_byte_reader_get_pos (reader);
959 
960     /* Find end of packet */
961     while (TRUE) {
962       if (!gst_byte_reader_peek_uint16_be (reader, &marker)) {
963         GST_ERROR_OBJECT (self, "Truncated file");
964         ret = GST_FLOW_ERROR;
965         goto done;
966       }
967 
968       if (marker == MARKER_SOP || marker == MARKER_EOC || marker == MARKER_SOT) {
969         Packet *p = g_slice_new (Packet);
970 
971         p->sop = TRUE;
972         p->eph = eph;
973         p->seqno = seqno;
974         p->data = packet_start_data;
975         p->length = reader->byte - packet_start_pos;
976         tile->packets = g_list_prepend (tile->packets, p);
977 
978         if (marker == MARKER_EOC || marker == MARKER_SOT)
979           goto done;
980         else
981           break;
982       }
983 
984       gst_byte_reader_skip_unchecked (reader, 1);
985     }
986   } else {
987     GST_ERROR_OBJECT (self, "Either PLT or SOP are required");
988     ret = GST_FLOW_ERROR;
989     goto done;
990   }
991 
992 done:
993 
994   return ret;
995 }
996 
997 static guint
sizeof_packet(GstJP2kDecimator * self,const Packet * packet)998 sizeof_packet (GstJP2kDecimator * self, const Packet * packet)
999 {
1000   return packet->length + (packet->sop ? 6 : 0) + ((packet->eph
1001           && !packet->data) ? 2 : 0);
1002 }
1003 
1004 static GstFlowReturn
parse_packets(GstJP2kDecimator * self,GstByteReader * reader,const MainHeader * header,Tile * tile)1005 parse_packets (GstJP2kDecimator * self, GstByteReader * reader,
1006     const MainHeader * header, Tile * tile)
1007 {
1008   guint16 marker = 0;
1009   GstFlowReturn ret = GST_FLOW_OK;
1010   PacketIterator it;
1011 
1012   /* Start of data here */
1013   if (!gst_byte_reader_get_uint16_be (reader, &marker)
1014       && marker != MARKER_SOD) {
1015     GST_ERROR_OBJECT (self, "No SOD in tile");
1016     return GST_FLOW_ERROR;
1017   }
1018 
1019   ret = init_packet_iterator (self, &it, header, tile);
1020   if (ret != GST_FLOW_OK)
1021     goto done;
1022 
1023   while ((it.next (&it))) {
1024     ret = parse_packet (self, reader, header, tile, &it);
1025     if (ret != GST_FLOW_OK)
1026       goto done;
1027   }
1028 
1029   tile->packets = g_list_reverse (tile->packets);
1030 
1031 done:
1032 
1033   return ret;
1034 }
1035 
1036 static GstFlowReturn
parse_tile(GstJP2kDecimator * self,GstByteReader * reader,const MainHeader * header,Tile * tile)1037 parse_tile (GstJP2kDecimator * self, GstByteReader * reader,
1038     const MainHeader * header, Tile * tile)
1039 {
1040   GstFlowReturn ret = GST_FLOW_OK;
1041   guint16 marker = 0, length;
1042 
1043   if (!gst_byte_reader_peek_uint16_be (reader, &marker)) {
1044     GST_ERROR_OBJECT (self, "Could not read marker");
1045     ret = GST_FLOW_ERROR;
1046     goto done;
1047   }
1048 
1049   if (marker != MARKER_SOT) {
1050     GST_ERROR_OBJECT (self, "Unexpected marker 0x%04x", marker);
1051     ret = GST_FLOW_ERROR;
1052     goto done;
1053   }
1054 
1055   /* Skip marker */
1056   gst_byte_reader_skip_unchecked (reader, 2);
1057 
1058   if (gst_byte_reader_get_remaining (reader) < 10) {
1059     GST_ERROR_OBJECT (self, "Invalid SOT marker");
1060     ret = GST_FLOW_ERROR;
1061     goto done;
1062   }
1063 
1064   length = gst_byte_reader_get_uint16_be_unchecked (reader);
1065   if (length != 10) {
1066     GST_ERROR_OBJECT (self, "Invalid SOT length");
1067     ret = GST_FLOW_ERROR;
1068     goto done;
1069   }
1070 
1071   /* FIXME: handle multiple tile parts per tile */
1072   tile->sot.tile_index = gst_byte_reader_get_uint16_be_unchecked (reader);
1073   tile->sot.tile_part_size = gst_byte_reader_get_uint32_be_unchecked (reader);
1074   tile->sot.tile_part_index = gst_byte_reader_get_uint8_unchecked (reader);
1075   tile->sot.n_tile_parts = gst_byte_reader_get_uint8_unchecked (reader);
1076 
1077   if (tile->sot.tile_part_size >
1078       2 + 10 + gst_byte_reader_get_remaining (reader)) {
1079     GST_ERROR_OBJECT (self, "Truncated tile part");
1080     ret = GST_FLOW_ERROR;
1081     goto done;
1082   }
1083 
1084   tile->tile_x = tile->sot.tile_index % header->n_tiles_x;
1085   tile->tile_y = tile->sot.tile_index / header->n_tiles_x;
1086 
1087   tile->tx0 =
1088       MAX (header->siz.xto + tile->tile_x * header->siz.xt, header->siz.xo);
1089   tile->ty0 =
1090       MAX (header->siz.yto + tile->tile_y * header->siz.yt, header->siz.yo);
1091   tile->tx1 =
1092       MIN (header->siz.xto + (tile->tile_x + 1) * header->siz.xt,
1093       header->siz.x);
1094   tile->ty1 =
1095       MIN (header->siz.yto + (tile->tile_y + 1) * header->siz.yt,
1096       header->siz.y);
1097 
1098   /* tile part header */
1099   while (TRUE) {
1100     if (!gst_byte_reader_peek_uint16_be (reader, &marker)) {
1101       GST_ERROR_OBJECT (self, "Could not read marker");
1102       ret = GST_FLOW_ERROR;
1103       goto done;
1104     }
1105 
1106     /* SOD starts the data */
1107     if (marker == MARKER_SOD) {
1108       break;
1109     }
1110 
1111     if ((marker >> 8) != 0xff) {
1112       GST_ERROR_OBJECT (self, "Lost synchronization (0x%04x)", marker);
1113       ret = GST_FLOW_ERROR;
1114       goto done;
1115     }
1116 
1117     /* Skip the marker */
1118     gst_byte_reader_skip_unchecked (reader, 2);
1119 
1120     /* All markers here have a length */
1121     if (!gst_byte_reader_get_uint16_be (reader, &length)) {
1122       GST_ERROR_OBJECT (self, "Could not read marker length");
1123       ret = GST_FLOW_ERROR;
1124       goto done;
1125     }
1126 
1127     if (length < 2 || gst_byte_reader_get_remaining (reader) < length - 2) {
1128       GST_ERROR_OBJECT (self, "Invalid marker length %u (available %u)",
1129           length, gst_byte_reader_get_remaining (reader));
1130       ret = GST_FLOW_ERROR;
1131       goto done;
1132     }
1133 
1134     GST_LOG_OBJECT (self,
1135         "Tile header Marker 0x%04x at offset %u with length %u", marker,
1136         gst_byte_reader_get_pos (reader), length);
1137 
1138     switch (marker) {
1139       case MARKER_COD:
1140         if (tile->cod) {
1141           GST_ERROR_OBJECT (self, "Only one COD allowed");
1142           ret = GST_FLOW_ERROR;
1143           goto done;
1144         }
1145 
1146         tile->cod = g_slice_new0 (CodingStyleDefault);
1147         ret = parse_cod (self, reader, tile->cod, length);
1148         if (ret != GST_FLOW_OK)
1149           goto done;
1150         break;
1151       case MARKER_COC:
1152         GST_ERROR_OBJECT (self, "COC marker not supported yet");
1153         ret = GST_FLOW_ERROR;
1154         goto done;
1155       case MARKER_POC:
1156         GST_ERROR_OBJECT (self, "POC marker not supported yet");
1157         ret = GST_FLOW_ERROR;
1158         goto done;
1159       case MARKER_RGN:
1160         GST_ERROR_OBJECT (self, "RGN marker not supported yet");
1161         ret = GST_FLOW_ERROR;
1162         goto done;
1163       case MARKER_PPT:
1164         GST_ERROR_OBJECT (self, "PPT marker not supported yet");
1165         ret = GST_FLOW_ERROR;
1166         goto done;
1167       case MARKER_PLT:{
1168         PacketLengthTilePart *plt = g_slice_new (PacketLengthTilePart);
1169 
1170         ret = parse_plt (self, reader, plt, length);
1171         if (ret != GST_FLOW_OK) {
1172           g_slice_free (PacketLengthTilePart, plt);
1173           goto done;
1174         }
1175 
1176         tile->plt = g_list_append (tile->plt, plt);
1177         break;
1178       }
1179       case MARKER_QCD:
1180         if (tile->qcd != NULL) {
1181           GST_ERROR_OBJECT (self, "Multiple QCD markers");
1182           ret = GST_FLOW_ERROR;
1183           goto done;
1184         }
1185         tile->qcd = g_slice_new (Buffer);
1186         tile->qcd->data = gst_byte_reader_peek_data_unchecked (reader);
1187         tile->qcd->length = length - 2;
1188         gst_byte_reader_skip_unchecked (reader, length - 2);
1189         break;
1190       case MARKER_QCC:{
1191         Buffer *p = g_slice_new (Buffer);
1192         p->data = gst_byte_reader_peek_data_unchecked (reader);
1193         p->length = length - 2;
1194         tile->qcc = g_list_append (tile->qcc, p);
1195         gst_byte_reader_skip_unchecked (reader, length - 2);
1196         break;
1197       }
1198       case MARKER_COM:{
1199         Buffer *p = g_slice_new (Buffer);
1200         p->data = gst_byte_reader_peek_data_unchecked (reader);
1201         p->length = length - 2;
1202         tile->com = g_list_append (tile->com, p);
1203         gst_byte_reader_skip_unchecked (reader, length - 2);
1204         break;
1205       }
1206       default:
1207         GST_DEBUG_OBJECT (self, "Skipping unknown marker 0x%04x", marker);
1208         gst_byte_reader_skip_unchecked (reader, length - 2);
1209         break;
1210     }
1211   }
1212 
1213   ret = parse_packets (self, reader, header, tile);
1214 
1215 done:
1216 
1217   return ret;
1218 }
1219 
1220 static guint
sizeof_tile(GstJP2kDecimator * self,const Tile * tile)1221 sizeof_tile (GstJP2kDecimator * self, const Tile * tile)
1222 {
1223   guint size = 0;
1224   GList *l;
1225 
1226   /* SOT */
1227   size += 2 + 2 + 2 + 4 + 1 + 1;
1228 
1229   if (tile->cod)
1230     size += sizeof_cod (self, tile->cod);
1231 
1232   if (tile->qcd)
1233     size += 2 + 2 + tile->qcd->length;
1234 
1235   for (l = tile->qcc; l; l = l->next) {
1236     Buffer *b = l->data;
1237     size += 2 + 2 + b->length;
1238   }
1239 
1240   for (l = tile->plt; l; l = l->next) {
1241     PacketLengthTilePart *plt = l->data;
1242     size += sizeof_plt (self, plt);
1243   }
1244 
1245   for (l = tile->com; l; l = l->next) {
1246     Buffer *b = l->data;
1247     size += 2 + 2 + b->length;
1248   }
1249 
1250   /* SOD */
1251   size += 2;
1252 
1253   for (l = tile->packets; l; l = l->next) {
1254     Packet *p = l->data;
1255     size += sizeof_packet (self, p);
1256   }
1257 
1258   return size;
1259 }
1260 
1261 static void
reset_tile(GstJP2kDecimator * self,const MainHeader * header,Tile * tile)1262 reset_tile (GstJP2kDecimator * self, const MainHeader * header, Tile * tile)
1263 {
1264   GList *l;
1265 
1266   if (tile->cod) {
1267     reset_cod (self, tile->cod);
1268     g_slice_free (CodingStyleDefault, tile->cod);
1269   }
1270 
1271   for (l = tile->plt; l; l = l->next) {
1272     PacketLengthTilePart *plt = l->data;
1273 
1274     reset_plt (self, plt);
1275 
1276     g_slice_free (PacketLengthTilePart, plt);
1277   }
1278   g_list_free (tile->plt);
1279 
1280   if (tile->qcd)
1281     g_slice_free (Buffer, tile->qcd);
1282 
1283   for (l = tile->qcc; l; l = l->next) {
1284     g_slice_free (Buffer, l->data);
1285   }
1286   g_list_free (tile->qcc);
1287 
1288   for (l = tile->com; l; l = l->next) {
1289     g_slice_free (Buffer, l->data);
1290   }
1291   g_list_free (tile->com);
1292 
1293   for (l = tile->packets; l; l = l->next) {
1294     Packet *p = l->data;
1295 
1296     g_slice_free (Packet, p);
1297   }
1298   g_list_free (tile->packets);
1299 
1300   memset (tile, 0, sizeof (Tile));
1301 }
1302 
1303 static GstFlowReturn
write_marker_buffer(GstJP2kDecimator * self,GstByteWriter * writer,guint16 marker,const Buffer * buffer)1304 write_marker_buffer (GstJP2kDecimator * self, GstByteWriter * writer,
1305     guint16 marker, const Buffer * buffer)
1306 {
1307   if (!gst_byte_writer_ensure_free_space (writer, 2 + 2 + buffer->length)) {
1308     GST_ERROR_OBJECT (self, "Could not ensure free space");
1309     return GST_FLOW_ERROR;
1310   }
1311 
1312   gst_byte_writer_put_uint16_be_unchecked (writer, marker);
1313   gst_byte_writer_put_uint16_be_unchecked (writer, buffer->length + 2);
1314   gst_byte_writer_put_data_unchecked (writer, buffer->data, buffer->length);
1315 
1316   return GST_FLOW_OK;
1317 }
1318 
1319 static GstFlowReturn
write_packet(GstJP2kDecimator * self,GstByteWriter * writer,const Packet * packet)1320 write_packet (GstJP2kDecimator * self, GstByteWriter * writer,
1321     const Packet * packet)
1322 {
1323   guint size = packet->length;
1324 
1325   if (packet->sop)
1326     size += 6;
1327   if (packet->eph && !packet->data)
1328     size += 2;
1329 
1330   if (!gst_byte_writer_ensure_free_space (writer, size)) {
1331     GST_ERROR_OBJECT (self, "Could not ensure free space");
1332     return GST_FLOW_ERROR;
1333   }
1334 
1335   if (packet->sop) {
1336     gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_SOP);
1337     gst_byte_writer_put_uint16_be_unchecked (writer, 4);
1338     gst_byte_writer_put_uint16_be_unchecked (writer, packet->seqno);
1339   }
1340 
1341   if (packet->data) {
1342     gst_byte_writer_put_data_unchecked (writer, packet->data, packet->length);
1343   } else {
1344     gst_byte_writer_put_uint8_unchecked (writer, 0);
1345     if (packet->eph) {
1346       gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_EPH);
1347     }
1348   }
1349 
1350   return GST_FLOW_OK;
1351 }
1352 
1353 static GstFlowReturn
write_tile(GstJP2kDecimator * self,GstByteWriter * writer,const MainHeader * header,Tile * tile)1354 write_tile (GstJP2kDecimator * self, GstByteWriter * writer,
1355     const MainHeader * header, Tile * tile)
1356 {
1357   GList *l;
1358   GstFlowReturn ret = GST_FLOW_OK;
1359 
1360   if (!gst_byte_writer_ensure_free_space (writer, 12)) {
1361     GST_ERROR_OBJECT (self, "Could not ensure free space");
1362     return GST_FLOW_ERROR;
1363   }
1364 
1365   gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_SOT);
1366   gst_byte_writer_put_uint16_be_unchecked (writer, 10);
1367 
1368   gst_byte_writer_put_uint16_be_unchecked (writer, tile->sot.tile_index);
1369   gst_byte_writer_put_uint32_be_unchecked (writer, tile->sot.tile_part_size);
1370   gst_byte_writer_put_uint8_unchecked (writer, tile->sot.tile_part_index);
1371   gst_byte_writer_put_uint8_unchecked (writer, tile->sot.n_tile_parts);
1372 
1373   if (tile->cod) {
1374     ret = write_cod (self, writer, tile->cod);
1375     if (ret != GST_FLOW_OK)
1376       goto done;
1377   }
1378 
1379   if (tile->qcd) {
1380     ret = write_marker_buffer (self, writer, MARKER_QCD, tile->qcd);
1381     if (ret != GST_FLOW_OK)
1382       goto done;
1383   }
1384 
1385   for (l = tile->qcc; l; l = l->next) {
1386     Buffer *p = l->data;
1387 
1388     ret = write_marker_buffer (self, writer, MARKER_QCC, p);
1389     if (ret != GST_FLOW_OK)
1390       goto done;
1391   }
1392 
1393   for (l = tile->plt; l; l = l->next) {
1394     PacketLengthTilePart *plt = l->data;
1395 
1396     ret = write_plt (self, writer, plt);
1397     if (ret != GST_FLOW_OK)
1398       goto done;
1399   }
1400 
1401   for (l = tile->com; l; l = l->next) {
1402     Buffer *p = l->data;
1403 
1404     ret = write_marker_buffer (self, writer, MARKER_COM, p);
1405     if (ret != GST_FLOW_OK)
1406       goto done;
1407   }
1408 
1409   if (!gst_byte_writer_put_uint16_be (writer, MARKER_SOD)) {
1410     GST_ERROR_OBJECT (self, "Could not ensure free space");
1411     ret = GST_FLOW_ERROR;
1412     goto done;
1413   }
1414 
1415   for (l = tile->packets; l; l = l->next) {
1416     Packet *p = l->data;
1417 
1418     ret = write_packet (self, writer, p);
1419     if (ret != GST_FLOW_OK)
1420       goto done;
1421   }
1422 
1423 done:
1424 
1425   return ret;
1426 }
1427 
1428 GstFlowReturn
parse_main_header(GstJP2kDecimator * self,GstByteReader * reader,MainHeader * header)1429 parse_main_header (GstJP2kDecimator * self, GstByteReader * reader,
1430     MainHeader * header)
1431 {
1432   GstFlowReturn ret = GST_FLOW_OK;
1433   guint16 marker = 0, length = 0;
1434 
1435   /* First SOC */
1436   if (!gst_byte_reader_get_uint16_be (reader, &marker)
1437       || marker != MARKER_SOC) {
1438     GST_ERROR_OBJECT (self, "Frame does not start with SOC");
1439     ret = GST_FLOW_ERROR;
1440     goto done;
1441   }
1442 
1443   while (TRUE) {
1444     if (!gst_byte_reader_peek_uint16_be (reader, &marker)) {
1445       GST_ERROR_OBJECT (self, "Could not read marker");
1446       ret = GST_FLOW_ERROR;
1447       goto done;
1448     }
1449 
1450     /* SOT starts the tiles */
1451     if (marker == MARKER_SOT) {
1452       ret = GST_FLOW_OK;
1453       break;
1454     } else if (marker == MARKER_EOC) {
1455       GST_WARNING_OBJECT (self, "EOC marker before SOT");
1456       ret = GST_FLOW_EOS;
1457       goto done;
1458     }
1459 
1460     if ((marker >> 8) != 0xff) {
1461       GST_ERROR_OBJECT (self, "Lost synchronization (0x%04x)", marker);
1462       ret = GST_FLOW_ERROR;
1463       goto done;
1464     }
1465 
1466     /* Now skip the marker */
1467     gst_byte_reader_skip_unchecked (reader, 2);
1468 
1469     /* All markers here have a length */
1470     if (!gst_byte_reader_get_uint16_be (reader, &length)) {
1471       GST_ERROR_OBJECT (self, "Could not read marker length");
1472       ret = GST_FLOW_ERROR;
1473       goto done;
1474     }
1475 
1476     if (length < 2 || gst_byte_reader_get_remaining (reader) < length - 2) {
1477       GST_ERROR_OBJECT (self, "Invalid marker length %u (available %u)",
1478           length, gst_byte_reader_get_remaining (reader));
1479       ret = GST_FLOW_ERROR;
1480       goto done;
1481     }
1482 
1483     GST_LOG_OBJECT (self, "Marker 0x%04x at offset %u with length %u", marker,
1484         gst_byte_reader_get_pos (reader), length);
1485 
1486     switch (marker) {
1487       case MARKER_SIZ:
1488 
1489         if (header->siz.n_components != 0) {
1490           GST_ERROR_OBJECT (self, "Multiple SIZ marker");
1491           ret = GST_FLOW_ERROR;
1492           goto done;
1493         }
1494         ret = parse_siz (self, reader, &header->siz, length);
1495         if (ret != GST_FLOW_OK)
1496           goto done;
1497         break;
1498       case MARKER_COD:
1499         if (header->siz.n_components == 0) {
1500           GST_ERROR_OBJECT (self, "Require SIZ before COD");
1501           ret = GST_FLOW_ERROR;
1502           goto done;
1503         }
1504 
1505         if (header->cod.n_layers != 0) {
1506           GST_ERROR_OBJECT (self, "Multiple COD");
1507           ret = GST_FLOW_ERROR;
1508           goto done;
1509         }
1510 
1511         ret = parse_cod (self, reader, &header->cod, length);
1512         if (ret != GST_FLOW_OK)
1513           goto done;
1514 
1515         break;
1516       case MARKER_POC:
1517         GST_ERROR_OBJECT (self, "POC marker not supported yet");
1518         ret = GST_FLOW_ERROR;
1519         goto done;
1520       case MARKER_COC:
1521         GST_ERROR_OBJECT (self, "COC marker not supported yet");
1522         ret = GST_FLOW_ERROR;
1523         goto done;
1524       case MARKER_RGN:
1525         GST_ERROR_OBJECT (self, "RGN marker not supported yet");
1526         ret = GST_FLOW_ERROR;
1527         goto done;
1528       case MARKER_TLM:
1529         GST_ERROR_OBJECT (self, "TLM marker not supported yet");
1530         ret = GST_FLOW_ERROR;
1531         goto done;
1532       case MARKER_PLM:
1533         GST_ERROR_OBJECT (self, "PLM marker not supported yet");
1534         ret = GST_FLOW_ERROR;
1535         goto done;
1536       case MARKER_PPM:
1537         GST_ERROR_OBJECT (self, "PPM marker not supported yet");
1538         ret = GST_FLOW_ERROR;
1539         goto done;
1540       case MARKER_QCD:
1541         if (header->qcd.data != NULL) {
1542           GST_ERROR_OBJECT (self, "Multiple QCD markers");
1543           ret = GST_FLOW_ERROR;
1544           goto done;
1545         }
1546         header->qcd.data = gst_byte_reader_peek_data_unchecked (reader);
1547         header->qcd.length = length - 2;
1548         gst_byte_reader_skip_unchecked (reader, length - 2);
1549         break;
1550       case MARKER_QCC:{
1551         Buffer *p = g_slice_new (Buffer);
1552         p->data = gst_byte_reader_peek_data_unchecked (reader);
1553         p->length = length - 2;
1554         header->qcc = g_list_append (header->qcc, p);
1555         gst_byte_reader_skip_unchecked (reader, length - 2);
1556         break;
1557       }
1558       case MARKER_COM:{
1559         Buffer *p = g_slice_new (Buffer);
1560         p->data = gst_byte_reader_peek_data_unchecked (reader);
1561         p->length = length - 2;
1562         header->com = g_list_append (header->com, p);
1563         gst_byte_reader_skip_unchecked (reader, length - 2);
1564         break;
1565       }
1566       case MARKER_CRG:{
1567         Buffer *p = g_slice_new (Buffer);
1568         p->data = gst_byte_reader_peek_data_unchecked (reader);
1569         p->length = length - 2;
1570         header->crg = g_list_append (header->crg, p);
1571         gst_byte_reader_skip_unchecked (reader, length - 2);
1572         break;
1573       }
1574       default:
1575         GST_DEBUG_OBJECT (self, "Skipping unknown marker 0x%04x", marker);
1576         gst_byte_reader_skip_unchecked (reader, length - 2);
1577         break;
1578     }
1579   }
1580 
1581   if (header->siz.n_components == 0 || header->cod.n_layers == 0) {
1582     GST_ERROR_OBJECT (self, "No SIZ or COD before SOT");
1583     return GST_FLOW_ERROR;
1584   }
1585 
1586   header->n_tiles_x =
1587       (header->siz.x - header->siz.xto + header->siz.xt - 1) / header->siz.xt;
1588   header->n_tiles_y =
1589       (header->siz.y - header->siz.yto + header->siz.yt - 1) / header->siz.yt;
1590   header->n_tiles = header->n_tiles_x * header->n_tiles_y;
1591 
1592   header->tiles = g_slice_alloc0 (sizeof (Tile) * header->n_tiles);
1593 
1594   /* now at SOT marker, read the tiles */
1595   {
1596     gint i;
1597 
1598     for (i = 0; i < header->n_tiles; i++) {
1599       ret = parse_tile (self, reader, header, &header->tiles[i]);
1600       if (ret != GST_FLOW_OK)
1601         goto done;
1602     }
1603   }
1604 
1605   /* now there must be the EOC marker */
1606   if (!gst_byte_reader_get_uint16_be (reader, &marker)
1607       || marker != MARKER_EOC) {
1608     GST_ERROR_OBJECT (self, "Frame does not end with EOC");
1609     ret = GST_FLOW_ERROR;
1610     goto done;
1611   }
1612 
1613 done:
1614 
1615   return ret;
1616 }
1617 
1618 guint
sizeof_main_header(GstJP2kDecimator * self,const MainHeader * header)1619 sizeof_main_header (GstJP2kDecimator * self, const MainHeader * header)
1620 {
1621   guint size = 2;
1622   GList *l;
1623   gint i;
1624 
1625   size += sizeof_siz (self, &header->siz);
1626   size += sizeof_cod (self, &header->cod);
1627   size += 2 + 2 + header->qcd.length;
1628 
1629   for (l = header->qcc; l; l = l->next) {
1630     Buffer *b = l->data;
1631     size += 2 + 2 + b->length;
1632   }
1633 
1634   for (l = header->crg; l; l = l->next) {
1635     Buffer *b = l->data;
1636     size += 2 + 2 + b->length;
1637   }
1638 
1639   for (l = header->com; l; l = l->next) {
1640     Buffer *b = l->data;
1641     size += 2 + 2 + b->length;
1642   }
1643 
1644   for (i = 0; i < header->n_tiles; i++) {
1645     size += sizeof_tile (self, &header->tiles[i]);
1646   }
1647 
1648   /* EOC */
1649   size += 2;
1650 
1651   return size;
1652 }
1653 
1654 void
reset_main_header(GstJP2kDecimator * self,MainHeader * header)1655 reset_main_header (GstJP2kDecimator * self, MainHeader * header)
1656 {
1657   gint i;
1658   GList *l;
1659 
1660   if (header->tiles) {
1661     for (i = 0; i < header->n_tiles; i++) {
1662       reset_tile (self, header, &header->tiles[i]);
1663     }
1664     g_slice_free1 (sizeof (Tile) * header->n_tiles, header->tiles);
1665   }
1666 
1667   for (l = header->qcc; l; l = l->next)
1668     g_slice_free (Buffer, l->data);
1669   g_list_free (header->qcc);
1670 
1671   for (l = header->com; l; l = l->next)
1672     g_slice_free (Buffer, l->data);
1673   g_list_free (header->com);
1674 
1675   for (l = header->crg; l; l = l->next)
1676     g_slice_free (Buffer, l->data);
1677   g_list_free (header->crg);
1678 
1679   reset_cod (self, &header->cod);
1680   reset_siz (self, &header->siz);
1681 
1682   memset (header, 0, sizeof (MainHeader));
1683 }
1684 
1685 GstFlowReturn
write_main_header(GstJP2kDecimator * self,GstByteWriter * writer,const MainHeader * header)1686 write_main_header (GstJP2kDecimator * self, GstByteWriter * writer,
1687     const MainHeader * header)
1688 {
1689   GstFlowReturn ret = GST_FLOW_OK;
1690   GList *l;
1691   gint i;
1692 
1693   if (!gst_byte_writer_ensure_free_space (writer, 2)) {
1694     GST_ERROR_OBJECT (self, "Could not ensure free space");
1695     return GST_FLOW_ERROR;
1696   }
1697 
1698   gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_SOC);
1699 
1700   ret = write_siz (self, writer, &header->siz);
1701   if (ret != GST_FLOW_OK)
1702     goto done;
1703 
1704   ret = write_cod (self, writer, &header->cod);
1705   if (ret != GST_FLOW_OK)
1706     goto done;
1707 
1708   ret = write_marker_buffer (self, writer, MARKER_QCD, &header->qcd);
1709   if (ret != GST_FLOW_OK)
1710     goto done;
1711 
1712   for (l = header->qcc; l; l = l->next) {
1713     Buffer *p = l->data;
1714 
1715     ret = write_marker_buffer (self, writer, MARKER_QCC, p);
1716     if (ret != GST_FLOW_OK)
1717       goto done;
1718   }
1719 
1720   for (l = header->crg; l; l = l->next) {
1721     Buffer *p = l->data;
1722 
1723     ret = write_marker_buffer (self, writer, MARKER_CRG, p);
1724     if (ret != GST_FLOW_OK)
1725       goto done;
1726   }
1727 
1728   for (l = header->com; l; l = l->next) {
1729     Buffer *p = l->data;
1730 
1731     ret = write_marker_buffer (self, writer, MARKER_COM, p);
1732     if (ret != GST_FLOW_OK)
1733       goto done;
1734   }
1735 
1736   for (i = 0; i < header->n_tiles; i++) {
1737     ret = write_tile (self, writer, header, &header->tiles[i]);
1738     if (ret != GST_FLOW_OK)
1739       goto done;
1740   }
1741 
1742   if (!gst_byte_writer_ensure_free_space (writer, 2)) {
1743     GST_ERROR_OBJECT (self, "Could not ensure free space");
1744     ret = GST_FLOW_ERROR;
1745     goto done;
1746   }
1747   gst_byte_writer_put_uint16_be_unchecked (writer, MARKER_EOC);
1748 
1749 done:
1750   return ret;
1751 }
1752 
1753 GstFlowReturn
decimate_main_header(GstJP2kDecimator * self,MainHeader * header)1754 decimate_main_header (GstJP2kDecimator * self, MainHeader * header)
1755 {
1756   GstFlowReturn ret = GST_FLOW_OK;
1757   gint i;
1758 
1759   for (i = 0; i < header->n_tiles; i++) {
1760     Tile *tile = &header->tiles[i];
1761     GList *l;
1762     PacketIterator it;
1763     PacketLengthTilePart *plt = NULL;
1764 
1765     if (tile->plt) {
1766       if (g_list_length (tile->plt) > 1) {
1767         GST_ERROR_OBJECT (self, "Multiple PLT per tile not supported yet");
1768         ret = GST_FLOW_ERROR;
1769         goto done;
1770       }
1771       plt = g_slice_new (PacketLengthTilePart);
1772       plt->index = 0;
1773       plt->packet_lengths = g_array_new (FALSE, FALSE, sizeof (guint32));
1774     }
1775 
1776     init_packet_iterator (self, &it, header, tile);
1777 
1778     l = tile->packets;
1779     while ((it.next (&it))) {
1780       Packet *p;
1781 
1782       if (l == NULL) {
1783         GST_ERROR_OBJECT (self, "Not enough packets");
1784         ret = GST_FLOW_ERROR;
1785         g_array_free (plt->packet_lengths, TRUE);
1786         g_slice_free (PacketLengthTilePart, plt);
1787         goto done;
1788       }
1789 
1790       p = l->data;
1791 
1792       if ((self->max_layers != 0 && it.cur_layer >= self->max_layers) ||
1793           (self->max_decomposition_levels != -1
1794               && it.cur_resolution > self->max_decomposition_levels)) {
1795         p->data = NULL;
1796         p->length = 1;
1797       }
1798 
1799       if (plt) {
1800         guint32 len = sizeof_packet (self, p);
1801         g_array_append_val (plt->packet_lengths, len);
1802       }
1803 
1804       l = l->next;
1805     }
1806 
1807     if (plt) {
1808       reset_plt (self, tile->plt->data);
1809       g_slice_free (PacketLengthTilePart, tile->plt->data);
1810       tile->plt->data = plt;
1811     }
1812 
1813     tile->sot.tile_part_size = sizeof_tile (self, tile);
1814   }
1815 
1816 done:
1817   return ret;
1818 }
1819