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