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
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
29 #include "opj_includes.h"
32 /** @defgroup JP2 JP2 - JPEG-2000 file format reader/writer */
35 /** @name Local static functions */
44 int mj2_read_boxhdr(mj2_box_t * box, opj_cio_t *cio)
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");
54 box->length = cio_read(cio, 4);
56 box->length = cio_numbytesleft(cio) + 12;
58 else if (box->length == 0) {
59 box->length = cio_numbytesleft(cio) + 8;
66 * Initialisation of a Standard Movie, given a simple movie structure defined by the user
67 * The movie will have one sample per chunk
69 * Arguments: opj_mj2_t * movie
70 * Several variables of "movie" must be defined in order to enable a correct execution of
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)
75 * The track type (tk->track_type)
76 * The number of sample (tk->num_samples)
77 * The sample rate (tk->sample_rate)
81 int OPJ_CALLCONV mj2_init_stdmovie(opj_mj2_t * movie)
88 movie->brand = MJ2_MJ2;
89 movie->minversion = 0;
91 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
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;
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;
113 w = tk0->w; h = tk0->h; prec = tk0->depth;
115 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++)
117 mj2_tk_t *tk = &movie->tk[i];
120 tk->jp2_struct.comps = NULL;
121 tk->jp2_struct.cl = NULL;
123 if (tk->track_type == 0) /* no sound or hint track */
125 if (tk->num_samples == 0)
128 tk->w = w; tk->h = h; tk->depth = prec;
132 tk->timescale = 1000; /* Timescale = 1 ms */
134 tk->chunk[0].num_samples = 1;
135 tk->chunk[0].sample_descr_idx = 1;
137 tk->same_sample_size = 0;
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;
145 if (tk->sample_rate == 0)
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);
153 for (j = 0; j < tk->num_samples; j++)
155 tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
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;
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) */
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;
194 tk->or_fieldcount = 1;
195 tk->or_fieldorder = 0;
197 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
199 tk->br[1] = MJ2_J2P0;
201 tk->hsub = 2; /* 4:2:0 */
202 tk->vsub = 2; /* 4:2:0 */
205 tk->visual_w = tk->w << 16;
206 tk->visual_h = tk->h << 16;
217 * Time To Sample box Decompact
220 void mj2_tts_decompact(mj2_tk_t * tk)
224 for (i = 0; i < tk->num_tts; i++) {
225 tk->num_samples += tk->tts[i].sample_count;
228 tk->sample = (mj2_sample_t*) opj_malloc(tk->num_samples * sizeof(mj2_sample_t));
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;
238 * Sample To Chunk box Decompact
241 void mj2_stsc_decompact(mj2_tk_t * tk)
243 unsigned int i, j, k, sampleno = 0;
245 if (tk->num_samplestochunk == 1) {
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;
255 tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_samples * sizeof(mj2_chunk_t));
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;
262 sampleno += tk->chunk[j].num_samples;
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;
271 tk->chunk = (mj2_chunk_t*)
272 opj_realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
279 * Chunk offset box Decompact
282 void mj2_stco_decompact(mj2_tk_t * tk)
284 unsigned int i, j, k = 0;
285 unsigned int intra_chunk_offset;
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;
303 void OPJ_CALLCONV mj2_write_jp(opj_cio_t *cio)
306 box.init_pos = cio_tell(cio);
309 cio_write(cio, MJ2_JP, 4); /* JP */
310 cio_write(cio, 0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
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);
321 * JPEG 2000 signature
324 int mj2_read_jp(opj_cio_t *cio)
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");
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");
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");
351 void OPJ_CALLCONV mj2_write_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
355 box.init_pos = cio_tell(cio);
358 cio_write(cio, MJ2_FTYP, 4); /* FTYP */
359 cio_write(cio, movie->brand, 4); /* BR */
360 cio_write(cio, movie->minversion, 4); /* MinV */
362 for (i = 0; i < movie->num_cl; i++)
363 cio_write(cio, movie->cl[i], 4); /* CL */
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);
377 int mj2_read_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
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");
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));
393 for (i = movie->num_cl - 1; i > -1; i--)
394 movie->cl[i] = cio_read(cio, 4); /* CLi */
396 if (cio_tell(cio) - box.init_pos != box.length) {
397 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FTYP Box\n");
410 void mj2_write_stco(mj2_tk_t * tk, opj_cio_t *cio)
415 box.init_pos = cio_tell(cio);
417 cio_write(cio, MJ2_STCO, 4); /* STCO */
419 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
421 cio_write(cio, tk->num_chunks, 4); /* Entry Count */
423 for (i = 0; i < tk->num_chunks; i++) {
424 cio_write(cio, tk->chunk[i].offset, 4); /* Entry offset */
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);
439 int mj2_read_stco(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
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");
465 for (i = 0; i < tk->num_chunks; i++) {
466 tk->chunk[i].offset = cio_read(cio, 4); /* Entry offset */
470 mj2_stco_decompact(tk);
473 if (cio_tell(cio) - box.init_pos != box.length) {
474 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STCO Box size\n");
486 void mj2_write_stsz(mj2_tk_t * tk, opj_cio_t *cio)
491 box.init_pos = cio_tell(cio);
493 cio_write(cio, MJ2_STSZ, 4); /* STSZ */
495 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
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 */
500 cio_write(cio, 1, 4); /* Entry count = 1 */
504 cio_write(cio, 0, 4); /* Sample Size = 0 becase they all have different sizes */
506 cio_write(cio, tk->num_samples, 4); /* Sample Count */
508 for (i = 0; i < tk->num_samples; i++) {
509 cio_write(cio, tk->sample[i].sample_size, 4);
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);
525 int mj2_read_stsz(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
548 sample_size = cio_read(cio, 4);
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;
555 cio_skip(cio,4); /* Sample count = 1 */
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");
563 for (i = 0; i < tk->num_samples; i++) {
564 tk->sample[i].sample_size = cio_read(cio, 4); /* Sample Size */
567 if (cio_tell(cio) - box.init_pos != box.length) {
568 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSZ Box size\n");
582 void mj2_write_stsc(mj2_tk_t * tk, opj_cio_t *cio)
587 box.init_pos = cio_tell(cio);
589 cio_write(cio, MJ2_STSC, 4); /* STSC */
591 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
593 cio_write(cio, tk->num_samplestochunk, 4); /* Entry Count */
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 */
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);
614 int mj2_read_stsc(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
636 tk->num_samplestochunk = cio_read(cio, 4);
638 tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
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);
646 mj2_stsc_decompact(tk); /* decompact sample to chunk box */
649 if (cio_tell(cio) - box.init_pos != box.length) {
650 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSC Box size\n");
662 void mj2_write_stts(mj2_tk_t * tk, opj_cio_t *cio)
668 box.init_pos = cio_tell(cio);
670 cio_write(cio, MJ2_STTS, 4); /* STTS */
672 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
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 */
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);
692 int mj2_read_stts(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
715 tk->num_tts = cio_read(cio, 4);
717 tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
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);
724 mj2_tts_decompact(tk);
726 if (cio_tell(cio) - box.init_pos != box.length) {
727 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STTS Box size\n");
739 void mj2_write_fiel(mj2_tk_t * tk, opj_cio_t *cio)
744 box.init_pos = cio_tell(cio);
746 cio_write(cio, MJ2_FIEL, 4); /* STTS */
748 cio_write(cio, tk->fieldcount, 1); /* Field count */
749 cio_write(cio, tk->fieldorder, 1); /* Field order */
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);
764 int mj2_read_fiel(mj2_tk_t * tk, opj_cio_t *cio)
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");
776 tk->fieldcount = cio_read(cio, 1);
777 tk->fieldorder = cio_read(cio, 1);
779 if (cio_tell(cio) - box.init_pos != box.length) {
780 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FIEL Box size\n");
789 * Original Format Box
792 void mj2_write_orfo(mj2_tk_t * tk, opj_cio_t *cio)
796 box.init_pos = cio_tell(cio);
798 cio_write(cio, MJ2_ORFO, 4);
800 cio_write(cio, tk->or_fieldcount, 1); /* Original Field count */
801 cio_write(cio, tk->or_fieldorder, 1); /* Original Field order */
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);
813 * Original Format Box
816 int mj2_read_orfo(mj2_tk_t * tk, opj_cio_t *cio)
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");
828 tk->or_fieldcount = cio_read(cio, 1);
829 tk->or_fieldorder = cio_read(cio, 1);
831 if (cio_tell(cio) - box.init_pos != box.length) {
832 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with ORFO Box size\n");
844 void mj2_write_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
850 box.init_pos = cio_tell(cio);
852 cio_write(cio, MJ2_JP2P, 4);
854 cio_write(cio, 0, 4); /* Version 0, flags =0 */
856 for (i = 0; i < tk->num_br; i++) {
857 cio_write(cio, tk->br[i], 4);
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);
872 int mj2_read_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
895 tk->num_br = (box.length - 12) / 4;
896 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
898 for (i = 0; i < tk->num_br; i++) {
899 tk->br[i] = cio_read(cio, 4);
902 if (cio_tell(cio) - box.init_pos != box.length) {
903 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2P Box size\n");
915 void mj2_write_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
921 box.init_pos = cio_tell(cio);
923 cio_write(cio, MJ2_JP2X, 4);
925 for (i = 0; i < tk->num_jp2x; i++) {
926 cio_write(cio, tk->jp2xdata[i], 1);
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);
941 int mj2_read_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
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");
954 tk->num_jp2x = (box.length - 8);
955 tk->jp2xdata = (unsigned char*) opj_malloc(tk->num_jp2x * sizeof(unsigned char));
957 for (i = 0; i < tk->num_jp2x; i++) {
958 tk->jp2xdata[i] = cio_read(cio, 1);
961 if (cio_tell(cio) - box.init_pos != box.length) {
962 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2X Box size\n");
971 * MJP2 Subsampling Box
974 void mj2_write_jsub(mj2_tk_t * tk, opj_cio_t *cio)
979 box.init_pos = cio_tell(cio);
981 cio_write(cio, MJ2_JSUB, 4);
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);
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);
997 * MJP2 Subsampling Box
1000 int mj2_read_jsub(mj2_tk_t * tk, opj_cio_t *cio)
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");
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);
1015 if (cio_tell(cio) - box.init_pos != box.length) {
1016 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JSUB Box size\n");
1023 * Write the SMJ2 box
1025 * Visual Sample Entry Description
1028 void mj2_write_smj2(mj2_tk_t * tk, opj_cio_t *cio)
1032 box.init_pos = cio_tell(cio);
1034 cio_write(cio, MJ2_MJ2, 4); /* MJ2 */
1036 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1038 cio_write(cio, 1, 4);
1040 cio_write(cio, 0, 2); /* Pre-defined */
1042 cio_write(cio, 0, 2); /* Reserved */
1044 cio_write(cio, 0, 4); /* Pre-defined */
1045 cio_write(cio, 0, 4); /* Pre-defined */
1046 cio_write(cio, 0, 4); /* Pre-defined */
1048 cio_write(cio, tk->w, 2); /* Width */
1049 cio_write(cio, tk->h, 2); /* Height */
1051 cio_write(cio, tk->horizresolution, 4); /* Horizontal resolution */
1052 cio_write(cio, tk->vertresolution, 4); /* Vertical resolution */
1054 cio_write(cio, 0, 4); /* Reserved */
1056 cio_write(cio, 1, 2); /* Pre-defined = 1 */
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);
1067 cio_write(cio, tk->depth, 2); /* Depth */
1069 cio_write(cio, 0xffff, 2); /* Pre-defined = -1 */
1071 jp2_write_jp2h(&tk->jp2_struct, cio);
1073 mj2_write_fiel(tk, cio);
1075 if (tk->num_br != 0)
1076 mj2_write_jp2p(tk, cio);
1077 if (tk->num_jp2x != 0)
1078 mj2_write_jp2x(tk, cio);
1080 mj2_write_jsub(tk, cio);
1081 mj2_write_orfo(tk, cio);
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);
1092 * Visual Sample Entry Description
1095 int mj2_read_smj2(opj_image_t * img, mj2_tk_t * tk, opj_cio_t *cio)
1099 opj_jp2_color_t color;
1103 mj2_read_boxhdr(&box, cio);
1105 if (MJ2_MJ2 != box.type) {
1106 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n");
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");
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");
1122 cio_skip(cio,2); /* Pre-defined */
1124 cio_skip(cio,2); /* Reserved */
1126 cio_skip(cio,4); /* Pre-defined */
1127 cio_skip(cio,4); /* Pre-defined */
1128 cio_skip(cio,4); /* Pre-defined */
1130 tk->w = cio_read(cio, 2); /* Width */
1131 tk->h = cio_read(cio, 2); /* Height */
1133 tk->horizresolution = cio_read(cio, 4); /* Horizontal resolution */
1134 tk->vertresolution = cio_read(cio, 4); /* Vertical resolution */
1136 cio_skip(cio,4); /* Reserved */
1138 cio_skip(cio,2); /* Pre-defined = 1 */
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);
1149 tk->depth = cio_read(cio, 2); /* Depth */
1151 /* Init std value */
1155 tk->or_fieldcount = 1;
1156 tk->or_fieldorder = 0;
1158 cio_skip(cio,2); /* Pre-defined = -1 */
1159 memset(&color, 0, sizeof(opj_jp2_color_t));
1160 tk->jp2_struct.cinfo = tk->cinfo;
1162 ok = jp2_read_jp2h(&tk->jp2_struct, cio, &color);
1164 tk->jp2_struct.cinfo = NULL;
1168 opj_event_msg(tk->cinfo, EVT_ERROR, "Error reading JP2H Box\n");
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));
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) {
1183 if (mj2_read_fiel(tk, cio))
1188 if (mj2_read_jp2p(tk, cio))
1193 if (mj2_read_jp2x(tk, cio))
1198 if (mj2_read_jsub(tk, cio))
1203 if (mj2_read_orfo(tk, cio))
1208 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MJP2 Box size\n");
1219 * Write the STSD box
1221 * Sample Description
1224 void mj2_write_stsd(mj2_tk_t * tk, opj_cio_t *cio)
1228 box.init_pos = cio_tell(cio);
1230 cio_write(cio, MJ2_STSD, 4); /* STSD */
1232 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1234 cio_write(cio, 1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
1236 if (tk->track_type == 0) {
1237 mj2_write_smj2(tk, cio);
1238 } else if (tk->track_type == 1) {
1239 /* Not implemented*/
1241 if (tk->track_type == 2) {
1242 /* Not implemented*/
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);
1255 * Sample Description
1258 int mj2_read_stsd(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1261 int entry_count, len_2skip;
1265 mj2_read_boxhdr(&box, cio);
1267 if (MJ2_STSD != box.type) {
1268 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSD Marker\n");
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");
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");
1282 entry_count = cio_read(cio, 4);
1284 if (tk->track_type == 0) {
1285 for (i = 0; i < entry_count; i++) {
1286 if (mj2_read_smj2(img, tk, cio))
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);
1298 if (cio_tell(cio) - box.init_pos != box.length) {
1299 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSD Box size\n");
1306 * Write the STBL box
1308 * Sample table box box
1311 void mj2_write_stbl(mj2_tk_t * tk, opj_cio_t *cio)
1315 box.init_pos = cio_tell(cio);
1317 cio_write(cio, MJ2_STBL, 4); /* STBL */
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);
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);
1334 * Sample table box box
1337 int mj2_read_stbl(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
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");
1347 if (mj2_read_stsd(tk, img, cio))
1349 if (mj2_read_stts(tk, cio))
1351 if (mj2_read_stsc(tk, cio))
1353 if (mj2_read_stsz(tk, cio))
1355 if (mj2_read_stco(tk, cio))
1358 if (cio_tell(cio) - box.init_pos != box.length) {
1359 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STBL Box size\n");
1371 void mj2_write_url(mj2_tk_t * tk, int url_num, opj_cio_t *cio)
1375 box.init_pos = cio_tell(cio);
1377 cio_write(cio, MJ2_URL, 4); /* URL */
1380 cio_write(cio, 1, 4); /* Version = 0, flags = 1 because stored in same file */
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);
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);
1401 int mj2_read_url(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
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");
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");
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);
1426 if (cio_tell(cio) - box.init_pos != box.length) {
1427 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URL Box size\n");
1439 void mj2_write_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1443 box.init_pos = cio_tell(cio);
1445 cio_write(cio, MJ2_URN, 4); /* URN */
1447 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
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);
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);
1470 int mj2_read_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
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");
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");
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);
1498 if (cio_tell(cio) - box.init_pos != box.length) {
1499 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URN Box size\n");
1507 * Write the DREF box
1509 * Data reference box
1512 void mj2_write_dref(mj2_tk_t * tk, opj_cio_t *cio)
1517 box.init_pos = cio_tell(cio);
1519 cio_write(cio, MJ2_DREF, 4); /* DREF */
1521 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
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);
1527 cio_write(cio, tk->num_url + tk->num_urn, 4); /* entry_count */
1529 for (i = 0; i < tk->num_url; i++)
1530 mj2_write_url(tk, i + 1, cio);
1532 for (i = 0; i < tk->num_urn; i++)
1533 mj2_write_urn(tk, i, cio);
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);
1545 * Data reference box
1548 int mj2_read_dref(mj2_tk_t * tk, opj_cio_t *cio)
1552 int entry_count, marker;
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");
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");
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");
1571 entry_count = cio_read(cio, 4);
1575 for (i = 0; i < entry_count; i++) {
1577 marker = cio_read(cio, 4);
1578 if (marker == MJ2_URL) {
1581 if (mj2_read_url(tk, tk->num_url, cio))
1583 } else if (marker == MJ2_URN) {
1586 if (mj2_read_urn(tk, tk->num_urn, cio))
1589 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n");
1596 if (cio_tell(cio) - box.init_pos != box.length) {
1597 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DREF Box size\n");
1604 * Write the DINF box
1606 * Data information box
1609 void mj2_write_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1613 box.init_pos = cio_tell(cio);
1615 cio_write(cio, MJ2_DINF, 4); /* DINF */
1617 mj2_write_dref(tk, cio);
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);
1628 * Data information box
1631 int mj2_read_dinf(mj2_tk_t * tk, opj_cio_t *cio)
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");
1641 if (mj2_read_dref(tk, cio))
1644 if (cio_tell(cio) - box.init_pos != box.length) {
1645 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DINF Box size\n");
1652 * Write the VMHD box
1654 * Video Media information box
1657 void mj2_write_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1661 box.init_pos = cio_tell(cio);
1663 cio_write(cio, MJ2_VMHD, 4); /* VMHD */
1665 cio_write(cio, 1, 4); /* Version = 0, flags = 1 */
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);
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);
1681 * Video Media information box
1684 int mj2_read_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
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);
1710 if (cio_tell(cio) - box.init_pos != box.length) {
1711 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with VMHD Box size\n");
1718 * Write the SMHD box
1720 * Sound Media information box
1723 void mj2_write_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1727 box.init_pos = cio_tell(cio);
1729 cio_write(cio, MJ2_SMHD, 4); /* SMHD */
1731 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1733 cio_write(cio, tk->balance, 2);
1735 cio_write(cio, 0, 2); /* Reserved */
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);
1746 * Sound Media information box
1749 int mj2_read_smhd(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
1770 tk->balance = cio_read(cio, 2);
1772 /* Init variables to zero to avoid problems when freeeing memory
1773 The values will possibly be overidded when decoding the track structure */
1779 tk->num_samplestochunk = 0;
1780 tk->num_samples = 0;
1782 cio_skip(cio,2); /* Reserved */
1784 if (cio_tell(cio) - box.init_pos != box.length) {
1785 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with SMHD Box size\n");
1792 * Write the HMHD box
1794 * Hint Media information box
1797 void mj2_write_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1801 box.init_pos = cio_tell(cio);
1803 cio_write(cio, MJ2_HMHD, 4); /* HMHD */
1805 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
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);
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);
1822 * Hint Media information box
1825 int mj2_read_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
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);
1852 /* Init variables to zero to avoid problems when freeeing memory
1853 The values will possibly be overidded when decoding the track structure */
1859 tk->num_samplestochunk = 0;
1860 tk->num_samples = 0;
1863 if (cio_tell(cio) - box.init_pos != box.length) {
1864 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HMHD Box size\n");
1871 * Write the MINF box
1873 * Media information box
1876 void mj2_write_minf(mj2_tk_t * tk, opj_cio_t *cio)
1880 box.init_pos = cio_tell(cio);
1882 cio_write(cio, MJ2_MINF, 4); /* MINF */
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);
1892 mj2_write_dinf(tk, cio);
1893 mj2_write_stbl(tk, cio);
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);
1904 * Media information box
1907 int mj2_read_minf(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1910 unsigned int box_type;
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");
1920 box_type = cio_read(cio, 4);
1923 if (box_type == MJ2_VMHD) {
1924 if (mj2_read_vmhd(tk, cio))
1926 } else if (box_type == MJ2_SMHD) {
1927 if (mj2_read_smhd(tk, cio))
1929 } else if (box_type == MJ2_HMHD) {
1930 if (mj2_read_hmhd(tk, cio))
1933 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n");
1937 if (mj2_read_dinf(tk, cio))
1940 if (mj2_read_stbl(tk, img, cio))
1943 if (cio_tell(cio) - box.init_pos != box.length) {
1944 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MINF Box size\n");
1951 * Write the HDLR box
1953 * Handler reference box
1956 void mj2_write_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
1960 box.init_pos = cio_tell(cio);
1962 cio_write(cio, MJ2_HDLR, 4); /* HDLR */
1964 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1966 cio_write(cio, 0, 4); /* Predefine */
1968 tk->name = 0; /* The track name is immediately determined by the track type */
1970 if (tk->track_type == 0) {
1971 tk->handler_type = 0x76696465; /* Handler type: vide */
1972 cio_write(cio, tk->handler_type, 4);
1974 cio_write(cio, 0, 4);
1975 cio_write(cio, 0, 4);
1976 cio_write(cio, 0, 4); /* Reserved */
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);
1987 cio_write(cio, 0, 4);
1988 cio_write(cio, 0, 4);
1989 cio_write(cio, 0, 4); /* Reserved */
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);
1997 cio_write(cio, 0, 4);
1998 cio_write(cio, 0, 4);
1999 cio_write(cio, 0, 4); /* Reserved */
2001 cio_write(cio, 0x48696E74, 4);
2002 cio_write(cio, 0, 2); /* String: Hint */
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);
2014 * Handler reference box
2017 int mj2_read_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
2039 cio_skip(cio,4); /* Reserved */
2041 tk->handler_type = cio_read(cio, 4);
2042 cio_skip(cio,12); /* Reserved */
2044 tk->name_size = box.length - 32;
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 */
2051 if (cio_tell(cio) - box.init_pos != box.length) {
2052 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HDLR Box size\n");
2059 * Write the MDHD box
2064 void mj2_write_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2069 unsigned int modification_time;
2071 box.init_pos = cio_tell(cio);
2073 cio_write(cio, MJ2_MDHD, 4); /* MDHD */
2075 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2077 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2079 time(<ime); /* Time since 1/1/70 */
2080 modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2082 cio_write(cio, modification_time, 4); /* Modification Time */
2084 cio_write(cio, tk->timescale, 4); /* Timescale */
2088 for (i = 0; i < tk->num_samples; i++)
2089 tk->duration += tk->sample[i].sample_delta;
2091 cio_write(cio, tk->duration, 4); /* Duration */
2093 cio_write(cio, tk->language, 2); /* Language */
2095 cio_write(cio, 0, 2); /* Predefined */
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);
2109 int mj2_read_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
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");
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");
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");
2130 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2132 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2134 tk->timescale = cio_read(cio, 4); /* Timescale */
2136 tk->duration = cio_read(cio, 4); /* Duration */
2138 tk->language = cio_read(cio, 2); /* Language */
2140 cio_skip(cio,2); /* Predefined */
2142 if (cio_tell(cio) - box.init_pos != box.length) {
2143 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDHD Box size\n");
2150 * Write the MDIA box
2155 void mj2_write_mdia(mj2_tk_t * tk, opj_cio_t *cio)
2159 box.init_pos = cio_tell(cio);
2161 cio_write(cio, MJ2_MDIA, 4); /* MDIA */
2163 mj2_write_mdhd(tk, cio);
2164 mj2_write_hdlr(tk, cio);
2165 mj2_write_minf(tk, cio);
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);
2179 int mj2_read_mdia(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
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");
2189 if (mj2_read_mdhd(tk, cio))
2191 if (mj2_read_hdlr(tk, cio))
2193 if (mj2_read_minf(tk, img, cio))
2196 if (cio_tell(cio) - box.init_pos != box.length) {
2197 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDIA Box size\n");
2204 * Write the TKHD box
2209 void mj2_write_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2215 box.init_pos = cio_tell(cio);
2218 cio_write(cio, MJ2_TKHD, 4); /* TKHD */
2220 cio_write(cio, 3, 4); /* Version=0, flags=3 */
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 */
2225 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2227 cio_write(cio, tk->modification_time, 4); /* Modification Time */
2229 cio_write(cio, tk->track_ID, 4); /* Track ID */
2231 cio_write(cio, 0, 4); /* Reserved */
2235 for (i = 0; i < tk->num_samples; i++)
2236 tk->duration += tk->sample[i].sample_delta;
2238 cio_write(cio, tk->duration, 4); /* Duration */
2240 cio_write(cio, 0, 4); /* Reserved */
2241 cio_write(cio, 0, 4); /* Reserved */
2243 cio_write(cio, tk->layer, 2); /* Layer */
2245 cio_write(cio, 0, 2); /* Predefined */
2247 cio_write(cio, tk->volume, 2); /* Volume */
2249 cio_write(cio, 0, 2); /* Reserved */
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);
2261 cio_write(cio, tk->visual_w, 4); /* Video Visual Width */
2263 cio_write(cio, tk->visual_h, 4); /* Video Visual Height */
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);
2277 int mj2_read_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2283 mj2_read_boxhdr(&box, cio);
2285 if (MJ2_TKHD != box.type) {
2286 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TKHD Marker\n");
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");
2295 flag = cio_read(cio, 3);
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");
2303 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2305 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2307 tk->track_ID = cio_read(cio, 4); /* Track ID */
2309 cio_skip(cio,4); /* Reserved */
2311 tk->duration = cio_read(cio, 4); /* Duration */
2313 cio_skip(cio,8); /* Reserved */
2315 tk->layer = cio_read(cio, 2); /* Layer */
2317 cio_read(cio, 2); /* Predefined */
2319 tk->volume = cio_read(cio, 2); /* Volume */
2321 cio_skip(cio,2); /* Reserved */
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);
2333 tk->visual_w = cio_read(cio, 4); /* Video Visual Width */
2335 tk->visual_h = cio_read(cio, 4); /* Video Visual Height */
2337 if (cio_tell(cio) - box.init_pos != box.length) {
2338 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TKHD Box size\n");
2345 * Write the TRAK box
2350 void mj2_write_trak(mj2_tk_t * tk, opj_cio_t *cio)
2354 box.init_pos = cio_tell(cio);
2357 cio_write(cio, MJ2_TRAK, 4); /* TRAK */
2359 mj2_write_tkhd(tk, cio);
2360 mj2_write_mdia(tk, cio);
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);
2374 int mj2_read_trak(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
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");
2383 if (mj2_read_tkhd(tk, cio))
2385 if (mj2_read_mdia(tk, img, cio))
2387 if (cio_tell(cio) - box.init_pos != box.length) {
2388 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TRAK Box\n");
2395 * Write the MVHD box
2400 void mj2_write_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2408 box.init_pos = cio_tell(cio);
2410 cio_write(cio, MJ2_MVHD, 4); /* MVHD */
2412 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
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 */
2417 cio_write(cio, movie->creation_time, 4); /* Creation Time */
2419 cio_write(cio, movie->modification_time, 4); /* Modification Time */
2421 cio_write(cio, movie->timescale, 4); /* Timescale */
2423 movie->duration = 0;
2425 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2426 mj2_tk_t *tk = &movie->tk[i];
2428 for (j = 0; j < tk->num_samples; j++) {
2429 movie->duration += tk->sample[j].sample_delta;
2433 cio_write(cio, movie->duration, 4);
2435 cio_write(cio, movie->rate, 4); /* Rate to play presentation */
2437 cio_write(cio, movie->volume, 2); /* Volume */
2439 cio_write(cio, 0, 2); /* Reserved */
2440 cio_write(cio, 0, 4); /* Reserved */
2441 cio_write(cio, 0, 4); /* Reserved */
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);
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 */
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;
2466 movie->next_tk_id = max_tk_num + 1;
2468 cio_write(cio, movie->next_tk_id, 4); /* ID of Next track to be added */
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);
2482 int mj2_read_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
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");
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");
2497 movie->creation_time = cio_read(cio, 4); /* Creation Time */
2499 movie->modification_time = cio_read(cio, 4); /* Modification Time */
2501 movie->timescale = cio_read(cio, 4); /* Timescale */
2503 movie->duration = cio_read(cio, 4); /* Duration */
2505 movie->rate = cio_read(cio, 4); /* Rate to play presentation */
2507 movie->volume = cio_read(cio, 2); /* Volume */
2509 cio_skip(cio,10); /* Reserved */
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);
2521 cio_skip(cio,24); /* Pre-defined */
2523 movie->next_tk_id = cio_read(cio, 4); /* ID of Next track to be added */
2525 if (cio_tell(cio) - box.init_pos != box.length) {
2526 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MVHD Box Size\n");
2534 * Write the MOOV box
2539 void OPJ_CALLCONV mj2_write_moov(opj_mj2_t * movie, opj_cio_t *cio)
2544 box.init_pos = cio_tell(cio);
2546 cio_write(cio, MJ2_MOOV, 4); /* MOOV */
2548 mj2_write_mvhd(movie, cio);
2550 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2551 mj2_write_trak(&movie->tk[i], cio);
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);
2566 int mj2_read_moov(opj_mj2_t * movie, opj_image_t * img, opj_cio_t *cio)
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");
2578 if (mj2_read_mvhd(movie, cio))
2581 movie->tk = (mj2_tk_t*) opj_malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
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))
2592 if (tk->track_type == 0) {
2594 } else if (tk->track_type == 1) {
2596 } else if (tk->track_type == 2) {
2599 } else if (box2.type == MJ2_MVEX) {
2600 cio_seek(cio, box2.init_pos);
2601 cio_skip(cio,box2.length);
2604 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2611 int OPJ_CALLCONV mj2_read_struct(FILE *file, opj_mj2_t *movie) {
2614 unsigned char * src;
2619 /* open a byte stream for reading */
2620 src = (unsigned char*) opj_malloc(300 * sizeof(unsigned char));
2622 /* Assuming that jp and ftyp markers size do
2623 not exceed 300 bytes */
2624 fread(src,300,1, file);
2626 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2628 if (mj2_read_jp(cio))
2630 if (mj2_read_ftyp(movie, cio))
2633 fsresult = fseek(file,cio_tell(cio),SEEK_SET);
2635 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read data after FTYP box\n" );
2639 foffset = cio_tell(cio);
2643 fread(src,30,1,file);
2644 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2645 mj2_read_boxhdr(&box, cio);
2647 while(box.type != MJ2_MOOV) {
2652 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2654 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MDAT box\n" );
2657 foffset += box.length;
2661 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2663 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOF box\n" );
2666 foffset += box.length;
2669 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2671 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read FREE box\n" );
2674 foffset += box.length;
2677 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2679 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read SKIP box\n" );
2682 foffset += box.length;
2685 opj_event_msg(cio->cinfo, EVT_ERROR, "Unknown box in MJ2 stream\n");
2686 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2688 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read end of unknown box\n");
2691 foffset += box.length;
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");
2699 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 8);
2700 mj2_read_boxhdr(&box, cio);
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");
2711 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, box.length);
2713 if (mj2_read_moov(movie, &img, cio))
2720 /* ----------------------------------------------------------------------- */
2721 /* MJ2 decoder interface */
2722 /* ----------------------------------------------------------------------- */
2724 opj_dinfo_t* OPJ_CALLCONV mj2_create_decompress() {
2726 opj_dinfo_t *dinfo = (opj_dinfo_t*) opj_calloc(1, sizeof(opj_dinfo_t));
2727 if(!dinfo) return NULL;
2729 dinfo->is_decompressor = OPJ_TRUE;
2731 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2732 dinfo->mj2_handle = mj2;
2734 mj2->cinfo = (opj_common_ptr)dinfo;
2736 mj2->j2k = j2k_create_decompress((opj_common_ptr)dinfo);
2737 dinfo->j2k_handle = mj2->j2k;
2742 void OPJ_CALLCONV mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters) {
2747 /* setup the J2K decoder parameters */
2748 j2k_setup_decoder((opj_j2k_t*)movie->cinfo->j2k_handle,
2749 &mj2_parameters->j2k_parameters);
2753 void OPJ_CALLCONV mj2_destroy_decompress(opj_mj2_t *movie) {
2758 if (movie->cinfo->j2k_handle)
2759 j2k_destroy_compress(movie->j2k);
2761 if (movie->num_cl != 0)
2762 opj_free(movie->cl);
2764 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2766 if (tk->name_size != 0)
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);
2777 if (tk->num_url != 0)
2779 if (tk->num_urn != 0)
2781 if (tk->num_br != 0)
2783 if (tk->num_tts != 0)
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);
2793 opj_free(movie->tk);
2798 /* ----------------------------------------------------------------------- */
2799 /* MJ2 encoder interface */
2800 /* ----------------------------------------------------------------------- */
2802 opj_cinfo_t* OPJ_CALLCONV mj2_create_compress() {
2804 opj_cinfo_t *cinfo = (opj_cinfo_t*) opj_calloc(1, sizeof(opj_cinfo_t));
2805 if(!cinfo) return NULL;
2807 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2808 cinfo->mj2_handle = mj2;
2810 mj2->cinfo = (opj_common_ptr)cinfo;
2813 mj2->j2k = j2k_create_compress(mj2->cinfo);
2814 cinfo->j2k_handle = mj2->j2k;
2819 void OPJ_CALLCONV mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters) {
2820 if(movie && parameters) {
2821 opj_jp2_t *jp2_struct;
2823 movie->num_htk = 0; /* No hint tracks*/
2824 movie->num_stk = 0; /* No sound tracks*/
2825 movie->num_vtk = 1; /* One video track*/
2827 movie->brand = MJ2_MJ2; /* One brand: MJ2*/
2828 movie->num_cl = 2; /* Two compatible brands: MJ2 and MJ2S*/
2829 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
2830 movie->cl[0] = MJ2_MJ2;
2831 movie->cl[1] = MJ2_MJ2S;
2832 movie->minversion = 0; /* Minimum version: 0 */
2834 movie->tk = (mj2_tk_t*) opj_malloc(sizeof(mj2_tk_t)); /*Memory allocation for the video track*/
2835 movie->tk[0].track_ID = 1; /* Track ID = 1 */
2836 movie->tk[0].track_type = 0; /* Video track */
2837 movie->tk[0].Dim[0] = parameters->Dim[0];
2838 movie->tk[0].Dim[1] = parameters->Dim[1];
2839 movie->tk[0].w = parameters->w;
2840 movie->tk[0].h = parameters->h;
2841 movie->tk[0].CbCr_subsampling_dx = parameters->CbCr_subsampling_dx;
2842 movie->tk[0].CbCr_subsampling_dy = parameters->CbCr_subsampling_dy;
2843 movie->tk[0].sample_rate = parameters->frame_rate;
2844 movie->tk[0].name_size = 0;
2845 movie->tk[0].chunk = (mj2_chunk_t*) opj_malloc(sizeof(mj2_chunk_t));
2846 movie->tk[0].sample = (mj2_sample_t*) opj_malloc(sizeof(mj2_sample_t));
2847 movie->tk[0].depth = parameters->prec;
2849 jp2_struct = &movie->tk[0].jp2_struct;
2850 jp2_struct->numcomps = parameters->numcomps; /* NC */
2851 jp2_struct->comps = (opj_jp2_comps_t*) opj_malloc(jp2_struct->numcomps * sizeof(opj_jp2_comps_t));
2852 jp2_struct->precedence = 0; /* PRECEDENCE*/
2853 jp2_struct->approx = 0; /* APPROX*/
2854 jp2_struct->brand = JP2_JP2; /* BR */
2855 jp2_struct->minversion = 0; /* MinV */
2856 jp2_struct->numcl = 1;
2857 jp2_struct->cl = (unsigned int*) opj_malloc(jp2_struct->numcl * sizeof(unsigned int));
2858 jp2_struct->cl[0] = JP2_JP2; /* CL0 : JP2 */
2859 jp2_struct->C = 7; /* C : Always 7*/
2860 jp2_struct->UnkC = 0; /* UnkC, colorspace specified in colr box*/
2861 jp2_struct->IPR = 0; /* IPR, no intellectual property*/
2862 jp2_struct->w = parameters->w;
2863 jp2_struct->h = parameters->h;
2864 jp2_struct->bpc = 7;
2865 jp2_struct->meth = parameters->meth;
2866 jp2_struct->enumcs = parameters->enumcs;
2870 void OPJ_CALLCONV mj2_destroy_compress(opj_mj2_t *movie) {
2875 if (movie->cinfo->j2k_handle) {
2876 j2k_destroy_compress(movie->j2k);
2879 if (movie->num_cl != 0)
2880 opj_free(movie->cl);
2882 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2884 if (tk->name_size != 0)
2886 if (tk->track_type == 0) {/* Video track*/
2887 if (tk->jp2_struct.comps != NULL)
2888 opj_free(tk->jp2_struct.comps);
2889 if (tk->jp2_struct.cl != NULL)
2890 opj_free(tk->jp2_struct.cl);
2891 if (tk->num_jp2x != 0)
2892 opj_free(tk->jp2xdata);
2895 if (tk->num_url != 0)
2897 if (tk->num_urn != 0)
2899 if (tk->num_br != 0)
2901 if (tk->num_tts != 0)
2903 if (tk->num_chunks != 0)
2904 opj_free(tk->chunk);
2905 if (tk->num_samplestochunk != 0)
2906 opj_free(tk->sampletochunk);
2907 if (tk->num_samples != 0)
2908 opj_free(tk->sample);
2911 opj_free(movie->tk);