1 /*
2 * Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
3 * Copyright (c) 2002-2007, Professor Benoit Macq
4 * Copyright (c) 2003-2007, Francois-Olivier Devaux
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "opj_includes.h"
30 #include "mj2.h"
31
32 /** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
33 /*@{*/
34
35 /** @name Local static functions */
36 /*@{*/
37
38 /*
39 *
40 * Read box headers
41 *
42 */
43
mj2_read_boxhdr(mj2_box_t * box,opj_cio_t * cio)44 int mj2_read_boxhdr(mj2_box_t * box, opj_cio_t *cio)
45 {
46 box->init_pos = cio_tell(cio);
47 box->length = cio_read(cio, 4);
48 box->type = cio_read(cio, 4);
49 if (box->length == 1) {
50 if (cio_read(cio, 4) != 0) {
51 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Cannot handle box sizes higher than 2^32\n");
52 return 1;
53 };
54 box->length = cio_read(cio, 4);
55 if (box->length == 0)
56 box->length = cio_numbytesleft(cio) + 12;
57 }
58 else if (box->length == 0) {
59 box->length = cio_numbytesleft(cio) + 8;
60 }
61 return 0;
62 }
63
64 /*
65 *
66 * Initialisation of a Standard Movie, given a simple movie structure defined by the user
67 * The movie will have one sample per chunk
68 *
69 * Arguments: opj_mj2_t * movie
70 * Several variables of "movie" must be defined in order to enable a correct execution of
71 * this function:
72 * - The number of tracks of each type (movie->num_vtk, movie->num_stk, movie->num_htk)
73 * - The memory for each must be allocated (movie->tk)
74 * - For each track:
75 * The track type (tk->track_type)
76 * The number of sample (tk->num_samples)
77 * The sample rate (tk->sample_rate)
78 *
79 */
80
mj2_init_stdmovie(opj_mj2_t * movie)81 int mj2_init_stdmovie(opj_mj2_t * movie)
82 {
83 mj2_tk_t *tk0;
84 int i, w, h, prec;
85 unsigned int j;
86 time_t ltime;
87
88 movie->brand = MJ2_MJ2;
89 movie->minversion = 0;
90 movie->num_cl = 2;
91 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
92
93 movie->cl[0] = MJ2_MJ2;
94 movie->cl[1] = MJ2_MJ2S;
95 time(<ime); /* Time since 1/1/70 */
96 movie->creation_time = (unsigned int) ltime + 2082844800; /* Seconds between 1/1/04 and 1/1/70 */
97 movie->timescale = 1000;
98
99 movie->rate = 1 << 16; /* Rate to play presentation (default = 0x00010000) */
100 movie->volume = 1 << 8; /* Movie volume (default = 0x0100) */
101 movie->trans_matrix[0] = 0x00010000; /* Transformation matrix for video */
102 movie->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
103 movie->trans_matrix[2] = 0;
104 movie->trans_matrix[3] = 0;
105 movie->trans_matrix[4] = 0x00010000;
106 movie->trans_matrix[5] = 0;
107 movie->trans_matrix[6] = 0;
108 movie->trans_matrix[7] = 0;
109 movie->trans_matrix[8] = 0x40000000;
110 movie->next_tk_id = 1;
111
112 tk0 = &movie->tk[0];
113 w = tk0->w; h = tk0->h; prec = tk0->depth;
114
115 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++)
116 {
117 mj2_tk_t *tk = &movie->tk[i];
118
119 movie->next_tk_id++;
120 tk->jp2_struct.comps = NULL;
121 tk->jp2_struct.cl = NULL;
122
123 if (tk->track_type == 0) /* no sound or hint track */
124 {
125 if (tk->num_samples == 0)
126 return 1;
127
128 tk->w = w; tk->h = h; tk->depth = prec;
129 tk->Dim[0] = 0;
130 tk->Dim[1] = 0;
131
132 tk->timescale = 1000; /* Timescale = 1 ms */
133
134 tk->chunk[0].num_samples = 1;
135 tk->chunk[0].sample_descr_idx = 1;
136
137 tk->same_sample_size = 0;
138
139 tk->num_samplestochunk = 1; /* One sample per chunk */
140 tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
141 tk->sampletochunk[0].first_chunk = 1;
142 tk->sampletochunk[0].samples_per_chunk = 1;
143 tk->sampletochunk[0].sample_descr_idx = 1;
144
145 if (tk->sample_rate == 0)
146 {
147 opj_event_msg(tk->cinfo, EVT_ERROR,
148 "Error while initializing MJ2 movie: Sample rate of track"
149 " %d must be different from zero\n", tk->track_ID);
150 return 1;
151 }
152
153 for (j = 0; j < tk->num_samples; j++)
154 {
155 tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
156 }
157
158 tk->num_tts = 1;
159 tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
160 tk->tts[0].sample_count = tk->num_samples;
161 tk->tts[0].sample_delta = tk->timescale / tk->sample_rate;
162
163 tk->horizresolution = 0x00480000; /* Horizontal resolution (typically 72) */
164 tk->vertresolution = 0x00480000; /* Vertical resolution (typically 72) */
165 tk->compressorname[0] = 0x0f4d6f74; /* Compressor Name[]: Motion JPEG2000 */
166 tk->compressorname[1] = 0x696f6e20;
167 tk->compressorname[2] = 0x4a504547;
168 tk->compressorname[3] = 0x32303030;
169 tk->compressorname[4] = 0x00120000;
170 tk->compressorname[5] = 0;
171 tk->compressorname[6] = 0x00000042;
172 tk->compressorname[7] = 0x000000DC;
173 tk->num_url = 0; /* Number of URL */
174 tk->num_urn = 0; /* Number of URN */
175 tk->graphicsmode = 0; /* Graphicsmode */
176 tk->opcolor[0] = 0; /* OpColor */
177 tk->opcolor[1] = 0; /* OpColor */
178 tk->opcolor[2] = 0; /* OpColor */
179 tk->creation_time = movie->creation_time; /* Seconds between 1/1/04 and 1/1/70 */
180 tk->language = 0; /* Language (undefined) */
181 tk->layer = 0;
182 tk->volume = 1 << 8; /* Movie volume (default = 0x0100) */
183 tk->trans_matrix[0] = 0x00010000; /* Transformation matrix for track */
184 tk->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
185 tk->trans_matrix[2] = 0;
186 tk->trans_matrix[3] = 0;
187 tk->trans_matrix[4] = 0x00010000;
188 tk->trans_matrix[5] = 0;
189 tk->trans_matrix[6] = 0;
190 tk->trans_matrix[7] = 0;
191 tk->trans_matrix[8] = 0x40000000;
192 tk->fieldcount = 1;
193 tk->fieldorder = 0;
194 tk->or_fieldcount = 1;
195 tk->or_fieldorder = 0;
196 tk->num_br = 2;
197 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
198 tk->br[0] = MJ2_JP2;
199 tk->br[1] = MJ2_J2P0;
200 tk->num_jp2x = 0;
201 tk->hsub = 2; /* 4:2:0 */
202 tk->vsub = 2; /* 4:2:0 */
203 tk->hoff = 0;
204 tk->voff = 0;
205 tk->visual_w = tk->w << 16;
206 tk->visual_h = tk->h << 16;
207 }
208 else {
209 tk->num_br = 0;
210 tk->jp2xdata = NULL;
211 }
212 }
213 return 0;
214 }
215
216 /*
217 * Time To Sample box Decompact
218 *
219 */
mj2_tts_decompact(mj2_tk_t * tk)220 void mj2_tts_decompact(mj2_tk_t * tk)
221 {
222 int i, j;
223 tk->num_samples = 0;
224 for (i = 0; i < tk->num_tts; i++) {
225 tk->num_samples += tk->tts[i].sample_count;
226 }
227
228 tk->sample = (mj2_sample_t*) opj_malloc(tk->num_samples * sizeof(mj2_sample_t));
229
230 for (i = 0; i < tk->num_tts; i++) {
231 for (j = 0; j < tk->tts[i].sample_count; j++) {
232 tk->sample[j].sample_delta = tk->tts[i].sample_delta;
233 }
234 }
235 }
236
237 /*
238 * Sample To Chunk box Decompact
239 *
240 */
mj2_stsc_decompact(mj2_tk_t * tk)241 void mj2_stsc_decompact(mj2_tk_t * tk)
242 {
243 unsigned int i, j, k, sampleno = 0;
244
245 if (tk->num_samplestochunk == 1) {
246 tk->num_chunks =
247 (unsigned int) ceil((double) tk->num_samples /
248 (double) tk->sampletochunk[0].samples_per_chunk);
249 tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_chunks * sizeof(mj2_chunk_t));
250 for (k = 0; k < tk->num_chunks; k++) {
251 tk->chunk[k].num_samples = tk->sampletochunk[0].samples_per_chunk;
252 }
253
254 } else {
255 tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_samples * sizeof(mj2_chunk_t));
256 tk->num_chunks = 0;
257 for (i = 0; i < tk->num_samplestochunk -1 ; i++) {
258 for (j = tk->sampletochunk[i].first_chunk - 1;
259 j < tk->sampletochunk[i + 1].first_chunk - 1; j++) {
260 tk->chunk[j].num_samples = tk->sampletochunk[i].samples_per_chunk;
261 tk->num_chunks++;
262 sampleno += tk->chunk[j].num_samples;
263 }
264 }
265 tk->num_chunks += (int)(tk->num_samples - sampleno) / tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
266 for (k = tk->sampletochunk[tk->num_samplestochunk - 1].first_chunk - 1;
267 k < tk->num_chunks; k++) {
268 tk->chunk[k].num_samples =
269 tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
270 }
271 tk->chunk = (mj2_chunk_t*)
272 opj_realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
273 }
274
275 }
276
277
278 /*
279 * Chunk offset box Decompact
280 *
281 */
mj2_stco_decompact(mj2_tk_t * tk)282 void mj2_stco_decompact(mj2_tk_t * tk)
283 {
284 unsigned int i, j, k = 0;
285 unsigned int intra_chunk_offset;
286
287 for (i = 0; i < tk->num_chunks; i++) {
288 intra_chunk_offset = 0;
289 for (j = 0; j < tk->chunk[i].num_samples; j++) {
290 tk->sample[k].offset = intra_chunk_offset + tk->chunk[i].offset;
291 intra_chunk_offset += tk->sample[k].sample_size;
292 k++;
293 }
294 }
295 }
296
297 /*
298 * Write the JP box
299 *
300 * JP Signature box
301 *
302 */
mj2_write_jp(opj_cio_t * cio)303 void mj2_write_jp(opj_cio_t *cio)
304 {
305 mj2_box_t box;
306 box.init_pos = cio_tell(cio);
307 cio_skip(cio,4);
308
309 cio_write(cio, MJ2_JP, 4); /* JP */
310 cio_write(cio, 0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
311
312 box.length = cio_tell(cio) - box.init_pos;
313 cio_seek(cio, box.init_pos);
314 cio_write(cio, box.length, 4);
315 cio_seek(cio, box.init_pos + box.length);
316 }
317
318 /*
319 * Read the JP box
320 *
321 * JPEG 2000 signature
322 *
323 */
mj2_read_jp(opj_cio_t * cio)324 int mj2_read_jp(opj_cio_t *cio)
325 {
326 mj2_box_t box;
327
328 mj2_read_boxhdr(&box, cio);
329 if (MJ2_JP != box.type) { /* Check Marker */
330 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP Marker\n");
331 return 1;
332 }
333 if (0x0d0a870a != cio_read(cio, 4)) { /* read the 0x0d0a870a required in a JP box */
334 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Marker\n");
335 return 1;
336 }
337 if (cio_tell(cio) - box.init_pos != box.length) { /* Check box length */
338 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Box size \n");
339 return 1;
340 }
341 return 0;
342
343 }
344
345 /*
346 * Write the FTYP box
347 *
348 * File type box
349 *
350 */
mj2_write_ftyp(opj_mj2_t * movie,opj_cio_t * cio)351 void mj2_write_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
352 {
353 int i;
354 mj2_box_t box;
355 box.init_pos = cio_tell(cio);
356 cio_skip(cio,4);
357
358 cio_write(cio, MJ2_FTYP, 4); /* FTYP */
359 cio_write(cio, movie->brand, 4); /* BR */
360 cio_write(cio, movie->minversion, 4); /* MinV */
361
362 for (i = 0; i < movie->num_cl; i++)
363 cio_write(cio, movie->cl[i], 4); /* CL */
364
365 box.length = cio_tell(cio) - box.init_pos;
366 cio_seek(cio, box.init_pos);
367 cio_write(cio, box.length, 4); /* Length */
368 cio_seek(cio, box.init_pos + box.length);
369 }
370
371 /*
372 * Read the FTYP box
373 *
374 * File type box
375 *
376 */
mj2_read_ftyp(opj_mj2_t * movie,opj_cio_t * cio)377 int mj2_read_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
378 {
379 int i;
380 mj2_box_t box;
381
382 mj2_read_boxhdr(&box, cio); /* Box Size */
383 if (MJ2_FTYP != box.type) {
384 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FTYP Marker\n");
385 return 1;
386 }
387
388 movie->brand = cio_read(cio, 4); /* BR */
389 movie->minversion = cio_read(cio, 4); /* MinV */
390 movie->num_cl = (box.length - 16) / 4;
391 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
392
393 for (i = movie->num_cl - 1; i > -1; i--)
394 movie->cl[i] = cio_read(cio, 4); /* CLi */
395
396 if (cio_tell(cio) - box.init_pos != box.length) {
397 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FTYP Box\n");
398 return 1;
399 }
400 return 0;
401 }
402
403
404 /*
405 * Write the STCO box
406 *
407 * Chunk Offset Box
408 *
409 */
mj2_write_stco(mj2_tk_t * tk,opj_cio_t * cio)410 void mj2_write_stco(mj2_tk_t * tk, opj_cio_t *cio)
411 {
412 mj2_box_t box;
413 unsigned int i;
414
415 box.init_pos = cio_tell(cio);
416 cio_skip(cio,4);
417 cio_write(cio, MJ2_STCO, 4); /* STCO */
418
419 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
420
421 cio_write(cio, tk->num_chunks, 4); /* Entry Count */
422
423 for (i = 0; i < tk->num_chunks; i++) {
424 cio_write(cio, tk->chunk[i].offset, 4); /* Entry offset */
425 }
426
427 box.length = cio_tell(cio) - box.init_pos;
428 cio_seek(cio, box.init_pos);
429 cio_write(cio, box.length, 4); /* L */
430 cio_seek(cio, box.init_pos + box.length);
431 }
432
433 /*
434 * Read the STCO box
435 *
436 * Chunk Offset Box
437 *
438 */
mj2_read_stco(mj2_tk_t * tk,opj_cio_t * cio)439 int mj2_read_stco(mj2_tk_t * tk, opj_cio_t *cio)
440 {
441 unsigned int i;
442 mj2_box_t box;
443
444 mj2_read_boxhdr(&box, cio); /* Box Size */
445 if (MJ2_STCO != box.type) {
446 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STCO Marker\n");
447 return 1;
448 }
449
450 if (0 != cio_read(cio, 1)) { /* Version = 0 */
451 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STCO box\n");
452 return 1;
453 }
454
455 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
456 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STCO box. Expected flag 0\n");
457 return 1;
458 }
459
460
461 if (cio_read(cio, 4) != tk->num_chunks) {
462 opj_event_msg(cio->cinfo, EVT_ERROR,
463 "Error in STCO box: expecting same amount of entry-count as chunks \n");
464 } else {
465 for (i = 0; i < tk->num_chunks; i++) {
466 tk->chunk[i].offset = cio_read(cio, 4); /* Entry offset */
467 }
468 }
469
470 mj2_stco_decompact(tk);
471
472
473 if (cio_tell(cio) - box.init_pos != box.length) {
474 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STCO Box size\n");
475 return 1;
476 }
477 return 0;
478 }
479
480 /*
481 * Write the STSZ box
482 *
483 * Sample size box
484 *
485 */
mj2_write_stsz(mj2_tk_t * tk,opj_cio_t * cio)486 void mj2_write_stsz(mj2_tk_t * tk, opj_cio_t *cio)
487 {
488 mj2_box_t box;
489 unsigned int i;
490
491 box.init_pos = cio_tell(cio);
492 cio_skip(cio,4);
493 cio_write(cio, MJ2_STSZ, 4); /* STSZ */
494
495 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
496
497 if (tk->same_sample_size == 1) { /* If they all have the same size */
498 cio_write(cio, tk->sample[0].sample_size, 4); /* Size */
499
500 cio_write(cio, 1, 4); /* Entry count = 1 */
501 }
502
503 else {
504 cio_write(cio, 0, 4); /* Sample Size = 0 becase they all have different sizes */
505
506 cio_write(cio, tk->num_samples, 4); /* Sample Count */
507
508 for (i = 0; i < tk->num_samples; i++) {
509 cio_write(cio, tk->sample[i].sample_size, 4);
510 }
511 }
512
513 box.length = cio_tell(cio) - box.init_pos;
514 cio_seek(cio, box.init_pos);
515 cio_write(cio, box.length, 4); /* L */
516 cio_seek(cio, box.init_pos + box.length);
517 }
518
519 /*
520 * Read the STSZ box
521 *
522 * Sample size box
523 *
524 */
mj2_read_stsz(mj2_tk_t * tk,opj_cio_t * cio)525 int mj2_read_stsz(mj2_tk_t * tk, opj_cio_t *cio)
526 {
527 int sample_size;
528 unsigned int i;
529 mj2_box_t box;
530
531 mj2_read_boxhdr(&box, cio); /* Box Size */
532 if (MJ2_STSZ != box.type) {
533 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSZ Marker\n");
534 return 1;
535 }
536
537
538 if (0 != cio_read(cio, 1)) { /* Version = 0 */
539 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSZ box\n");
540 return 1;
541 }
542
543 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
544 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSZ box. Expected flag 0\n");
545 return 1;
546 }
547
548 sample_size = cio_read(cio, 4);
549
550 if (sample_size != 0) { /* Samples do have the same size */
551 tk->same_sample_size = 1;
552 for (i = 0; i < tk->num_samples; i++) {
553 tk->sample[i].sample_size = sample_size;
554 }
555 cio_skip(cio,4); /* Sample count = 1 */
556 } else {
557 tk->same_sample_size = 0;
558 if (tk->num_samples != cio_read(cio, 4)) { /* Sample count */
559 opj_event_msg(cio->cinfo, EVT_ERROR,
560 "Error in STSZ box. Expected that sample-count is number of samples in track\n");
561 return 1;
562 }
563 for (i = 0; i < tk->num_samples; i++) {
564 tk->sample[i].sample_size = cio_read(cio, 4); /* Sample Size */
565 }
566
567 if (cio_tell(cio) - box.init_pos != box.length) {
568 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSZ Box size\n");
569 return 1;
570 }
571 }
572 return 0;
573
574 }
575
576 /*
577 * Write the STSC box
578 *
579 * Sample to Chunk
580 *
581 */
mj2_write_stsc(mj2_tk_t * tk,opj_cio_t * cio)582 void mj2_write_stsc(mj2_tk_t * tk, opj_cio_t *cio)
583 {
584 unsigned int i;
585 mj2_box_t box;
586
587 box.init_pos = cio_tell(cio);
588 cio_skip(cio,4);
589 cio_write(cio, MJ2_STSC, 4); /* STSC */
590
591 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
592
593 cio_write(cio, tk->num_samplestochunk, 4); /* Entry Count */
594
595 for (i = 0; i < tk->num_samplestochunk; i++) {
596 cio_write(cio, tk->sampletochunk[i].first_chunk, 4); /* First Chunk */
597 cio_write(cio, tk->sampletochunk[i].samples_per_chunk, 4); /* Samples per chunk */
598 cio_write(cio, tk->sampletochunk[i].sample_descr_idx, 4); /* Samples description index */
599 }
600
601
602 box.length = cio_tell(cio) - box.init_pos;
603 cio_seek(cio, box.init_pos);
604 cio_write(cio, box.length, 4); /* L */
605 cio_seek(cio, box.init_pos + box.length);
606 }
607
608 /*
609 * Read the STSC box
610 *
611 * Sample to Chunk
612 *
613 */
mj2_read_stsc(mj2_tk_t * tk,opj_cio_t * cio)614 int mj2_read_stsc(mj2_tk_t * tk, opj_cio_t *cio)
615 {
616 unsigned int i;
617 mj2_box_t box;
618
619 mj2_read_boxhdr(&box, cio); /* Box Size */
620 if (MJ2_STSC != box.type) {
621 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSC Marker\n");
622 return 1;
623 }
624
625
626 if (0 != cio_read(cio, 1)) { /* Version = 0 */
627 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSC box\n");
628 return 1;
629 }
630
631 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
632 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSC box. Expected flag 0\n");
633 return 1;
634 }
635
636 tk->num_samplestochunk = cio_read(cio, 4);
637
638 tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
639
640 for (i = 0; i < tk->num_samplestochunk; i++) {
641 tk->sampletochunk[i].first_chunk = cio_read(cio, 4);
642 tk->sampletochunk[i].samples_per_chunk = cio_read(cio, 4);
643 tk->sampletochunk[i].sample_descr_idx = cio_read(cio, 4);
644 }
645
646 mj2_stsc_decompact(tk); /* decompact sample to chunk box */
647
648
649 if (cio_tell(cio) - box.init_pos != box.length) {
650 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSC Box size\n");
651 return 1;
652 }
653 return 0;
654 }
655
656 /*
657 * Write the STTS box
658 *
659 * Time to Sample Box
660 *
661 */
mj2_write_stts(mj2_tk_t * tk,opj_cio_t * cio)662 void mj2_write_stts(mj2_tk_t * tk, opj_cio_t *cio)
663 {
664
665 int i;
666 mj2_box_t box;
667
668 box.init_pos = cio_tell(cio);
669 cio_skip(cio,4);
670 cio_write(cio, MJ2_STTS, 4); /* STTS */
671
672 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
673
674 cio_write(cio, tk->num_tts, 4); /* entry_count */
675 for (i = 0; i < tk->num_tts; i++) {
676 cio_write(cio, tk->tts[i].sample_count, 4); /* Sample-count */
677 cio_write(cio, tk->tts[i].sample_delta, 4); /* Sample-Delta */
678 }
679
680 box.length = cio_tell(cio) - box.init_pos;
681 cio_seek(cio, box.init_pos);
682 cio_write(cio, box.length, 4); /* L */
683 cio_seek(cio, box.init_pos + box.length);
684 }
685
686 /*
687 * Read the STTS box
688 *
689 *
690 *
691 */
mj2_read_stts(mj2_tk_t * tk,opj_cio_t * cio)692 int mj2_read_stts(mj2_tk_t * tk, opj_cio_t *cio)
693 {
694 int i;
695
696 mj2_box_t box;
697
698 mj2_read_boxhdr(&box, cio);
699 if (MJ2_STTS != box.type) {
700 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STTS Marker\n");
701 return 1;
702 }
703
704
705 if (0 != cio_read(cio, 1)) { /* Version = 0 */
706 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STTS box\n");
707 return 1;
708 }
709
710 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
711 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STTS box. Expected flag 0\n");
712 return 1;
713 }
714
715 tk->num_tts = cio_read(cio, 4);
716
717 tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
718
719 for (i = 0; i < tk->num_tts; i++) {
720 tk->tts[i].sample_count = cio_read(cio, 4);
721 tk->tts[i].sample_delta = cio_read(cio, 4);
722 }
723
724 mj2_tts_decompact(tk);
725
726 if (cio_tell(cio) - box.init_pos != box.length) {
727 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STTS Box size\n");
728 return 1;
729 }
730 return 0;
731 }
732
733 /*
734 * Write the FIEL box
735 *
736 * Field coding Box
737 *
738 */
mj2_write_fiel(mj2_tk_t * tk,opj_cio_t * cio)739 void mj2_write_fiel(mj2_tk_t * tk, opj_cio_t *cio)
740 {
741
742 mj2_box_t box;
743
744 box.init_pos = cio_tell(cio);
745 cio_skip(cio,4);
746 cio_write(cio, MJ2_FIEL, 4); /* STTS */
747
748 cio_write(cio, tk->fieldcount, 1); /* Field count */
749 cio_write(cio, tk->fieldorder, 1); /* Field order */
750
751
752 box.length = cio_tell(cio) - box.init_pos;
753 cio_seek(cio, box.init_pos);
754 cio_write(cio, box.length, 4); /* L */
755 cio_seek(cio, box.init_pos + box.length);
756 }
757
758 /*
759 * Read the FIEL box
760 *
761 * Field coding Box
762 *
763 */
mj2_read_fiel(mj2_tk_t * tk,opj_cio_t * cio)764 int mj2_read_fiel(mj2_tk_t * tk, opj_cio_t *cio)
765 {
766
767 mj2_box_t box;
768
769 mj2_read_boxhdr(&box, cio);
770 if (MJ2_FIEL != box.type) {
771 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FIEL Marker\n");
772 return 1;
773 }
774
775
776 tk->fieldcount = cio_read(cio, 1);
777 tk->fieldorder = cio_read(cio, 1);
778
779 if (cio_tell(cio) - box.init_pos != box.length) {
780 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FIEL Box size\n");
781 return 1;
782 }
783 return 0;
784 }
785
786 /*
787 * Write the ORFO box
788 *
789 * Original Format Box
790 *
791 */
mj2_write_orfo(mj2_tk_t * tk,opj_cio_t * cio)792 void mj2_write_orfo(mj2_tk_t * tk, opj_cio_t *cio)
793 {
794 mj2_box_t box;
795
796 box.init_pos = cio_tell(cio);
797 cio_skip(cio,4);
798 cio_write(cio, MJ2_ORFO, 4);
799
800 cio_write(cio, tk->or_fieldcount, 1); /* Original Field count */
801 cio_write(cio, tk->or_fieldorder, 1); /* Original Field order */
802
803
804 box.length = cio_tell(cio) - box.init_pos;
805 cio_seek(cio, box.init_pos);
806 cio_write(cio, box.length, 4); /* L */
807 cio_seek(cio, box.init_pos + box.length);
808 }
809
810 /*
811 * Read the ORFO box
812 *
813 * Original Format Box
814 *
815 */
mj2_read_orfo(mj2_tk_t * tk,opj_cio_t * cio)816 int mj2_read_orfo(mj2_tk_t * tk, opj_cio_t *cio)
817 {
818
819 mj2_box_t box;
820
821 mj2_read_boxhdr(&box, cio);
822 if (MJ2_ORFO != box.type) {
823 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected ORFO Marker\n");
824 return 1;
825 }
826
827
828 tk->or_fieldcount = cio_read(cio, 1);
829 tk->or_fieldorder = cio_read(cio, 1);
830
831 if (cio_tell(cio) - box.init_pos != box.length) {
832 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with ORFO Box size\n");
833 return 1;
834 }
835 return 0;
836 }
837
838 /*
839 * Write the JP2P box
840 *
841 * MJP2 Profile Box
842 *
843 */
mj2_write_jp2p(mj2_tk_t * tk,opj_cio_t * cio)844 void mj2_write_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
845 {
846
847 int i;
848 mj2_box_t box;
849
850 box.init_pos = cio_tell(cio);
851 cio_skip(cio,4);
852 cio_write(cio, MJ2_JP2P, 4);
853
854 cio_write(cio, 0, 4); /* Version 0, flags =0 */
855
856 for (i = 0; i < tk->num_br; i++) {
857 cio_write(cio, tk->br[i], 4);
858 }
859
860 box.length = cio_tell(cio) - box.init_pos;
861 cio_seek(cio, box.init_pos);
862 cio_write(cio, box.length, 4); /* L */
863 cio_seek(cio, box.init_pos + box.length);
864 }
865
866 /*
867 * Read the JP2P box
868 *
869 * MJP2 Profile Box
870 *
871 */
mj2_read_jp2p(mj2_tk_t * tk,opj_cio_t * cio)872 int mj2_read_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
873 {
874 int i;
875
876 mj2_box_t box;
877
878 mj2_read_boxhdr(&box, cio);
879 if (MJ2_JP2P != box.type) {
880 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2P Marker\n");
881 return 1;
882 }
883
884 if (0 != cio_read(cio, 1)) { /* Version = 0 */
885 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in JP2P box\n");
886 return 1;
887 }
888
889 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
890 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in JP2P box. Expected flag 0\n");
891 return 1;
892 }
893
894
895 tk->num_br = (box.length - 12) / 4;
896 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
897
898 for (i = 0; i < tk->num_br; i++) {
899 tk->br[i] = cio_read(cio, 4);
900 }
901
902 if (cio_tell(cio) - box.init_pos != box.length) {
903 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2P Box size\n");
904 return 1;
905 }
906 return 0;
907 }
908
909 /*
910 * Write the JP2X box
911 *
912 * MJP2 Prefix Box
913 *
914 */
mj2_write_jp2x(mj2_tk_t * tk,opj_cio_t * cio)915 void mj2_write_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
916 {
917
918 int i;
919 mj2_box_t box;
920
921 box.init_pos = cio_tell(cio);
922 cio_skip(cio,4);
923 cio_write(cio, MJ2_JP2X, 4);
924
925 for (i = 0; i < tk->num_jp2x; i++) {
926 cio_write(cio, tk->jp2xdata[i], 1);
927 }
928
929 box.length = cio_tell(cio) - box.init_pos;
930 cio_seek(cio, box.init_pos);
931 cio_write(cio, box.length, 4); /* L */
932 cio_seek(cio, box.init_pos + box.length);
933 }
934
935 /*
936 * Read the JP2X box
937 *
938 * MJP2 Prefix Box
939 *
940 */
mj2_read_jp2x(mj2_tk_t * tk,opj_cio_t * cio)941 int mj2_read_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
942 {
943 unsigned int i;
944
945 mj2_box_t box;
946
947 mj2_read_boxhdr(&box, cio);
948 if (MJ2_JP2X != box.type) {
949 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2X Marker\n");
950 return 1;
951 }
952
953
954 tk->num_jp2x = (box.length - 8);
955 tk->jp2xdata = (unsigned char*) opj_malloc(tk->num_jp2x * sizeof(unsigned char));
956
957 for (i = 0; i < tk->num_jp2x; i++) {
958 tk->jp2xdata[i] = cio_read(cio, 1);
959 }
960
961 if (cio_tell(cio) - box.init_pos != box.length) {
962 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2X Box size\n");
963 return 1;
964 }
965 return 0;
966 }
967
968 /*
969 * Write the JSUB box
970 *
971 * MJP2 Subsampling Box
972 *
973 */
mj2_write_jsub(mj2_tk_t * tk,opj_cio_t * cio)974 void mj2_write_jsub(mj2_tk_t * tk, opj_cio_t *cio)
975 {
976
977 mj2_box_t box;
978
979 box.init_pos = cio_tell(cio);
980 cio_skip(cio,4);
981 cio_write(cio, MJ2_JSUB, 4);
982
983 cio_write(cio, tk->hsub, 1);
984 cio_write(cio, tk->vsub, 1);
985 cio_write(cio, tk->hoff, 1);
986 cio_write(cio, tk->voff, 1);
987
988 box.length = cio_tell(cio) - box.init_pos;
989 cio_seek(cio, box.init_pos);
990 cio_write(cio, box.length, 4); /* L */
991 cio_seek(cio, box.init_pos + box.length);
992 }
993
994 /*
995 * Read the JSUB box
996 *
997 * MJP2 Subsampling Box
998 *
999 */
mj2_read_jsub(mj2_tk_t * tk,opj_cio_t * cio)1000 int mj2_read_jsub(mj2_tk_t * tk, opj_cio_t *cio)
1001 {
1002 mj2_box_t box;
1003
1004 mj2_read_boxhdr(&box, cio);
1005 if (MJ2_JSUB != box.type) {
1006 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JSUB Marker\n");
1007 return 1;
1008 }
1009
1010 tk->hsub = cio_read(cio, 1);
1011 tk->vsub = cio_read(cio, 1);
1012 tk->hoff = cio_read(cio, 1);;
1013 tk->voff = cio_read(cio, 1);
1014
1015 if (cio_tell(cio) - box.init_pos != box.length) {
1016 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JSUB Box size\n");
1017 return 1;
1018 }
1019 return 0;
1020 }
1021
1022 /*
1023 * Write the SMJ2 box
1024 *
1025 * Visual Sample Entry Description
1026 *
1027 */
mj2_write_smj2(mj2_tk_t * tk,opj_cio_t * cio)1028 void mj2_write_smj2(mj2_tk_t * tk, opj_cio_t *cio)
1029 {
1030 mj2_box_t box;
1031
1032 box.init_pos = cio_tell(cio);
1033 cio_skip(cio,4);
1034 cio_write(cio, MJ2_MJ2, 4); /* MJ2 */
1035
1036 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1037
1038 cio_write(cio, 1, 4);
1039
1040 cio_write(cio, 0, 2); /* Pre-defined */
1041
1042 cio_write(cio, 0, 2); /* Reserved */
1043
1044 cio_write(cio, 0, 4); /* Pre-defined */
1045 cio_write(cio, 0, 4); /* Pre-defined */
1046 cio_write(cio, 0, 4); /* Pre-defined */
1047
1048 cio_write(cio, tk->w, 2); /* Width */
1049 cio_write(cio, tk->h, 2); /* Height */
1050
1051 cio_write(cio, tk->horizresolution, 4); /* Horizontal resolution */
1052 cio_write(cio, tk->vertresolution, 4); /* Vertical resolution */
1053
1054 cio_write(cio, 0, 4); /* Reserved */
1055
1056 cio_write(cio, 1, 2); /* Pre-defined = 1 */
1057
1058 cio_write(cio, tk->compressorname[0], 4); /* Compressor Name */
1059 cio_write(cio, tk->compressorname[1], 4);
1060 cio_write(cio, tk->compressorname[2], 4);
1061 cio_write(cio, tk->compressorname[3], 4);
1062 cio_write(cio, tk->compressorname[4], 4);
1063 cio_write(cio, tk->compressorname[5], 4);
1064 cio_write(cio, tk->compressorname[6], 4);
1065 cio_write(cio, tk->compressorname[7], 4);
1066
1067 cio_write(cio, tk->depth, 2); /* Depth */
1068
1069 cio_write(cio, 0xffff, 2); /* Pre-defined = -1 */
1070
1071 jp2_write_jp2h(&tk->jp2_struct, cio);
1072
1073 mj2_write_fiel(tk, cio);
1074
1075 if (tk->num_br != 0)
1076 mj2_write_jp2p(tk, cio);
1077 if (tk->num_jp2x != 0)
1078 mj2_write_jp2x(tk, cio);
1079
1080 mj2_write_jsub(tk, cio);
1081 mj2_write_orfo(tk, cio);
1082
1083 box.length = cio_tell(cio) - box.init_pos;
1084 cio_seek(cio, box.init_pos);
1085 cio_write(cio, box.length, 4); /* L */
1086 cio_seek(cio, box.init_pos + box.length);
1087 }
1088
1089 /*
1090 * Read the SMJ2 box
1091 *
1092 * Visual Sample Entry Description
1093 *
1094 */
mj2_read_smj2(opj_image_t * img,mj2_tk_t * tk,opj_cio_t * cio)1095 int mj2_read_smj2(opj_image_t * img, mj2_tk_t * tk, opj_cio_t *cio)
1096 {
1097 mj2_box_t box;
1098 mj2_box_t box2;
1099 opj_jp2_color_t color;
1100 int i;
1101 opj_bool ok;
1102
1103 mj2_read_boxhdr(&box, cio);
1104
1105 if (MJ2_MJ2 != box.type) {
1106 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n");
1107 return 1;
1108 }
1109
1110 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1111 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MJP2 box\n");
1112 return 1;
1113 }
1114
1115 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1116 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MJP2 box. Expected flag 0\n");
1117 return 1;
1118 }
1119
1120 cio_skip(cio,4);
1121
1122 cio_skip(cio,2); /* Pre-defined */
1123
1124 cio_skip(cio,2); /* Reserved */
1125
1126 cio_skip(cio,4); /* Pre-defined */
1127 cio_skip(cio,4); /* Pre-defined */
1128 cio_skip(cio,4); /* Pre-defined */
1129
1130 tk->w = cio_read(cio, 2); /* Width */
1131 tk->h = cio_read(cio, 2); /* Height */
1132
1133 tk->horizresolution = cio_read(cio, 4); /* Horizontal resolution */
1134 tk->vertresolution = cio_read(cio, 4); /* Vertical resolution */
1135
1136 cio_skip(cio,4); /* Reserved */
1137
1138 cio_skip(cio,2); /* Pre-defined = 1 */
1139
1140 tk->compressorname[0] = cio_read(cio, 4); /* Compressor Name */
1141 tk->compressorname[1] = cio_read(cio, 4);
1142 tk->compressorname[2] = cio_read(cio, 4);
1143 tk->compressorname[3] = cio_read(cio, 4);
1144 tk->compressorname[4] = cio_read(cio, 4);
1145 tk->compressorname[5] = cio_read(cio, 4);
1146 tk->compressorname[6] = cio_read(cio, 4);
1147 tk->compressorname[7] = cio_read(cio, 4);
1148
1149 tk->depth = cio_read(cio, 2); /* Depth */
1150
1151 /* Init std value */
1152 tk->num_jp2x = 0;
1153 tk->fieldcount = 1;
1154 tk->fieldorder = 0;
1155 tk->or_fieldcount = 1;
1156 tk->or_fieldorder = 0;
1157
1158 cio_skip(cio,2); /* Pre-defined = -1 */
1159 memset(&color, 0, sizeof(opj_jp2_color_t));
1160 tk->jp2_struct.cinfo = tk->cinfo;
1161
1162 ok = jp2_read_jp2h(&tk->jp2_struct, cio, &color);
1163
1164 tk->jp2_struct.cinfo = NULL;
1165
1166 if(ok == OPJ_FALSE)
1167 {
1168 opj_event_msg(tk->cinfo, EVT_ERROR, "Error reading JP2H Box\n");
1169 return 1;
1170 }
1171
1172 tk->jp2_struct.comps = (opj_jp2_comps_t*) opj_malloc(tk->jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
1173 tk->jp2_struct.cl = (unsigned int*) opj_malloc(sizeof(unsigned int));
1174
1175 tk->num_br = 0;
1176 tk->num_jp2x = 0;
1177
1178 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
1179 mj2_read_boxhdr(&box2, cio);
1180 cio_seek(cio, box2.init_pos);
1181 switch (box2.type) {
1182 case MJ2_FIEL:
1183 if (mj2_read_fiel(tk, cio))
1184 return 1;
1185 break;
1186
1187 case MJ2_JP2P:
1188 if (mj2_read_jp2p(tk, cio))
1189 return 1;
1190 break;
1191
1192 case MJ2_JP2X:
1193 if (mj2_read_jp2x(tk, cio))
1194 return 1;
1195 break;
1196
1197 case MJ2_JSUB:
1198 if (mj2_read_jsub(tk, cio))
1199 return 1;
1200 break;
1201
1202 case MJ2_ORFO:
1203 if (mj2_read_orfo(tk, cio))
1204 return 1;
1205 break;
1206
1207 default:
1208 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MJP2 Box size\n");
1209 return 1;
1210 break;
1211
1212 }
1213 }
1214 return 0;
1215 }
1216
1217
1218 /*
1219 * Write the STSD box
1220 *
1221 * Sample Description
1222 *
1223 */
mj2_write_stsd(mj2_tk_t * tk,opj_cio_t * cio)1224 void mj2_write_stsd(mj2_tk_t * tk, opj_cio_t *cio)
1225 {
1226 mj2_box_t box;
1227
1228 box.init_pos = cio_tell(cio);
1229 cio_skip(cio,4);
1230 cio_write(cio, MJ2_STSD, 4); /* STSD */
1231
1232 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1233
1234 cio_write(cio, 1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
1235
1236 if (tk->track_type == 0) {
1237 mj2_write_smj2(tk, cio);
1238 } else if (tk->track_type == 1) {
1239 /* Not implemented */
1240 }
1241 if (tk->track_type == 2) {
1242 /* Not implemented */
1243 }
1244
1245
1246 box.length = cio_tell(cio) - box.init_pos;
1247 cio_seek(cio, box.init_pos);
1248 cio_write(cio, box.length, 4); /* L */
1249 cio_seek(cio, box.init_pos + box.length);
1250 }
1251
1252 /*
1253 * Read the STSD box
1254 *
1255 * Sample Description
1256 *
1257 */
mj2_read_stsd(mj2_tk_t * tk,opj_image_t * img,opj_cio_t * cio)1258 int mj2_read_stsd(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1259 {
1260 int i;
1261 int entry_count, len_2skip;
1262
1263 mj2_box_t box;
1264
1265 mj2_read_boxhdr(&box, cio);
1266
1267 if (MJ2_STSD != box.type) {
1268 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSD Marker\n");
1269 return 1;
1270 }
1271
1272 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1273 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSD box\n");
1274 return 1;
1275 }
1276
1277 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1278 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSD box. Expected flag 0\n");
1279 return 1;
1280 }
1281
1282 entry_count = cio_read(cio, 4);
1283
1284 if (tk->track_type == 0) {
1285 for (i = 0; i < entry_count; i++) {
1286 if (mj2_read_smj2(img, tk, cio))
1287 return 1;
1288 }
1289 } else if (tk->track_type == 1) {
1290 len_2skip = cio_read(cio, 4); /* Not implemented -> skipping box */
1291 cio_skip(cio,len_2skip - 4);
1292 } else if (tk->track_type == 2) {
1293 len_2skip = cio_read(cio, 4); /* Not implemented -> skipping box */
1294 cio_skip(cio,len_2skip - 4);
1295 }
1296
1297
1298 if (cio_tell(cio) - box.init_pos != box.length) {
1299 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSD Box size\n");
1300 return 1;
1301 }
1302 return 0;
1303 }
1304
1305 /*
1306 * Write the STBL box
1307 *
1308 * Sample table box box
1309 *
1310 */
mj2_write_stbl(mj2_tk_t * tk,opj_cio_t * cio)1311 void mj2_write_stbl(mj2_tk_t * tk, opj_cio_t *cio)
1312 {
1313 mj2_box_t box;
1314
1315 box.init_pos = cio_tell(cio);
1316 cio_skip(cio,4);
1317 cio_write(cio, MJ2_STBL, 4); /* STBL */
1318
1319 mj2_write_stsd(tk, cio);
1320 mj2_write_stts(tk, cio);
1321 mj2_write_stsc(tk, cio);
1322 mj2_write_stsz(tk, cio);
1323 mj2_write_stco(tk, cio);
1324
1325 box.length = cio_tell(cio) - box.init_pos;
1326 cio_seek(cio, box.init_pos);
1327 cio_write(cio, box.length, 4); /* L */
1328 cio_seek(cio, box.init_pos + box.length);
1329 }
1330
1331 /*
1332 * Read the STBL box
1333 *
1334 * Sample table box box
1335 *
1336 */
mj2_read_stbl(mj2_tk_t * tk,opj_image_t * img,opj_cio_t * cio)1337 int mj2_read_stbl(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1338 {
1339 mj2_box_t box;
1340
1341 mj2_read_boxhdr(&box, cio);
1342 if (MJ2_STBL != box.type) {
1343 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STBL Marker\n");
1344 return 1;
1345 }
1346
1347 if (mj2_read_stsd(tk, img, cio))
1348 return 1;
1349 if (mj2_read_stts(tk, cio))
1350 return 1;
1351 if (mj2_read_stsc(tk, cio))
1352 return 1;
1353 if (mj2_read_stsz(tk, cio))
1354 return 1;
1355 if (mj2_read_stco(tk, cio))
1356 return 1;
1357
1358 if (cio_tell(cio) - box.init_pos != box.length) {
1359 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STBL Box size\n");
1360 return 1;
1361 }
1362 return 0;
1363 }
1364
1365 /*
1366 * Write the URL box
1367 *
1368 * URL box
1369 *
1370 */
mj2_write_url(mj2_tk_t * tk,int url_num,opj_cio_t * cio)1371 void mj2_write_url(mj2_tk_t * tk, int url_num, opj_cio_t *cio)
1372 {
1373 mj2_box_t box;
1374
1375 box.init_pos = cio_tell(cio);
1376 cio_skip(cio,4);
1377 cio_write(cio, MJ2_URL, 4); /* URL */
1378
1379 if (url_num == 0)
1380 cio_write(cio, 1, 4); /* Version = 0, flags = 1 because stored in same file */
1381 else {
1382 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1383 cio_write(cio, tk->url[url_num - 1].location[0], 4);
1384 cio_write(cio, tk->url[url_num - 1].location[1], 4);
1385 cio_write(cio, tk->url[url_num - 1].location[2], 4);
1386 cio_write(cio, tk->url[url_num - 1].location[3], 4);
1387 }
1388
1389 box.length = cio_tell(cio) - box.init_pos;
1390 cio_seek(cio, box.init_pos);
1391 cio_write(cio, box.length, 4); /* L */
1392 cio_seek(cio, box.init_pos + box.length);
1393 }
1394
1395 /*
1396 * Read the URL box
1397 *
1398 * URL box
1399 *
1400 */
mj2_read_url(mj2_tk_t * tk,int urn_num,opj_cio_t * cio)1401 int mj2_read_url(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1402 {
1403 mj2_box_t box;
1404
1405 mj2_read_boxhdr(&box, cio);
1406 if (MJ2_URL != box.type) {
1407 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URL Marker\n");
1408 return 1;
1409 }
1410
1411 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1412 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URL box\n");
1413 return 1;
1414 }
1415
1416 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1417 tk->url[urn_num].location[0] = cio_read(cio, 4);
1418 tk->url[urn_num].location[1] = cio_read(cio, 4);
1419 tk->url[urn_num].location[2] = cio_read(cio, 4);
1420 tk->url[urn_num].location[3] = cio_read(cio, 4);
1421 } else {
1422 tk->num_url--;
1423 }
1424
1425
1426 if (cio_tell(cio) - box.init_pos != box.length) {
1427 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URL Box size\n");
1428 return 1;
1429 }
1430 return 0;
1431 }
1432
1433 /*
1434 * Write the URN box
1435 *
1436 * URN box
1437 *
1438 */
mj2_write_urn(mj2_tk_t * tk,int urn_num,opj_cio_t * cio)1439 void mj2_write_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1440 {
1441 mj2_box_t box;
1442
1443 box.init_pos = cio_tell(cio);
1444 cio_skip(cio,4);
1445 cio_write(cio, MJ2_URN, 4); /* URN */
1446
1447 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1448
1449 cio_write(cio, tk->urn[urn_num].name[0], 4);
1450 cio_write(cio, tk->urn[urn_num].name[1], 4);
1451 cio_write(cio, tk->urn[urn_num].name[2], 4);
1452 cio_write(cio, tk->urn[urn_num].name[3], 4);
1453 cio_write(cio, tk->urn[urn_num].location[0], 4);
1454 cio_write(cio, tk->urn[urn_num].location[1], 4);
1455 cio_write(cio, tk->urn[urn_num].location[2], 4);
1456 cio_write(cio, tk->urn[urn_num].location[3], 4);
1457
1458 box.length = cio_tell(cio) - box.init_pos;
1459 cio_seek(cio, box.init_pos);
1460 cio_write(cio, box.length, 4); /* L */
1461 cio_seek(cio, box.init_pos + box.length);
1462 }
1463
1464 /*
1465 * Read the URN box
1466 *
1467 * URN box
1468 *
1469 */
mj2_read_urn(mj2_tk_t * tk,int urn_num,opj_cio_t * cio)1470 int mj2_read_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1471 {
1472
1473 mj2_box_t box;
1474
1475 mj2_read_boxhdr(&box, cio);
1476 if (MJ2_URN != box.type) {
1477 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URN Marker\n");
1478 return 1;
1479 }
1480
1481 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1482 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URN box\n");
1483 return 1;
1484 }
1485
1486 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1487 tk->urn[urn_num].name[0] = cio_read(cio, 4);
1488 tk->urn[urn_num].name[1] = cio_read(cio, 4);
1489 tk->urn[urn_num].name[2] = cio_read(cio, 4);
1490 tk->urn[urn_num].name[3] = cio_read(cio, 4);
1491 tk->urn[urn_num].location[0] = cio_read(cio, 4);
1492 tk->urn[urn_num].location[1] = cio_read(cio, 4);
1493 tk->urn[urn_num].location[2] = cio_read(cio, 4);
1494 tk->urn[urn_num].location[3] = cio_read(cio, 4);
1495 }
1496
1497
1498 if (cio_tell(cio) - box.init_pos != box.length) {
1499 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URN Box size\n");
1500 return 1;
1501 }
1502 return 0;
1503 }
1504
1505
1506 /*
1507 * Write the DREF box
1508 *
1509 * Data reference box
1510 *
1511 */
mj2_write_dref(mj2_tk_t * tk,opj_cio_t * cio)1512 void mj2_write_dref(mj2_tk_t * tk, opj_cio_t *cio)
1513 {
1514 int i;
1515 mj2_box_t box;
1516
1517 box.init_pos = cio_tell(cio);
1518 cio_skip(cio,4);
1519 cio_write(cio, MJ2_DREF, 4); /* DREF */
1520
1521 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1522
1523 if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
1524 cio_write(cio, 1, 4); /* entry_count = 1 */
1525 mj2_write_url(tk, 0, cio);
1526 } else {
1527 cio_write(cio, tk->num_url + tk->num_urn, 4); /* entry_count */
1528
1529 for (i = 0; i < tk->num_url; i++)
1530 mj2_write_url(tk, i + 1, cio);
1531
1532 for (i = 0; i < tk->num_urn; i++)
1533 mj2_write_urn(tk, i, cio);
1534 }
1535
1536 box.length = cio_tell(cio) - box.init_pos;
1537 cio_seek(cio, box.init_pos);
1538 cio_write(cio, box.length, 4); /* L */
1539 cio_seek(cio, box.init_pos + box.length);
1540 }
1541
1542 /*
1543 * Read the DREF box
1544 *
1545 * Data reference box
1546 *
1547 */
mj2_read_dref(mj2_tk_t * tk,opj_cio_t * cio)1548 int mj2_read_dref(mj2_tk_t * tk, opj_cio_t *cio)
1549 {
1550
1551 int i;
1552 int entry_count, marker;
1553 mj2_box_t box;
1554
1555 mj2_read_boxhdr(&box, cio);
1556 if (MJ2_DREF != box.type) {
1557 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DREF Marker\n");
1558 return 1;
1559 }
1560
1561 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1562 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in DREF box\n");
1563 return 1;
1564 }
1565
1566 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1567 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in DREF box. Expected flag 0\n");
1568 return 1;
1569 }
1570
1571 entry_count = cio_read(cio, 4);
1572 tk->num_url = 0;
1573 tk->num_urn = 0;
1574
1575 for (i = 0; i < entry_count; i++) {
1576 cio_skip(cio,4);
1577 marker = cio_read(cio, 4);
1578 if (marker == MJ2_URL) {
1579 cio_skip(cio,-8);
1580 tk->num_url++;
1581 if (mj2_read_url(tk, tk->num_url, cio))
1582 return 1;
1583 } else if (marker == MJ2_URN) {
1584 cio_skip(cio,-8);
1585 tk->num_urn++;
1586 if (mj2_read_urn(tk, tk->num_urn, cio))
1587 return 1;
1588 } else {
1589 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n");
1590 return 1;
1591 }
1592
1593 }
1594
1595
1596 if (cio_tell(cio) - box.init_pos != box.length) {
1597 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DREF Box size\n");
1598 return 1;
1599 }
1600 return 0;
1601 }
1602
1603 /*
1604 * Write the DINF box
1605 *
1606 * Data information box
1607 *
1608 */
mj2_write_dinf(mj2_tk_t * tk,opj_cio_t * cio)1609 void mj2_write_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1610 {
1611 mj2_box_t box;
1612
1613 box.init_pos = cio_tell(cio);
1614 cio_skip(cio,4);
1615 cio_write(cio, MJ2_DINF, 4); /* DINF */
1616
1617 mj2_write_dref(tk, cio);
1618
1619 box.length = cio_tell(cio) - box.init_pos;
1620 cio_seek(cio, box.init_pos);
1621 cio_write(cio, box.length, 4); /* L */
1622 cio_seek(cio, box.init_pos + box.length);
1623 }
1624
1625 /*
1626 * Read the DINF box
1627 *
1628 * Data information box
1629 *
1630 */
mj2_read_dinf(mj2_tk_t * tk,opj_cio_t * cio)1631 int mj2_read_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1632 {
1633 mj2_box_t box;
1634
1635 mj2_read_boxhdr(&box, cio);
1636 if (MJ2_DINF != box.type) {
1637 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DINF Marker\n");
1638 return 1;
1639 }
1640
1641 if (mj2_read_dref(tk, cio))
1642 return 1;
1643
1644 if (cio_tell(cio) - box.init_pos != box.length) {
1645 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DINF Box size\n");
1646 return 1;
1647 }
1648 return 0;
1649 }
1650
1651 /*
1652 * Write the VMHD box
1653 *
1654 * Video Media information box
1655 *
1656 */
mj2_write_vmhd(mj2_tk_t * tk,opj_cio_t * cio)1657 void mj2_write_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1658 {
1659 mj2_box_t box;
1660
1661 box.init_pos = cio_tell(cio);
1662 cio_skip(cio,4);
1663 cio_write(cio, MJ2_VMHD, 4); /* VMHD */
1664
1665 cio_write(cio, 1, 4); /* Version = 0, flags = 1 */
1666
1667 cio_write(cio, tk->graphicsmode, 2);
1668 cio_write(cio, tk->opcolor[0], 2);
1669 cio_write(cio, tk->opcolor[1], 2);
1670 cio_write(cio, tk->opcolor[2], 2);
1671
1672 box.length = cio_tell(cio) - box.init_pos;
1673 cio_seek(cio, box.init_pos);
1674 cio_write(cio, box.length, 4); /* L */
1675 cio_seek(cio, box.init_pos + box.length);
1676 }
1677
1678 /*
1679 * Read the VMHD box
1680 *
1681 * Video Media information box
1682 *
1683 */
mj2_read_vmhd(mj2_tk_t * tk,opj_cio_t * cio)1684 int mj2_read_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1685 {
1686 mj2_box_t box;
1687
1688 mj2_read_boxhdr(&box, cio);
1689 if (MJ2_VMHD != box.type) {
1690 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected VMHD Marker\n");
1691 return 1;
1692 }
1693
1694 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1695 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in VMHD box\n");
1696 return 1;
1697 }
1698
1699 if (1 != cio_read(cio, 3)) { /* Flags = 1 */
1700 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in VMHD box. Expected flag 1\n");
1701 return 1;
1702 }
1703
1704 tk->track_type = 0;
1705 tk->graphicsmode = cio_read(cio, 2);
1706 tk->opcolor[0] = cio_read(cio, 2);
1707 tk->opcolor[1] = cio_read(cio, 2);
1708 tk->opcolor[2] = cio_read(cio, 2);
1709
1710 if (cio_tell(cio) - box.init_pos != box.length) {
1711 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with VMHD Box size\n");
1712 return 1;
1713 }
1714 return 0;
1715 }
1716
1717 /*
1718 * Write the SMHD box
1719 *
1720 * Sound Media information box
1721 *
1722 */
mj2_write_smhd(mj2_tk_t * tk,opj_cio_t * cio)1723 void mj2_write_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1724 {
1725 mj2_box_t box;
1726
1727 box.init_pos = cio_tell(cio);
1728 cio_skip(cio,4);
1729 cio_write(cio, MJ2_SMHD, 4); /* SMHD */
1730
1731 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1732
1733 cio_write(cio, tk->balance, 2);
1734
1735 cio_write(cio, 0, 2); /* Reserved */
1736
1737 box.length = cio_tell(cio) - box.init_pos;
1738 cio_seek(cio, box.init_pos);
1739 cio_write(cio, box.length, 4); /* L */
1740 cio_seek(cio, box.init_pos + box.length);
1741 }
1742
1743 /*
1744 * Read the SMHD box
1745 *
1746 * Sound Media information box
1747 *
1748 */
mj2_read_smhd(mj2_tk_t * tk,opj_cio_t * cio)1749 int mj2_read_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1750 {
1751 mj2_box_t box;
1752
1753 mj2_read_boxhdr(&box, cio);
1754 if (MJ2_SMHD != box.type) {
1755 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected SMHD Marker\n");
1756 return 1;
1757 }
1758
1759 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1760 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in SMHD box\n");
1761 return 1;
1762 }
1763
1764 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1765 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in SMHD box. Expected flag 0\n");
1766 return 1;
1767 }
1768
1769 tk->track_type = 1;
1770 tk->balance = cio_read(cio, 2);
1771
1772 /* Init variables to zero to avoid problems when freeeing memory
1773 The values will possibly be overidded when decoding the track structure */
1774 tk->num_br = 0;
1775 tk->num_url = 0;
1776 tk->num_urn = 0;
1777 tk->num_chunks = 0;
1778 tk->num_tts = 0;
1779 tk->num_samplestochunk = 0;
1780 tk->num_samples = 0;
1781
1782 cio_skip(cio,2); /* Reserved */
1783
1784 if (cio_tell(cio) - box.init_pos != box.length) {
1785 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with SMHD Box size\n");
1786 return 1;
1787 }
1788 return 0;
1789 }
1790
1791 /*
1792 * Write the HMHD box
1793 *
1794 * Hint Media information box
1795 *
1796 */
mj2_write_hmhd(mj2_tk_t * tk,opj_cio_t * cio)1797 void mj2_write_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1798 {
1799 mj2_box_t box;
1800
1801 box.init_pos = cio_tell(cio);
1802 cio_skip(cio,4);
1803 cio_write(cio, MJ2_HMHD, 4); /* HMHD */
1804
1805 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1806
1807 cio_write(cio, tk->maxPDUsize, 2);
1808 cio_write(cio, tk->avgPDUsize, 2);
1809 cio_write(cio, tk->maxbitrate, 4);
1810 cio_write(cio, tk->avgbitrate, 4);
1811 cio_write(cio, tk->slidingavgbitrate, 4);
1812
1813 box.length = cio_tell(cio) - box.init_pos;
1814 cio_seek(cio, box.init_pos);
1815 cio_write(cio, box.length, 4); /* L */
1816 cio_seek(cio, box.init_pos + box.length);
1817 }
1818
1819 /*
1820 * Read the HMHD box
1821 *
1822 * Hint Media information box
1823 *
1824 */
mj2_read_hmhd(mj2_tk_t * tk,opj_cio_t * cio)1825 int mj2_read_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1826 {
1827 mj2_box_t box;
1828
1829 mj2_read_boxhdr(&box, cio);
1830 if (MJ2_HMHD != box.type) {
1831 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HMHD Marker\n");
1832 return 1;
1833 }
1834
1835 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1836 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HMHD box\n");
1837 return 1;
1838 }
1839
1840 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1841 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HMHD box. Expected flag 0\n");
1842 return 1;
1843 }
1844
1845 tk->track_type = 2;
1846 tk->maxPDUsize = cio_read(cio, 2);
1847 tk->avgPDUsize = cio_read(cio, 2);
1848 tk->maxbitrate = cio_read(cio, 4);
1849 tk->avgbitrate = cio_read(cio, 4);
1850 tk->slidingavgbitrate = cio_read(cio, 4);
1851
1852 /* Init variables to zero to avoid problems when freeeing memory
1853 The values will possibly be overidded when decoding the track structure */
1854 tk->num_br = 0;
1855 tk->num_url = 0;
1856 tk->num_urn = 0;
1857 tk->num_chunks = 0;
1858 tk->num_tts = 0;
1859 tk->num_samplestochunk = 0;
1860 tk->num_samples = 0;
1861
1862
1863 if (cio_tell(cio) - box.init_pos != box.length) {
1864 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HMHD Box size\n");
1865 return 1;
1866 }
1867 return 0;
1868 }
1869
1870 /*
1871 * Write the MINF box
1872 *
1873 * Media information box
1874 *
1875 */
mj2_write_minf(mj2_tk_t * tk,opj_cio_t * cio)1876 void mj2_write_minf(mj2_tk_t * tk, opj_cio_t *cio)
1877 {
1878 mj2_box_t box;
1879
1880 box.init_pos = cio_tell(cio);
1881 cio_skip(cio,4);
1882 cio_write(cio, MJ2_MINF, 4); /* MINF */
1883
1884 if (tk->track_type == 0) {
1885 mj2_write_vmhd(tk, cio);
1886 } else if (tk->track_type == 1) {
1887 mj2_write_smhd(tk, cio);
1888 } else if (tk->track_type == 2) {
1889 mj2_write_hmhd(tk, cio);
1890 }
1891
1892 mj2_write_dinf(tk, cio);
1893 mj2_write_stbl(tk, cio);
1894
1895 box.length = cio_tell(cio) - box.init_pos;
1896 cio_seek(cio, box.init_pos);
1897 cio_write(cio, box.length, 4); /* L */
1898 cio_seek(cio, box.init_pos + box.length);
1899 }
1900
1901 /*
1902 * Read the MINF box
1903 *
1904 * Media information box
1905 *
1906 */
mj2_read_minf(mj2_tk_t * tk,opj_image_t * img,opj_cio_t * cio)1907 int mj2_read_minf(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1908 {
1909
1910 unsigned int box_type;
1911 mj2_box_t box;
1912
1913 mj2_read_boxhdr(&box, cio);
1914 if (MJ2_MINF != box.type) {
1915 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MINF Marker\n");
1916 return 1;
1917 }
1918
1919 cio_skip(cio,4);
1920 box_type = cio_read(cio, 4);
1921 cio_skip(cio,-8);
1922
1923 if (box_type == MJ2_VMHD) {
1924 if (mj2_read_vmhd(tk, cio))
1925 return 1;
1926 } else if (box_type == MJ2_SMHD) {
1927 if (mj2_read_smhd(tk, cio))
1928 return 1;
1929 } else if (box_type == MJ2_HMHD) {
1930 if (mj2_read_hmhd(tk, cio))
1931 return 1;
1932 } else {
1933 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n");
1934 return 1;
1935 }
1936
1937 if (mj2_read_dinf(tk, cio))
1938 return 1;
1939
1940 if (mj2_read_stbl(tk, img, cio))
1941 return 1;
1942
1943 if (cio_tell(cio) - box.init_pos != box.length) {
1944 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MINF Box size\n");
1945 return 1;
1946 }
1947 return 0;
1948 }
1949
1950 /*
1951 * Write the HDLR box
1952 *
1953 * Handler reference box
1954 *
1955 */
mj2_write_hdlr(mj2_tk_t * tk,opj_cio_t * cio)1956 void mj2_write_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
1957 {
1958 mj2_box_t box;
1959
1960 box.init_pos = cio_tell(cio);
1961 cio_skip(cio,4);
1962 cio_write(cio, MJ2_HDLR, 4); /* HDLR */
1963
1964 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1965
1966 cio_write(cio, 0, 4); /* Predefine */
1967
1968 tk->name = 0; /* The track name is immediately determined by the track type */
1969
1970 if (tk->track_type == 0) {
1971 tk->handler_type = 0x76696465; /* Handler type: vide */
1972 cio_write(cio, tk->handler_type, 4);
1973
1974 cio_write(cio, 0, 4);
1975 cio_write(cio, 0, 4);
1976 cio_write(cio, 0, 4); /* Reserved */
1977
1978 cio_write(cio, 0x76696465, 4);
1979 cio_write(cio, 0x6F206d65, 4);
1980 cio_write(cio, 0x64696120, 4);
1981 cio_write(cio, 0x74726163, 4);
1982 cio_write(cio, 0x6b00, 2); /* String: video media track */
1983 } else if (tk->track_type == 1) {
1984 tk->handler_type = 0x736F756E; /* Handler type: soun */
1985 cio_write(cio, tk->handler_type, 4);
1986
1987 cio_write(cio, 0, 4);
1988 cio_write(cio, 0, 4);
1989 cio_write(cio, 0, 4); /* Reserved */
1990
1991 cio_write(cio, 0x536F756E, 4);
1992 cio_write(cio, 0x6400, 2); /* String: Sound */
1993 } else if (tk->track_type == 2) {
1994 tk->handler_type = 0x68696E74; /* Handler type: hint */
1995 cio_write(cio, tk->handler_type, 4);
1996
1997 cio_write(cio, 0, 4);
1998 cio_write(cio, 0, 4);
1999 cio_write(cio, 0, 4); /* Reserved */
2000
2001 cio_write(cio, 0x48696E74, 4);
2002 cio_write(cio, 0, 2); /* String: Hint */
2003 }
2004
2005 box.length = cio_tell(cio) - box.init_pos;
2006 cio_seek(cio, box.init_pos);
2007 cio_write(cio, box.length, 4); /* L */
2008 cio_seek(cio, box.init_pos + box.length);
2009 }
2010
2011 /*
2012 * Read the HDLR box
2013 *
2014 * Handler reference box
2015 *
2016 */
mj2_read_hdlr(mj2_tk_t * tk,opj_cio_t * cio)2017 int mj2_read_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
2018 {
2019 int i;
2020 mj2_box_t box;
2021
2022 mj2_read_boxhdr(&box, cio);
2023 if (MJ2_HDLR != box.type) {
2024 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HDLR Marker\n");
2025 return 1;
2026 }
2027
2028
2029 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2030 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HDLR box\n");
2031 return 1;
2032 }
2033
2034 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2035 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HDLR box. Expected flag 0\n");
2036 return 1;
2037 }
2038
2039 cio_skip(cio,4); /* Reserved */
2040
2041 tk->handler_type = cio_read(cio, 4);
2042 cio_skip(cio,12); /* Reserved */
2043
2044 tk->name_size = box.length - 32;
2045
2046 tk->name = (char*) opj_malloc(tk->name_size * sizeof(char));
2047 for (i = 0; i < tk->name_size; i++) {
2048 tk->name[i] = cio_read(cio, 1); /* Name */
2049 }
2050
2051 if (cio_tell(cio) - box.init_pos != box.length) {
2052 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HDLR Box size\n");
2053 return 1;
2054 }
2055 return 0;
2056 }
2057
2058 /*
2059 * Write the MDHD box
2060 *
2061 * Media Header Box
2062 *
2063 */
mj2_write_mdhd(mj2_tk_t * tk,opj_cio_t * cio)2064 void mj2_write_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2065 {
2066 mj2_box_t box;
2067 unsigned int i;
2068 time_t ltime;
2069 unsigned int modification_time;
2070
2071 box.init_pos = cio_tell(cio);
2072 cio_skip(cio,4);
2073 cio_write(cio, MJ2_MDHD, 4); /* MDHD */
2074
2075 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2076
2077 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2078
2079 time(<ime); /* Time since 1/1/70 */
2080 modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2081
2082 cio_write(cio, modification_time, 4); /* Modification Time */
2083
2084 cio_write(cio, tk->timescale, 4); /* Timescale */
2085
2086 tk->duration = 0;
2087
2088 for (i = 0; i < tk->num_samples; i++)
2089 tk->duration += tk->sample[i].sample_delta;
2090
2091 cio_write(cio, tk->duration, 4); /* Duration */
2092
2093 cio_write(cio, tk->language, 2); /* Language */
2094
2095 cio_write(cio, 0, 2); /* Predefined */
2096
2097 box.length = cio_tell(cio) - box.init_pos;
2098 cio_seek(cio, box.init_pos);
2099 cio_write(cio, box.length, 4); /* L */
2100 cio_seek(cio, box.init_pos + box.length);
2101 }
2102
2103 /*
2104 * Read the MDHD box
2105 *
2106 * Media Header Box
2107 *
2108 */
mj2_read_mdhd(mj2_tk_t * tk,opj_cio_t * cio)2109 int mj2_read_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2110 {
2111 mj2_box_t box;
2112
2113 mj2_read_boxhdr(&box, cio);
2114 if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) { /* Kakadu writes MHDR instead of MDHD */
2115 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDHD Marker\n");
2116 return 1;
2117 }
2118
2119 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2120 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MDHD box\n");
2121 return 1;
2122 }
2123
2124 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2125 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MDHD box. Expected flag 0\n");
2126 return 1;
2127 }
2128
2129
2130 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2131
2132 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2133
2134 tk->timescale = cio_read(cio, 4); /* Timescale */
2135
2136 tk->duration = cio_read(cio, 4); /* Duration */
2137
2138 tk->language = cio_read(cio, 2); /* Language */
2139
2140 cio_skip(cio,2); /* Predefined */
2141
2142 if (cio_tell(cio) - box.init_pos != box.length) {
2143 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDHD Box size\n");
2144 return 1;
2145 }
2146 return 0;
2147 }
2148
2149 /*
2150 * Write the MDIA box
2151 *
2152 * Media box
2153 *
2154 */
mj2_write_mdia(mj2_tk_t * tk,opj_cio_t * cio)2155 void mj2_write_mdia(mj2_tk_t * tk, opj_cio_t *cio)
2156 {
2157 mj2_box_t box;
2158
2159 box.init_pos = cio_tell(cio);
2160 cio_skip(cio,4);
2161 cio_write(cio, MJ2_MDIA, 4); /* MDIA */
2162
2163 mj2_write_mdhd(tk, cio);
2164 mj2_write_hdlr(tk, cio);
2165 mj2_write_minf(tk, cio);
2166
2167 box.length = cio_tell(cio) - box.init_pos;
2168 cio_seek(cio, box.init_pos);
2169 cio_write(cio, box.length, 4); /* L */
2170 cio_seek(cio, box.init_pos + box.length);
2171 }
2172
2173 /*
2174 * Read the MDIA box
2175 *
2176 * Media box
2177 *
2178 */
mj2_read_mdia(mj2_tk_t * tk,opj_image_t * img,opj_cio_t * cio)2179 int mj2_read_mdia(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2180 {
2181 mj2_box_t box;
2182
2183 mj2_read_boxhdr(&box, cio);
2184 if (MJ2_MDIA != box.type) {
2185 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDIA Marker\n");
2186 return 1;
2187 }
2188
2189 if (mj2_read_mdhd(tk, cio))
2190 return 1;
2191 if (mj2_read_hdlr(tk, cio))
2192 return 1;
2193 if (mj2_read_minf(tk, img, cio))
2194 return 1;
2195
2196 if (cio_tell(cio) - box.init_pos != box.length) {
2197 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDIA Box size\n");
2198 return 1;
2199 }
2200 return 0;
2201 }
2202
2203 /*
2204 * Write the TKHD box
2205 *
2206 * Track Header box
2207 *
2208 */
mj2_write_tkhd(mj2_tk_t * tk,opj_cio_t * cio)2209 void mj2_write_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2210 {
2211 mj2_box_t box;
2212 unsigned int i;
2213 time_t ltime;
2214
2215 box.init_pos = cio_tell(cio);
2216 cio_skip(cio,4);
2217
2218 cio_write(cio, MJ2_TKHD, 4); /* TKHD */
2219
2220 cio_write(cio, 3, 4); /* Version=0, flags=3 */
2221
2222 time(<ime); /* Time since 1/1/70 */
2223 tk->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2224
2225 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2226
2227 cio_write(cio, tk->modification_time, 4); /* Modification Time */
2228
2229 cio_write(cio, tk->track_ID, 4); /* Track ID */
2230
2231 cio_write(cio, 0, 4); /* Reserved */
2232
2233 tk->duration = 0;
2234
2235 for (i = 0; i < tk->num_samples; i++)
2236 tk->duration += tk->sample[i].sample_delta;
2237
2238 cio_write(cio, tk->duration, 4); /* Duration */
2239
2240 cio_write(cio, 0, 4); /* Reserved */
2241 cio_write(cio, 0, 4); /* Reserved */
2242
2243 cio_write(cio, tk->layer, 2); /* Layer */
2244
2245 cio_write(cio, 0, 2); /* Predefined */
2246
2247 cio_write(cio, tk->volume, 2); /* Volume */
2248
2249 cio_write(cio, 0, 2); /* Reserved */
2250
2251 cio_write(cio, tk->trans_matrix[0], 4); /* Transformation matrix for track */
2252 cio_write(cio, tk->trans_matrix[1], 4);
2253 cio_write(cio, tk->trans_matrix[2], 4);
2254 cio_write(cio, tk->trans_matrix[3], 4);
2255 cio_write(cio, tk->trans_matrix[4], 4);
2256 cio_write(cio, tk->trans_matrix[5], 4);
2257 cio_write(cio, tk->trans_matrix[6], 4);
2258 cio_write(cio, tk->trans_matrix[7], 4);
2259 cio_write(cio, tk->trans_matrix[8], 4);
2260
2261 cio_write(cio, tk->visual_w, 4); /* Video Visual Width */
2262
2263 cio_write(cio, tk->visual_h, 4); /* Video Visual Height */
2264
2265 box.length = cio_tell(cio) - box.init_pos;
2266 cio_seek(cio, box.init_pos);
2267 cio_write(cio, box.length, 4); /* L */
2268 cio_seek(cio, box.init_pos + box.length);
2269 }
2270
2271 /*
2272 * Read the TKHD box
2273 *
2274 * Track Header box
2275 *
2276 */
mj2_read_tkhd(mj2_tk_t * tk,opj_cio_t * cio)2277 int mj2_read_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2278 {
2279 int flag;
2280
2281 mj2_box_t box;
2282
2283 mj2_read_boxhdr(&box, cio);
2284
2285 if (MJ2_TKHD != box.type) {
2286 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TKHD Marker\n");
2287 return 1;
2288 }
2289
2290 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2291 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in TKHD box\n");
2292 return 1;
2293 }
2294
2295 flag = cio_read(cio, 3);
2296
2297 if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) { /* Flags = 1,2,3 or 4 */
2298 opj_event_msg(cio->cinfo, EVT_ERROR,
2299 "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2300 return 1;
2301 }
2302
2303 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2304
2305 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2306
2307 tk->track_ID = cio_read(cio, 4); /* Track ID */
2308
2309 cio_skip(cio,4); /* Reserved */
2310
2311 tk->duration = cio_read(cio, 4); /* Duration */
2312
2313 cio_skip(cio,8); /* Reserved */
2314
2315 tk->layer = cio_read(cio, 2); /* Layer */
2316
2317 cio_read(cio, 2); /* Predefined */
2318
2319 tk->volume = cio_read(cio, 2); /* Volume */
2320
2321 cio_skip(cio,2); /* Reserved */
2322
2323 tk->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for track */
2324 tk->trans_matrix[1] = cio_read(cio, 4);
2325 tk->trans_matrix[2] = cio_read(cio, 4);
2326 tk->trans_matrix[3] = cio_read(cio, 4);
2327 tk->trans_matrix[4] = cio_read(cio, 4);
2328 tk->trans_matrix[5] = cio_read(cio, 4);
2329 tk->trans_matrix[6] = cio_read(cio, 4);
2330 tk->trans_matrix[7] = cio_read(cio, 4);
2331 tk->trans_matrix[8] = cio_read(cio, 4);
2332
2333 tk->visual_w = cio_read(cio, 4); /* Video Visual Width */
2334
2335 tk->visual_h = cio_read(cio, 4); /* Video Visual Height */
2336
2337 if (cio_tell(cio) - box.init_pos != box.length) {
2338 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TKHD Box size\n");
2339 return 1;
2340 }
2341 return 0;
2342 }
2343
2344 /*
2345 * Write the TRAK box
2346 *
2347 * Track box
2348 *
2349 */
mj2_write_trak(mj2_tk_t * tk,opj_cio_t * cio)2350 void mj2_write_trak(mj2_tk_t * tk, opj_cio_t *cio)
2351 {
2352 mj2_box_t box;
2353
2354 box.init_pos = cio_tell(cio);
2355 cio_skip(cio,4);
2356
2357 cio_write(cio, MJ2_TRAK, 4); /* TRAK */
2358
2359 mj2_write_tkhd(tk, cio);
2360 mj2_write_mdia(tk, cio);
2361
2362 box.length = cio_tell(cio) - box.init_pos;
2363 cio_seek(cio, box.init_pos);
2364 cio_write(cio, box.length, 4); /* L */
2365 cio_seek(cio, box.init_pos + box.length);
2366 }
2367
2368 /*
2369 * Read the TRAK box
2370 *
2371 * Track box
2372 *
2373 */
mj2_read_trak(mj2_tk_t * tk,opj_image_t * img,opj_cio_t * cio)2374 int mj2_read_trak(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2375 {
2376 mj2_box_t box;
2377
2378 mj2_read_boxhdr(&box, cio);
2379 if (MJ2_TRAK != box.type) {
2380 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TRAK Marker\n");
2381 return 1;
2382 }
2383 if (mj2_read_tkhd(tk, cio))
2384 return 1;
2385 if (mj2_read_mdia(tk, img, cio))
2386 return 1;
2387 if (cio_tell(cio) - box.init_pos != box.length) {
2388 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TRAK Box\n");
2389 return 1;
2390 }
2391 return 0;
2392 }
2393
2394 /*
2395 * Write the MVHD box
2396 *
2397 * Movie header Box
2398 *
2399 */
mj2_write_mvhd(opj_mj2_t * movie,opj_cio_t * cio)2400 void mj2_write_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2401 {
2402 int i;
2403 mj2_box_t box;
2404 unsigned j;
2405 time_t ltime;
2406 int max_tk_num = 0;
2407
2408 box.init_pos = cio_tell(cio);
2409 cio_skip(cio,4);
2410 cio_write(cio, MJ2_MVHD, 4); /* MVHD */
2411
2412 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2413
2414 time(<ime); /* Time since 1/1/70 */
2415 movie->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2416
2417 cio_write(cio, movie->creation_time, 4); /* Creation Time */
2418
2419 cio_write(cio, movie->modification_time, 4); /* Modification Time */
2420
2421 cio_write(cio, movie->timescale, 4); /* Timescale */
2422
2423 movie->duration = 0;
2424
2425 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2426 mj2_tk_t *tk = &movie->tk[i];
2427
2428 for (j = 0; j < tk->num_samples; j++) {
2429 movie->duration += tk->sample[j].sample_delta;
2430 }
2431 }
2432
2433 cio_write(cio, movie->duration, 4);
2434
2435 cio_write(cio, movie->rate, 4); /* Rate to play presentation */
2436
2437 cio_write(cio, movie->volume, 2); /* Volume */
2438
2439 cio_write(cio, 0, 2); /* Reserved */
2440 cio_write(cio, 0, 4); /* Reserved */
2441 cio_write(cio, 0, 4); /* Reserved */
2442
2443 cio_write(cio, movie->trans_matrix[0], 4); /* Transformation matrix for video */
2444 cio_write(cio, movie->trans_matrix[1], 4);
2445 cio_write(cio, movie->trans_matrix[2], 4);
2446 cio_write(cio, movie->trans_matrix[3], 4);
2447 cio_write(cio, movie->trans_matrix[4], 4);
2448 cio_write(cio, movie->trans_matrix[5], 4);
2449 cio_write(cio, movie->trans_matrix[6], 4);
2450 cio_write(cio, movie->trans_matrix[7], 4);
2451 cio_write(cio, movie->trans_matrix[8], 4);
2452
2453 cio_write(cio, 0, 4); /* Pre-defined */
2454 cio_write(cio, 0, 4); /* Pre-defined */
2455 cio_write(cio, 0, 4); /* Pre-defined */
2456 cio_write(cio, 0, 4); /* Pre-defined */
2457 cio_write(cio, 0, 4); /* Pre-defined */
2458 cio_write(cio, 0, 4); /* Pre-defined */
2459
2460
2461 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
2462 if (max_tk_num < movie->tk[i].track_ID)
2463 max_tk_num = movie->tk[i].track_ID;
2464 }
2465
2466 movie->next_tk_id = max_tk_num + 1;
2467
2468 cio_write(cio, movie->next_tk_id, 4); /* ID of Next track to be added */
2469
2470 box.length = cio_tell(cio) - box.init_pos;
2471 cio_seek(cio, box.init_pos);
2472 cio_write(cio, box.length, 4); /* L */
2473 cio_seek(cio, box.init_pos + box.length);
2474 }
2475
2476 /*
2477 * Read the MVHD box
2478 *
2479 * Movie header Box
2480 *
2481 */
mj2_read_mvhd(opj_mj2_t * movie,opj_cio_t * cio)2482 int mj2_read_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2483 {
2484 mj2_box_t box;
2485
2486 mj2_read_boxhdr(&box, cio);
2487 if (MJ2_MVHD != box.type) {
2488 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MVHD Marker\n");
2489 return 1;
2490 }
2491
2492
2493 if (0 != cio_read(cio, 4)) { /* Version = 0, flags = 0 */
2494 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MVHD box\n");
2495 }
2496
2497 movie->creation_time = cio_read(cio, 4); /* Creation Time */
2498
2499 movie->modification_time = cio_read(cio, 4); /* Modification Time */
2500
2501 movie->timescale = cio_read(cio, 4); /* Timescale */
2502
2503 movie->duration = cio_read(cio, 4); /* Duration */
2504
2505 movie->rate = cio_read(cio, 4); /* Rate to play presentation */
2506
2507 movie->volume = cio_read(cio, 2); /* Volume */
2508
2509 cio_skip(cio,10); /* Reserved */
2510
2511 movie->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for video */
2512 movie->trans_matrix[1] = cio_read(cio, 4);
2513 movie->trans_matrix[2] = cio_read(cio, 4);
2514 movie->trans_matrix[3] = cio_read(cio, 4);
2515 movie->trans_matrix[4] = cio_read(cio, 4);
2516 movie->trans_matrix[5] = cio_read(cio, 4);
2517 movie->trans_matrix[6] = cio_read(cio, 4);
2518 movie->trans_matrix[7] = cio_read(cio, 4);
2519 movie->trans_matrix[8] = cio_read(cio, 4);
2520
2521 cio_skip(cio,24); /* Pre-defined */
2522
2523 movie->next_tk_id = cio_read(cio, 4); /* ID of Next track to be added */
2524
2525 if (cio_tell(cio) - box.init_pos != box.length) {
2526 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MVHD Box Size\n");
2527 return 1;
2528 }
2529 return 0;
2530 }
2531
2532
2533 /*
2534 * Write the MOOV box
2535 *
2536 * Movie Box
2537 *
2538 */
mj2_write_moov(opj_mj2_t * movie,opj_cio_t * cio)2539 void mj2_write_moov(opj_mj2_t * movie, opj_cio_t *cio)
2540 {
2541 int i;
2542 mj2_box_t box;
2543
2544 box.init_pos = cio_tell(cio);
2545 cio_skip(cio,4);
2546 cio_write(cio, MJ2_MOOV, 4); /* MOOV */
2547
2548 mj2_write_mvhd(movie, cio);
2549
2550 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2551 mj2_write_trak(&movie->tk[i], cio);
2552 }
2553
2554 box.length = cio_tell(cio) - box.init_pos;
2555 cio_seek(cio, box.init_pos);
2556 cio_write(cio, box.length, 4); /* L */
2557 cio_seek(cio, box.init_pos + box.length);
2558 }
2559
2560 /*
2561 * Read the MOOV box
2562 *
2563 * Movie Box
2564 *
2565 */
mj2_read_moov(opj_mj2_t * movie,opj_image_t * img,opj_cio_t * cio)2566 int mj2_read_moov(opj_mj2_t * movie, opj_image_t * img, opj_cio_t *cio)
2567 {
2568 unsigned int i;
2569 mj2_box_t box;
2570 mj2_box_t box2;
2571
2572 mj2_read_boxhdr(&box, cio);
2573 if (MJ2_MOOV != box.type) {
2574 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MOOV Marker\n");
2575 return 1;
2576 }
2577
2578 if (mj2_read_mvhd(movie, cio))
2579 return 1;
2580
2581 movie->tk = (mj2_tk_t*) opj_malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2582
2583 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
2584 mj2_tk_t *tk = &movie->tk[i];
2585 tk->cinfo = movie->cinfo;
2586 mj2_read_boxhdr(&box2, cio);
2587 if (box2.type == MJ2_TRAK) {
2588 cio_seek(cio, box2.init_pos);
2589 if (mj2_read_trak(tk, img, cio))
2590 return 1;
2591
2592 if (tk->track_type == 0) {
2593 movie->num_vtk++;
2594 } else if (tk->track_type == 1) {
2595 movie->num_stk++;
2596 } else if (tk->track_type == 2) {
2597 movie->num_htk++;
2598 }
2599 } else if (box2.type == MJ2_MVEX) {
2600 cio_seek(cio, box2.init_pos);
2601 cio_skip(cio,box2.length);
2602 i--;
2603 } else {
2604 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2605 return 1;
2606 }
2607 }
2608 return 0;
2609 }
2610
mj2_read_struct(FILE * file,opj_mj2_t * movie)2611 int mj2_read_struct(FILE *file, opj_mj2_t *movie) {
2612 mj2_box_t box;
2613 opj_image_t img;
2614 unsigned char * src;
2615 int fsresult;
2616 int foffset;
2617 opj_cio_t *cio;
2618
2619 /* open a byte stream for reading */
2620 src = (unsigned char*) opj_malloc(300 * sizeof(unsigned char));
2621
2622 /* Assuming that jp and ftyp markers size do
2623 not exceed 300 bytes */
2624 fread(src,300,1, file);
2625
2626 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2627
2628 if (mj2_read_jp(cio))
2629 return 1;
2630 if (mj2_read_ftyp(movie, cio))
2631 return 1;
2632
2633 fsresult = fseek(file,cio_tell(cio),SEEK_SET);
2634 if( fsresult ) {
2635 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read data after FTYP box\n" );
2636 return 1;
2637 }
2638
2639 foffset = cio_tell(cio);
2640
2641 box.type = 0;
2642
2643 fread(src,30,1,file);
2644 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2645 mj2_read_boxhdr(&box, cio);
2646
2647 while(box.type != MJ2_MOOV) {
2648
2649 switch(box.type)
2650 {
2651 case MJ2_MDAT:
2652 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2653 if( fsresult ) {
2654 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MDAT box\n" );
2655 return 1;
2656 }
2657 foffset += box.length;
2658 break;
2659
2660 case MJ2_MOOF:
2661 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2662 if( fsresult ) {
2663 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOF box\n" );
2664 return 1;
2665 }
2666 foffset += box.length;
2667 break;
2668 case MJ2_FREE:
2669 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2670 if( fsresult ) {
2671 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read FREE box\n" );
2672 return 1;
2673 }
2674 foffset += box.length;
2675 break;
2676 case MJ2_SKIP:
2677 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2678 if( fsresult ) {
2679 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read SKIP box\n" );
2680 return 1;
2681 }
2682 foffset += box.length;
2683 break;
2684 default:
2685 opj_event_msg(cio->cinfo, EVT_ERROR, "Unknown box in MJ2 stream\n");
2686 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2687 if( fsresult ) {
2688 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read end of unknown box\n");
2689 return 1;
2690 }
2691 foffset += box.length;
2692 break;
2693 }
2694 fsresult = fread(src,8,1,file);
2695 if (fsresult != 1) {
2696 opj_event_msg(cio->cinfo, EVT_ERROR, "MOOV box not found in file\n");
2697 return 1;
2698 }
2699 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 8);
2700 mj2_read_boxhdr(&box, cio);
2701 }
2702
2703 fseek(file,foffset,SEEK_SET);
2704 src = (unsigned char*)opj_realloc(src,box.length);
2705 fsresult = fread(src,box.length,1,file);
2706 if (fsresult != 1) {
2707 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOV box\n");
2708 return 1;
2709 }
2710
2711 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, box.length);
2712
2713 if (mj2_read_moov(movie, &img, cio))
2714 return 1;
2715
2716 opj_free(src);
2717 return 0;
2718 }
2719
2720 /* ----------------------------------------------------------------------- */
2721 /* MJ2 decoder interface */
2722 /* ----------------------------------------------------------------------- */
2723
mj2_create_decompress()2724 opj_dinfo_t* mj2_create_decompress() {
2725 opj_mj2_t* mj2;
2726 opj_dinfo_t *dinfo = (opj_dinfo_t*) opj_calloc(1, sizeof(opj_dinfo_t));
2727 if(!dinfo) return NULL;
2728
2729 dinfo->is_decompressor = OPJ_TRUE;
2730
2731 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2732 dinfo->mj2_handle = mj2;
2733 if(mj2) {
2734 mj2->cinfo = (opj_common_ptr)dinfo;
2735 }
2736 mj2->j2k = j2k_create_decompress((opj_common_ptr)dinfo);
2737 dinfo->j2k_handle = mj2->j2k;
2738
2739 return dinfo;
2740 }
2741
mj2_setup_decoder(opj_mj2_t * movie,mj2_dparameters_t * mj2_parameters)2742 void mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters) {
2743 movie->num_vtk=0;
2744 movie->num_stk=0;
2745 movie->num_htk=0;
2746
2747 /* setup the J2K decoder parameters */
2748 j2k_setup_decoder((opj_j2k_t*)movie->cinfo->j2k_handle,
2749 &mj2_parameters->j2k_parameters);
2750
2751 }
2752
mj2_destroy_decompress(opj_mj2_t * movie)2753 void mj2_destroy_decompress(opj_mj2_t *movie) {
2754 if(movie) {
2755 int i;
2756 mj2_tk_t *tk=NULL;
2757
2758 if (movie->cinfo->j2k_handle)
2759 j2k_destroy_compress(movie->j2k);
2760
2761 if (movie->num_cl != 0)
2762 opj_free(movie->cl);
2763
2764 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2765 tk = &movie->tk[i];
2766 if (tk->name_size != 0)
2767 opj_free(tk->name);
2768 if (tk->track_type == 0) {/* Video track */
2769 if (tk->jp2_struct.comps != NULL)
2770 opj_free(tk->jp2_struct.comps);
2771 if (tk->jp2_struct.cl != NULL)
2772 opj_free(tk->jp2_struct.cl);
2773 if (tk->num_jp2x != 0)
2774 opj_free(tk->jp2xdata);
2775
2776 }
2777 if (tk->num_url != 0)
2778 opj_free(tk->url);
2779 if (tk->num_urn != 0)
2780 opj_free(tk->urn);
2781 if (tk->num_br != 0)
2782 opj_free(tk->br);
2783 if (tk->num_tts != 0)
2784 opj_free(tk->tts);
2785 if (tk->num_chunks != 0)
2786 opj_free(tk->chunk);
2787 if (tk->num_samplestochunk != 0)
2788 opj_free(tk->sampletochunk);
2789 if (tk->num_samples != 0)
2790 opj_free(tk->sample);
2791 }
2792
2793 opj_free(movie->tk);
2794 }
2795 opj_free(movie);
2796 }
2797
2798 /* ----------------------------------------------------------------------- */
2799 /* MJ2 encoder interface */
2800 /* ----------------------------------------------------------------------- */
2801
2802
mj2_create_compress()2803 opj_cinfo_t* mj2_create_compress() {
2804 opj_mj2_t* mj2;
2805 opj_cinfo_t *cinfo = (opj_cinfo_t*) opj_calloc(1, sizeof(opj_cinfo_t));
2806 if(!cinfo) return NULL;
2807
2808 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2809 cinfo->mj2_handle = mj2;
2810 if(mj2) {
2811 mj2->cinfo = (opj_common_ptr)cinfo;
2812 }
2813
2814 mj2->j2k = j2k_create_compress(mj2->cinfo);
2815 cinfo->j2k_handle = mj2->j2k;
2816
2817 return cinfo;
2818 }
2819
mj2_setup_encoder(opj_mj2_t * movie,mj2_cparameters_t * parameters)2820 void mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters) {
2821 if(movie && parameters) {
2822 opj_jp2_t *jp2_struct;
2823
2824 movie->num_htk = 0; /* No hint tracks */
2825 movie->num_stk = 0; /* No sound tracks */
2826 movie->num_vtk = 1; /* One video track */
2827
2828 movie->brand = MJ2_MJ2; /* One brand: MJ2 */
2829 movie->num_cl = 2; /* Two compatible brands: MJ2 and MJ2S */
2830 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
2831 movie->cl[0] = MJ2_MJ2;
2832 movie->cl[1] = MJ2_MJ2S;
2833 movie->minversion = 0; /* Minimum version: 0 */
2834
2835 movie->tk = (mj2_tk_t*) opj_malloc(sizeof(mj2_tk_t)); /*Memory allocation for the video track*/
2836 movie->tk[0].track_ID = 1; /* Track ID = 1 */
2837 movie->tk[0].track_type = 0; /* Video track */
2838 movie->tk[0].Dim[0] = parameters->Dim[0];
2839 movie->tk[0].Dim[1] = parameters->Dim[1];
2840 movie->tk[0].w = parameters->w;
2841 movie->tk[0].h = parameters->h;
2842 movie->tk[0].CbCr_subsampling_dx = parameters->CbCr_subsampling_dx;
2843 movie->tk[0].CbCr_subsampling_dy = parameters->CbCr_subsampling_dy;
2844 movie->tk[0].sample_rate = parameters->frame_rate;
2845 movie->tk[0].name_size = 0;
2846 movie->tk[0].chunk = (mj2_chunk_t*) opj_malloc(sizeof(mj2_chunk_t));
2847 movie->tk[0].sample = (mj2_sample_t*) opj_malloc(sizeof(mj2_sample_t));
2848 movie->tk[0].depth = parameters->prec;
2849
2850 jp2_struct = &movie->tk[0].jp2_struct;
2851 jp2_struct->numcomps = parameters->numcomps; /* NC */
2852 jp2_struct->comps = (opj_jp2_comps_t*) opj_malloc(jp2_struct->numcomps * sizeof(opj_jp2_comps_t));
2853 jp2_struct->precedence = 0; /* PRECEDENCE*/
2854 jp2_struct->approx = 0; /* APPROX*/
2855 jp2_struct->brand = JP2_JP2; /* BR */
2856 jp2_struct->minversion = 0; /* MinV */
2857 jp2_struct->numcl = 1;
2858 jp2_struct->cl = (unsigned int*) opj_malloc(jp2_struct->numcl * sizeof(unsigned int));
2859 jp2_struct->cl[0] = JP2_JP2; /* CL0 : JP2 */
2860 jp2_struct->C = 7; /* C : Always 7*/
2861 jp2_struct->UnkC = 0; /* UnkC, colorspace specified in colr box*/
2862 jp2_struct->IPR = 0; /* IPR, no intellectual property*/
2863 jp2_struct->w = parameters->w;
2864 jp2_struct->h = parameters->h;
2865 jp2_struct->bpc = 7;
2866 jp2_struct->meth = parameters->meth;
2867 jp2_struct->enumcs = parameters->enumcs;
2868 }
2869 }
2870
mj2_destroy_compress(opj_mj2_t * movie)2871 void mj2_destroy_compress(opj_mj2_t *movie) {
2872 if(movie) {
2873 int i;
2874 mj2_tk_t *tk=NULL;
2875
2876 if (movie->cinfo->j2k_handle) {
2877 j2k_destroy_compress(movie->j2k);
2878 }
2879
2880 if (movie->num_cl != 0)
2881 opj_free(movie->cl);
2882
2883 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2884 tk = &movie->tk[i];
2885 if (tk->name_size != 0)
2886 opj_free(tk->name);
2887 if (tk->track_type == 0) {/* Video track */
2888 if (tk->jp2_struct.comps != NULL)
2889 opj_free(tk->jp2_struct.comps);
2890 if (tk->jp2_struct.cl != NULL)
2891 opj_free(tk->jp2_struct.cl);
2892 if (tk->num_jp2x != 0)
2893 opj_free(tk->jp2xdata);
2894
2895 }
2896 if (tk->num_url != 0)
2897 opj_free(tk->url);
2898 if (tk->num_urn != 0)
2899 opj_free(tk->urn);
2900 if (tk->num_br != 0)
2901 opj_free(tk->br);
2902 if (tk->num_tts != 0)
2903 opj_free(tk->tts);
2904 if (tk->num_chunks != 0)
2905 opj_free(tk->chunk);
2906 if (tk->num_samplestochunk != 0)
2907 opj_free(tk->sampletochunk);
2908 if (tk->num_samples != 0)
2909 opj_free(tk->sample);
2910 }
2911
2912 opj_free(movie->tk);
2913 }
2914 opj_free(movie);
2915 }
2916