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 */
40 @param cinfo Codec context info
41 @param cio Input stream
43 @return Returns true if successful, returns false otherwise
45 static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box);
53 int mj2_read_boxhdr(mj2_box_t * box, opj_cio_t *cio)
55 box->init_pos = cio_tell(cio);
56 box->length = cio_read(cio, 4);
57 box->type = cio_read(cio, 4);
58 if (box->length == 1) {
59 if (cio_read(cio, 4) != 0) {
60 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Cannot handle box sizes higher than 2^32\n");
63 box->length = cio_read(cio, 4);
65 box->length = cio_numbytesleft(cio) + 12;
67 else if (box->length == 0) {
68 box->length = cio_numbytesleft(cio) + 8;
75 * Initialisation of a Standard Movie, given a simple movie structure defined by the user
76 * The movie will have one sample per chunk
78 * Arguments: opj_mj2_t * movie
79 * Several variables of "movie" must be defined in order to enable a correct execution of
81 * - The number of tracks of each type (movie->num_vtk, movie->num_stk, movie->num_htk)
82 * - The memory for each must be allocated (movie->tk)
84 * The track type (tk->track_type)
85 * The number of sample (tk->num_samples)
86 * The sample rate (tk->sample_rate)
90 int mj2_init_stdmovie(opj_mj2_t * movie)
96 movie->brand = MJ2_MJ2;
97 movie->minversion = 0;
100 (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
102 movie->cl[0] = MJ2_MJ2;
103 movie->cl[1] = MJ2_MJ2S;
104 time(<ime); /* Time since 1/1/70 */
105 movie->creation_time = (unsigned int) ltime + 2082844800; /* Seconds between 1/1/04 and 1/1/70 */
106 movie->timescale = 1000;
108 movie->rate = 1 << 16; /* Rate to play presentation (default = 0x00010000) */
109 movie->volume = 1 << 8; /* Movie volume (default = 0x0100) */
110 movie->trans_matrix[0] = 0x00010000; /* Transformation matrix for video */
111 movie->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
112 movie->trans_matrix[2] = 0;
113 movie->trans_matrix[3] = 0;
114 movie->trans_matrix[4] = 0x00010000;
115 movie->trans_matrix[5] = 0;
116 movie->trans_matrix[6] = 0;
117 movie->trans_matrix[7] = 0;
118 movie->trans_matrix[8] = 0x40000000;
119 movie->next_tk_id = 1;
121 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
122 mj2_tk_t *tk = &movie->tk[i];
124 tk->jp2_struct.comps = NULL;
125 tk->jp2_struct.cl = NULL;
127 if (tk->track_type == 0) {
128 if (tk->num_samples == 0)
134 tk->timescale = 1000; /* Timescale = 1 ms */
136 tk->chunk[0].num_samples = 1;
137 tk->chunk[0].sample_descr_idx = 1;
139 tk->same_sample_size = 0;
141 tk->num_samplestochunk = 1; /* One sample per chunk */
143 (mj2_sampletochunk_t *) malloc(tk->num_samplestochunk *
144 sizeof(mj2_sampletochunk_t));
145 tk->sampletochunk[0].first_chunk = 1;
146 tk->sampletochunk[0].samples_per_chunk = 1;
147 tk->sampletochunk[0].sample_descr_idx = 1;
149 if (tk->sample_rate == 0) {
150 opj_event_msg(tk->cinfo, EVT_ERROR,
151 "Error while initializing MJ2 movie: Sample rate of track %d must be different from zero\n",
156 for (j = 0; j < tk->num_samples; j++) {
157 tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
161 tk->tts = (mj2_tts_t *) malloc(tk->num_tts * sizeof(mj2_tts_t));
162 tk->tts[0].sample_count = tk->num_samples;
163 tk->tts[0].sample_delta = tk->timescale / tk->sample_rate;
165 tk->horizresolution = 0x00480000; /* Horizontal resolution (typically 72) */
166 tk->vertresolution = 0x00480000; /* Vertical resolution (typically 72) */
167 tk->compressorname[0] = 0x0f4d6f74; /* Compressor Name[]: Motion JPEG2000 */
168 tk->compressorname[1] = 0x696f6e20;
169 tk->compressorname[2] = 0x4a504547;
170 tk->compressorname[3] = 0x32303030;
171 tk->compressorname[4] = 0x00120000;
172 tk->compressorname[5] = 0;
173 tk->compressorname[6] = 0x00000042;
174 tk->compressorname[7] = 0x000000DC;
175 tk->num_url = 0; /* Number of URL */
176 tk->num_urn = 0; /* Number of URN */
177 tk->graphicsmode = 0; /* Graphicsmode */
178 tk->opcolor[0] = 0; /* OpColor */
179 tk->opcolor[1] = 0; /* OpColor */
180 tk->opcolor[2] = 0; /* OpColor */
181 tk->creation_time = movie->creation_time; /* Seconds between 1/1/04 and 1/1/70 */
182 tk->language = 0; /* Language (undefined) */
184 tk->volume = 1 << 8; /* Movie volume (default = 0x0100) */
185 tk->trans_matrix[0] = 0x00010000; /* Transformation matrix for track */
186 tk->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
187 tk->trans_matrix[2] = 0;
188 tk->trans_matrix[3] = 0;
189 tk->trans_matrix[4] = 0x00010000;
190 tk->trans_matrix[5] = 0;
191 tk->trans_matrix[6] = 0;
192 tk->trans_matrix[7] = 0;
193 tk->trans_matrix[8] = 0x40000000;
196 tk->or_fieldcount = 1;
197 tk->or_fieldorder = 0;
199 tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
201 tk->br[1] = MJ2_J2P0;
203 tk->hsub = 2; /* 4:2:0 */
204 tk->vsub = 2; /* 4:2:0 */
207 tk->visual_w = tk->w << 16;
208 tk->visual_h = tk->h << 16;
219 * Time To Sample box Decompact
222 void mj2_tts_decompact(mj2_tk_t * tk)
226 for (i = 0; i < tk->num_tts; i++) {
227 tk->num_samples += tk->tts[i].sample_count;
231 (mj2_sample_t *) malloc(tk->num_samples * sizeof(mj2_sample_t));
233 for (i = 0; i < tk->num_tts; i++) {
234 for (j = 0; j < tk->tts[i].sample_count; j++) {
235 tk->sample[j].sample_delta = tk->tts[i].sample_delta;
241 * Sample To Chunk box Decompact
244 void mj2_stsc_decompact(mj2_tk_t * tk)
250 if (tk->num_samplestochunk == 1) {
252 (unsigned int) ceil((double) tk->num_samples /
253 (double) tk->sampletochunk[0].samples_per_chunk);
255 (mj2_chunk_t *) malloc(tk->num_chunks * sizeof(mj2_chunk_t));
256 for (k = 0; k < tk->num_chunks; k++) {
257 tk->chunk[k].num_samples = tk->sampletochunk[0].samples_per_chunk;
262 (mj2_chunk_t *) malloc(tk->num_samples * sizeof(mj2_chunk_t));
264 for (i = 0; i < tk->num_samplestochunk -1 ; i++) {
265 for (j = tk->sampletochunk[i].first_chunk - 1;
266 j < tk->sampletochunk[i + 1].first_chunk - 1; j++) {
267 tk->chunk[j].num_samples = tk->sampletochunk[i].samples_per_chunk;
269 sampleno += tk->chunk[j].num_samples;
272 tk->num_chunks += (int)(tk->num_samples - sampleno) / tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
273 for (k = tk->sampletochunk[tk->num_samplestochunk - 1].first_chunk - 1;
274 k < tk->num_chunks; k++) {
275 tk->chunk[k].num_samples =
276 tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
278 tk->chunk = realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
285 * Chunk offset box Decompact
288 void mj2_stco_decompact(mj2_tk_t * tk)
293 int intra_chunk_offset;
295 for (i = 0; i < tk->num_chunks; i++) {
296 intra_chunk_offset = 0;
297 for (j = 0; j < tk->chunk[i].num_samples; j++) {
298 tk->sample[k].offset = intra_chunk_offset + tk->chunk[i].offset;
299 intra_chunk_offset += tk->sample[k].sample_size;
311 void mj2_write_jp(opj_cio_t *cio)
314 box.init_pos = cio_tell(cio);
317 cio_write(cio, MJ2_JP, 4); /* JP */
318 cio_write(cio, 0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
320 box.length = cio_tell(cio) - box.init_pos;
321 cio_seek(cio, box.init_pos);
322 cio_write(cio, box.length, 4);
323 cio_seek(cio, box.init_pos + box.length);
329 * JPEG 2000 signature
332 int mj2_read_jp(opj_cio_t *cio)
336 mj2_read_boxhdr(&box, cio);
337 if (MJ2_JP != box.type) { /* Check Marker */
338 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP Marker\n");
341 if (0x0d0a870a != cio_read(cio, 4)) { /* read the 0x0d0a870a required in a JP box */
342 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Marker\n");
345 if (cio_tell(cio) - box.init_pos != box.length) { /* Check box length */
346 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Box size \n");
359 void mj2_write_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
363 box.init_pos = cio_tell(cio);
366 cio_write(cio, MJ2_FTYP, 4); /* FTYP */
367 cio_write(cio, movie->brand, 4); /* BR */
368 cio_write(cio, movie->minversion, 4); /* MinV */
370 for (i = 0; i < movie->num_cl; i++)
371 cio_write(cio, movie->cl[i], 4); /* CL */
373 box.length = cio_tell(cio) - box.init_pos;
374 cio_seek(cio, box.init_pos);
375 cio_write(cio, box.length, 4); /* Length */
376 cio_seek(cio, box.init_pos + box.length);
385 int mj2_read_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
390 mj2_read_boxhdr(&box, cio); /* Box Size */
391 if (MJ2_FTYP != box.type) {
392 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FTYP Marker\n");
396 movie->brand = cio_read(cio, 4); /* BR */
397 movie->minversion = cio_read(cio, 4); /* MinV */
398 movie->num_cl = (box.length - 16) / 4;
400 (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
402 for (i = movie->num_cl - 1; i > -1; i--)
403 movie->cl[i] = cio_read(cio, 4); /* CLi */
405 if (cio_tell(cio) - box.init_pos != box.length) {
406 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FTYP Box\n");
419 void mj2_write_stco(mj2_tk_t * tk, opj_cio_t *cio)
424 box.init_pos = cio_tell(cio);
426 cio_write(cio, MJ2_STCO, 4); /* STCO */
428 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
430 cio_write(cio, tk->num_chunks, 4); /* Entry Count */
432 for (i = 0; i < tk->num_chunks; i++) {
433 cio_write(cio, tk->chunk[i].offset, 4); /* Entry offset */
436 box.length = cio_tell(cio) - box.init_pos;
437 cio_seek(cio, box.init_pos);
438 cio_write(cio, box.length, 4); /* L */
439 cio_seek(cio, box.init_pos + box.length);
448 int mj2_read_stco(mj2_tk_t * tk, opj_cio_t *cio)
453 mj2_read_boxhdr(&box, cio); /* Box Size */
454 if (MJ2_STCO != box.type) {
455 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STCO Marker\n");
459 if (0 != cio_read(cio, 1)) { /* Version = 0 */
460 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STCO box\n");
464 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
465 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STCO box. Expected flag 0\n");
470 if (cio_read(cio, 4) != tk->num_chunks) {
471 opj_event_msg(cio->cinfo, EVT_ERROR,
472 "Error in STCO box: expecting same amount of entry-count as chunks \n");
474 for (i = 0; i < tk->num_chunks; i++) {
475 tk->chunk[i].offset = cio_read(cio, 4); /* Entry offset */
479 mj2_stco_decompact(tk);
482 if (cio_tell(cio) - box.init_pos != box.length) {
483 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STCO Box size\n");
495 void mj2_write_stsz(mj2_tk_t * tk, opj_cio_t *cio)
500 box.init_pos = cio_tell(cio);
502 cio_write(cio, MJ2_STSZ, 4); /* STSZ */
504 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
506 if (tk->same_sample_size == 1) { /* If they all have the same size */
507 cio_write(cio, tk->sample[0].sample_size, 4); /* Size */
509 cio_write(cio, 1, 4); /* Entry count = 1 */
513 cio_write(cio, 0, 4); /* Sample Size = 0 becase they all have different sizes */
515 cio_write(cio, tk->num_samples, 4); /* Sample Count */
517 for (i = 0; i < tk->num_samples; i++) {
518 cio_write(cio, tk->sample[i].sample_size, 4);
522 box.length = cio_tell(cio) - box.init_pos;
523 cio_seek(cio, box.init_pos);
524 cio_write(cio, box.length, 4); /* L */
525 cio_seek(cio, box.init_pos + box.length);
534 int mj2_read_stsz(mj2_tk_t * tk, opj_cio_t *cio)
540 mj2_read_boxhdr(&box, cio); /* Box Size */
541 if (MJ2_STSZ != box.type) {
542 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSZ Marker\n");
547 if (0 != cio_read(cio, 1)) { /* Version = 0 */
548 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSZ box\n");
552 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
553 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSZ box. Expected flag 0\n");
557 sample_size = cio_read(cio, 4);
559 if (sample_size != 0) { /* Samples do have the same size */
560 tk->same_sample_size = 1;
561 for (i = 0; i < tk->num_samples; i++) {
562 tk->sample[i].sample_size = sample_size;
564 cio_skip(cio,4); /* Sample count = 1 */
566 tk->same_sample_size = 0;
567 if (tk->num_samples != cio_read(cio, 4)) { /* Sample count */
568 opj_event_msg(cio->cinfo, EVT_ERROR,
569 "Error in STSZ box. Expected that sample-count is number of samples in track\n");
572 for (i = 0; i < tk->num_samples; i++) {
573 tk->sample[i].sample_size = cio_read(cio, 4); /* Sample Size */
576 if (cio_tell(cio) - box.init_pos != box.length) {
577 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSZ Box size\n");
591 void mj2_write_stsc(mj2_tk_t * tk, opj_cio_t *cio)
596 box.init_pos = cio_tell(cio);
598 cio_write(cio, MJ2_STSC, 4); /* STSC */
600 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
602 cio_write(cio, tk->num_samplestochunk, 4); /* Entry Count */
604 for (i = 0; i < tk->num_samplestochunk; i++) {
605 cio_write(cio, tk->sampletochunk[i].first_chunk, 4); /* First Chunk */
606 cio_write(cio, tk->sampletochunk[i].samples_per_chunk, 4); /* Samples per chunk */
607 cio_write(cio, tk->sampletochunk[i].sample_descr_idx, 4); /* Samples description index */
611 box.length = cio_tell(cio) - box.init_pos;
612 cio_seek(cio, box.init_pos);
613 cio_write(cio, box.length, 4); /* L */
614 cio_seek(cio, box.init_pos + box.length);
623 int mj2_read_stsc(mj2_tk_t * tk, opj_cio_t *cio)
628 mj2_read_boxhdr(&box, cio); /* Box Size */
629 if (MJ2_STSC != box.type) {
630 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSC Marker\n");
635 if (0 != cio_read(cio, 1)) { /* Version = 0 */
636 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSC box\n");
640 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
641 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSC box. Expected flag 0\n");
645 tk->num_samplestochunk = cio_read(cio, 4);
648 (mj2_sampletochunk_t *) malloc(tk->num_samplestochunk *
649 sizeof(mj2_sampletochunk_t));
652 for (i = 0; i < tk->num_samplestochunk; i++) {
653 tk->sampletochunk[i].first_chunk = cio_read(cio, 4);
654 tk->sampletochunk[i].samples_per_chunk = cio_read(cio, 4);
655 tk->sampletochunk[i].sample_descr_idx = cio_read(cio, 4);
658 mj2_stsc_decompact(tk); /* decompact sample to chunk box */
661 if (cio_tell(cio) - box.init_pos != box.length) {
662 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSC Box size\n");
674 void mj2_write_stts(mj2_tk_t * tk, opj_cio_t *cio)
680 box.init_pos = cio_tell(cio);
682 cio_write(cio, MJ2_STTS, 4); /* STTS */
684 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
686 cio_write(cio, tk->num_tts, 4); /* entry_count */
687 for (i = 0; i < tk->num_tts; i++) {
688 cio_write(cio, tk->tts[i].sample_count, 4); /* Sample-count */
689 cio_write(cio, tk->tts[i].sample_delta, 4); /* Sample-Delta */
692 box.length = cio_tell(cio) - box.init_pos;
693 cio_seek(cio, box.init_pos);
694 cio_write(cio, box.length, 4); /* L */
695 cio_seek(cio, box.init_pos + box.length);
704 int mj2_read_stts(mj2_tk_t * tk, opj_cio_t *cio)
710 mj2_read_boxhdr(&box, cio);
711 if (MJ2_STTS != box.type) {
712 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STTS Marker\n");
717 if (0 != cio_read(cio, 1)) { /* Version = 0 */
718 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STTS box\n");
722 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
723 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STTS box. Expected flag 0\n");
727 tk->num_tts = cio_read(cio, 4);
729 tk->tts = (mj2_tts_t *) malloc(tk->num_tts * sizeof(mj2_tts_t));
731 for (i = 0; i < tk->num_tts; i++) {
732 tk->tts[i].sample_count = cio_read(cio, 4);
733 tk->tts[i].sample_delta = cio_read(cio, 4);
736 mj2_tts_decompact(tk);
738 if (cio_tell(cio) - box.init_pos != box.length) {
739 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STTS Box size\n");
751 void mj2_write_fiel(mj2_tk_t * tk, opj_cio_t *cio)
756 box.init_pos = cio_tell(cio);
758 cio_write(cio, MJ2_FIEL, 4); /* STTS */
760 cio_write(cio, tk->fieldcount, 1); /* Field count */
761 cio_write(cio, tk->fieldorder, 1); /* Field order */
764 box.length = cio_tell(cio) - box.init_pos;
765 cio_seek(cio, box.init_pos);
766 cio_write(cio, box.length, 4); /* L */
767 cio_seek(cio, box.init_pos + box.length);
776 int mj2_read_fiel(mj2_tk_t * tk, opj_cio_t *cio)
781 mj2_read_boxhdr(&box, cio);
782 if (MJ2_FIEL != box.type) {
783 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FIEL Marker\n");
788 tk->fieldcount = cio_read(cio, 1);
789 tk->fieldorder = cio_read(cio, 1);
791 if (cio_tell(cio) - box.init_pos != box.length) {
792 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FIEL Box size\n");
801 * Original Format Box
804 void mj2_write_orfo(mj2_tk_t * tk, opj_cio_t *cio)
808 box.init_pos = cio_tell(cio);
810 cio_write(cio, MJ2_ORFO, 4);
812 cio_write(cio, tk->or_fieldcount, 1); /* Original Field count */
813 cio_write(cio, tk->or_fieldorder, 1); /* Original Field order */
816 box.length = cio_tell(cio) - box.init_pos;
817 cio_seek(cio, box.init_pos);
818 cio_write(cio, box.length, 4); /* L */
819 cio_seek(cio, box.init_pos + box.length);
825 * Original Format Box
828 int mj2_read_orfo(mj2_tk_t * tk, opj_cio_t *cio)
833 mj2_read_boxhdr(&box, cio);
834 if (MJ2_ORFO != box.type) {
835 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected ORFO Marker\n");
840 tk->or_fieldcount = cio_read(cio, 1);
841 tk->or_fieldorder = cio_read(cio, 1);
843 if (cio_tell(cio) - box.init_pos != box.length) {
844 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with ORFO Box size\n");
856 void mj2_write_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
862 box.init_pos = cio_tell(cio);
864 cio_write(cio, MJ2_JP2P, 4);
866 cio_write(cio, 0, 4); /* Version 0, flags =0 */
868 for (i = 0; i < tk->num_br; i++) {
869 cio_write(cio, tk->br[i], 4);
872 box.length = cio_tell(cio) - box.init_pos;
873 cio_seek(cio, box.init_pos);
874 cio_write(cio, box.length, 4); /* L */
875 cio_seek(cio, box.init_pos + box.length);
884 int mj2_read_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
890 mj2_read_boxhdr(&box, cio);
891 if (MJ2_JP2P != box.type) {
892 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2P Marker\n");
896 if (0 != cio_read(cio, 1)) { /* Version = 0 */
897 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in JP2P box\n");
901 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
902 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in JP2P box. Expected flag 0\n");
907 tk->num_br = (box.length - 12) / 4;
908 tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
910 for (i = 0; i < tk->num_br; i++) {
911 tk->br[i] = cio_read(cio, 4);
914 if (cio_tell(cio) - box.init_pos != box.length) {
915 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2P Box size\n");
927 void mj2_write_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
933 box.init_pos = cio_tell(cio);
935 cio_write(cio, MJ2_JP2X, 4);
937 for (i = 0; i < tk->num_jp2x; i++) {
938 cio_write(cio, tk->jp2xdata[i], 1);
941 box.length = cio_tell(cio) - box.init_pos;
942 cio_seek(cio, box.init_pos);
943 cio_write(cio, box.length, 4); /* L */
944 cio_seek(cio, box.init_pos + box.length);
953 int mj2_read_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
959 mj2_read_boxhdr(&box, cio);
960 if (MJ2_JP2X != box.type) {
961 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2X Marker\n");
966 tk->num_jp2x = (box.length - 8);
968 (unsigned char *) malloc(tk->num_jp2x * sizeof(unsigned char));
970 for (i = 0; i < tk->num_jp2x; i++) {
971 tk->jp2xdata[i] = cio_read(cio, 1);
974 if (cio_tell(cio) - box.init_pos != box.length) {
975 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2X Box size\n");
984 * MJP2 Subsampling Box
987 void mj2_write_jsub(mj2_tk_t * tk, opj_cio_t *cio)
992 box.init_pos = cio_tell(cio);
994 cio_write(cio, MJ2_JSUB, 4);
996 cio_write(cio, tk->hsub, 1);
997 cio_write(cio, tk->vsub, 1);
998 cio_write(cio, tk->hoff, 1);
999 cio_write(cio, tk->voff, 1);
1001 box.length = cio_tell(cio) - box.init_pos;
1002 cio_seek(cio, box.init_pos);
1003 cio_write(cio, box.length, 4); /* L */
1004 cio_seek(cio, box.init_pos + box.length);
1010 * MJP2 Subsampling Box
1013 int mj2_read_jsub(mj2_tk_t * tk, opj_cio_t *cio)
1017 mj2_read_boxhdr(&box, cio);
1018 if (MJ2_JSUB != box.type) {
1019 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JSUB Marker\n");
1023 tk->hsub = cio_read(cio, 1);
1024 tk->vsub = cio_read(cio, 1);
1025 tk->hoff = cio_read(cio, 1);;
1026 tk->voff = cio_read(cio, 1);
1028 if (cio_tell(cio) - box.init_pos != box.length) {
1029 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JSUB Box size\n");
1036 * Write the SMJ2 box
1038 * Visual Sample Entry Description
1041 void mj2_write_smj2(mj2_tk_t * tk, opj_cio_t *cio)
1045 box.init_pos = cio_tell(cio);
1047 cio_write(cio, MJ2_MJ2, 4); /* MJ2 */
1049 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1051 cio_write(cio, 1, 4);
1053 cio_write(cio, 0, 2); /* Pre-defined */
1055 cio_write(cio, 0, 2); /* Reserved */
1057 cio_write(cio, 0, 4); /* Pre-defined */
1058 cio_write(cio, 0, 4); /* Pre-defined */
1059 cio_write(cio, 0, 4); /* Pre-defined */
1061 cio_write(cio, tk->w, 2); /* Width */
1062 cio_write(cio, tk->h, 2); /* Height */
1064 cio_write(cio, tk->horizresolution, 4); /* Horizontal resolution */
1065 cio_write(cio, tk->vertresolution, 4); /* Vertical resolution */
1067 cio_write(cio, 0, 4); /* Reserved */
1069 cio_write(cio, 1, 2); /* Pre-defined = 1 */
1071 cio_write(cio, tk->compressorname[0], 4); /* Compressor Name */
1072 cio_write(cio, tk->compressorname[1], 4);
1073 cio_write(cio, tk->compressorname[2], 4);
1074 cio_write(cio, tk->compressorname[3], 4);
1075 cio_write(cio, tk->compressorname[4], 4);
1076 cio_write(cio, tk->compressorname[5], 4);
1077 cio_write(cio, tk->compressorname[6], 4);
1078 cio_write(cio, tk->compressorname[7], 4);
1080 cio_write(cio, tk->depth, 2); /* Depth */
1082 cio_write(cio, 0xffff, 2); /* Pre-defined = -1 */
1084 jp2_write_jp2h(&tk->jp2_struct, cio);
1086 mj2_write_fiel(tk, cio);
1088 if (tk->num_br != 0)
1089 mj2_write_jp2p(tk, cio);
1090 if (tk->num_jp2x != 0)
1091 mj2_write_jp2x(tk, cio);
1093 mj2_write_jsub(tk, cio);
1094 mj2_write_orfo(tk, cio);
1096 box.length = cio_tell(cio) - box.init_pos;
1097 cio_seek(cio, box.init_pos);
1098 cio_write(cio, box.length, 4); /* L */
1099 cio_seek(cio, box.init_pos + box.length);
1105 * Visual Sample Entry Description
1108 int mj2_read_smj2(opj_image_t * img, mj2_tk_t * tk, opj_cio_t *cio)
1114 mj2_read_boxhdr(&box, cio);
1116 if (MJ2_MJ2 != box.type) {
1117 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n");
1121 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1122 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MJP2 box\n");
1126 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1127 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MJP2 box. Expected flag 0\n");
1133 cio_skip(cio,2); /* Pre-defined */
1135 cio_skip(cio,2); /* Reserved */
1137 cio_skip(cio,4); /* Pre-defined */
1138 cio_skip(cio,4); /* Pre-defined */
1139 cio_skip(cio,4); /* Pre-defined */
1141 tk->w = cio_read(cio, 2); /* Width */
1142 tk->h = cio_read(cio, 2); /* Height */
1144 tk->horizresolution = cio_read(cio, 4); /* Horizontal resolution */
1145 tk->vertresolution = cio_read(cio, 4); /* Vertical resolution */
1147 cio_skip(cio,4); /* Reserved */
1149 cio_skip(cio,2); /* Pre-defined = 1 */
1151 tk->compressorname[0] = cio_read(cio, 4); /* Compressor Name */
1152 tk->compressorname[1] = cio_read(cio, 4);
1153 tk->compressorname[2] = cio_read(cio, 4);
1154 tk->compressorname[3] = cio_read(cio, 4);
1155 tk->compressorname[4] = cio_read(cio, 4);
1156 tk->compressorname[5] = cio_read(cio, 4);
1157 tk->compressorname[6] = cio_read(cio, 4);
1158 tk->compressorname[7] = cio_read(cio, 4);
1160 tk->depth = cio_read(cio, 2); /* Depth */
1162 /* Init std value */
1166 tk->or_fieldcount = 1;
1167 tk->or_fieldorder = 0;
1169 cio_skip(cio,2); /* Pre-defined = -1 */
1171 if (!jp2_read_jp2h(&tk->jp2_struct, cio)) {
1172 opj_event_msg(tk->cinfo, EVT_ERROR, "Error reading JP2H Box\n");
1176 tk->jp2_struct.comps = (opj_jp2_comps_t *) malloc(tk->jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
1177 tk->jp2_struct.cl = (int *) malloc(sizeof(int));
1182 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
1183 mj2_read_boxhdr(&box2, cio);
1184 cio_seek(cio, box2.init_pos);
1185 switch (box2.type) {
1187 if (mj2_read_fiel(tk, cio))
1192 if (mj2_read_jp2p(tk, cio))
1197 if (mj2_read_jp2x(tk, cio))
1202 if (mj2_read_jsub(tk, cio))
1207 if (mj2_read_orfo(tk, cio))
1212 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MJP2 Box size\n");
1223 * Write the STSD box
1225 * Sample Description
1228 void mj2_write_stsd(mj2_tk_t * tk, opj_cio_t *cio)
1232 box.init_pos = cio_tell(cio);
1234 cio_write(cio, MJ2_STSD, 4); /* STSD */
1236 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1238 cio_write(cio, 1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
1240 if (tk->track_type == 0) {
1241 mj2_write_smj2(tk, cio);
1242 } else if (tk->track_type == 1) {
1245 if (tk->track_type == 2) {
1250 box.length = cio_tell(cio) - box.init_pos;
1251 cio_seek(cio, box.init_pos);
1252 cio_write(cio, box.length, 4); /* L */
1253 cio_seek(cio, box.init_pos + box.length);
1259 * Sample Description
1262 int mj2_read_stsd(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1265 int entry_count, len_2skip;
1269 mj2_read_boxhdr(&box, cio);
1271 if (MJ2_STSD != box.type) {
1272 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSD Marker\n");
1276 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1277 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSD box\n");
1281 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1282 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSD box. Expected flag 0\n");
1286 entry_count = cio_read(cio, 4);
1288 if (tk->track_type == 0) {
1289 for (i = 0; i < entry_count; i++) {
1290 if (mj2_read_smj2(img, tk, cio))
1293 } else if (tk->track_type == 1) {
1294 len_2skip = cio_read(cio, 4); // Not implemented -> skipping box
1295 cio_skip(cio,len_2skip - 4);
1296 } else if (tk->track_type == 2) {
1297 len_2skip = cio_read(cio, 4); // Not implemented -> skipping box
1298 cio_skip(cio,len_2skip - 4);
1302 if (cio_tell(cio) - box.init_pos != box.length) {
1303 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSD Box size\n");
1310 * Write the STBL box
1312 * Sample table box box
1315 void mj2_write_stbl(mj2_tk_t * tk, opj_cio_t *cio)
1319 box.init_pos = cio_tell(cio);
1321 cio_write(cio, MJ2_STBL, 4); /* STBL */
1323 mj2_write_stsd(tk, cio);
1324 mj2_write_stts(tk, cio);
1325 mj2_write_stsc(tk, cio);
1326 mj2_write_stsz(tk, cio);
1327 mj2_write_stco(tk, cio);
1329 box.length = cio_tell(cio) - box.init_pos;
1330 cio_seek(cio, box.init_pos);
1331 cio_write(cio, box.length, 4); /* L */
1332 cio_seek(cio, box.init_pos + box.length);
1338 * Sample table box box
1341 int mj2_read_stbl(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1345 mj2_read_boxhdr(&box, cio);
1346 if (MJ2_STBL != box.type) {
1347 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STBL Marker\n");
1351 if (mj2_read_stsd(tk, img, cio))
1353 if (mj2_read_stts(tk, cio))
1355 if (mj2_read_stsc(tk, cio))
1357 if (mj2_read_stsz(tk, cio))
1359 if (mj2_read_stco(tk, cio))
1362 if (cio_tell(cio) - box.init_pos != box.length) {
1363 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STBL Box size\n");
1375 void mj2_write_url(mj2_tk_t * tk, int url_num, opj_cio_t *cio)
1379 box.init_pos = cio_tell(cio);
1381 cio_write(cio, MJ2_URL, 4); /* URL */
1384 cio_write(cio, 1, 4); /* Version = 0, flags = 1 because stored in same file */
1386 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1387 cio_write(cio, tk->url[url_num - 1].location[0], 4);
1388 cio_write(cio, tk->url[url_num - 1].location[1], 4);
1389 cio_write(cio, tk->url[url_num - 1].location[2], 4);
1390 cio_write(cio, tk->url[url_num - 1].location[3], 4);
1393 box.length = cio_tell(cio) - box.init_pos;
1394 cio_seek(cio, box.init_pos);
1395 cio_write(cio, box.length, 4); /* L */
1396 cio_seek(cio, box.init_pos + box.length);
1405 int mj2_read_url(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1409 mj2_read_boxhdr(&box, cio);
1410 if (MJ2_URL != box.type) {
1411 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URL Marker\n");
1415 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1416 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URL box\n");
1420 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1421 tk->url[urn_num].location[0] = cio_read(cio, 4);
1422 tk->url[urn_num].location[1] = cio_read(cio, 4);
1423 tk->url[urn_num].location[2] = cio_read(cio, 4);
1424 tk->url[urn_num].location[3] = cio_read(cio, 4);
1430 if (cio_tell(cio) - box.init_pos != box.length) {
1431 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URL Box size\n");
1443 void mj2_write_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1447 box.init_pos = cio_tell(cio);
1449 cio_write(cio, MJ2_URN, 4); /* URN */
1451 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1453 cio_write(cio, tk->urn[urn_num].name[0], 4);
1454 cio_write(cio, tk->urn[urn_num].name[1], 4);
1455 cio_write(cio, tk->urn[urn_num].name[2], 4);
1456 cio_write(cio, tk->urn[urn_num].name[3], 4);
1457 cio_write(cio, tk->urn[urn_num].location[0], 4);
1458 cio_write(cio, tk->urn[urn_num].location[1], 4);
1459 cio_write(cio, tk->urn[urn_num].location[2], 4);
1460 cio_write(cio, tk->urn[urn_num].location[3], 4);
1462 box.length = cio_tell(cio) - box.init_pos;
1463 cio_seek(cio, box.init_pos);
1464 cio_write(cio, box.length, 4); /* L */
1465 cio_seek(cio, box.init_pos + box.length);
1474 int mj2_read_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1479 mj2_read_boxhdr(&box, cio);
1480 if (MJ2_URN != box.type) {
1481 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URN Marker\n");
1485 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1486 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URN box\n");
1490 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1491 tk->urn[urn_num].name[0] = cio_read(cio, 4);
1492 tk->urn[urn_num].name[1] = cio_read(cio, 4);
1493 tk->urn[urn_num].name[2] = cio_read(cio, 4);
1494 tk->urn[urn_num].name[3] = cio_read(cio, 4);
1495 tk->urn[urn_num].location[0] = cio_read(cio, 4);
1496 tk->urn[urn_num].location[1] = cio_read(cio, 4);
1497 tk->urn[urn_num].location[2] = cio_read(cio, 4);
1498 tk->urn[urn_num].location[3] = cio_read(cio, 4);
1502 if (cio_tell(cio) - box.init_pos != box.length) {
1503 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URN Box size\n");
1511 * Write the DREF box
1513 * Data reference box
1516 void mj2_write_dref(mj2_tk_t * tk, opj_cio_t *cio)
1521 box.init_pos = cio_tell(cio);
1523 cio_write(cio, MJ2_DREF, 4); /* DREF */
1525 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1527 if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
1528 cio_write(cio, 1, 4); /* entry_count = 1 */
1529 mj2_write_url(tk, 0, cio);
1531 cio_write(cio, tk->num_url + tk->num_urn, 4); /* entry_count */
1533 for (i = 0; i < tk->num_url; i++)
1534 mj2_write_url(tk, i + 1, cio);
1536 for (i = 0; i < tk->num_urn; i++)
1537 mj2_write_urn(tk, i, cio);
1540 box.length = cio_tell(cio) - box.init_pos;
1541 cio_seek(cio, box.init_pos);
1542 cio_write(cio, box.length, 4); /* L */
1543 cio_seek(cio, box.init_pos + box.length);
1549 * Data reference box
1552 int mj2_read_dref(mj2_tk_t * tk, opj_cio_t *cio)
1556 int entry_count, marker;
1559 mj2_read_boxhdr(&box, cio);
1560 if (MJ2_DREF != box.type) {
1561 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DREF Marker\n");
1565 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1566 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in DREF box\n");
1570 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1571 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in DREF box. Expected flag 0\n");
1575 entry_count = cio_read(cio, 4);
1579 for (i = 0; i < entry_count; i++) {
1581 marker = cio_read(cio, 4);
1582 if (marker == MJ2_URL) {
1585 if (mj2_read_url(tk, tk->num_url, cio))
1587 } else if (marker == MJ2_URN) {
1590 if (mj2_read_urn(tk, tk->num_urn, cio))
1593 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n");
1600 if (cio_tell(cio) - box.init_pos != box.length) {
1601 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DREF Box size\n");
1608 * Write the DINF box
1610 * Data information box
1613 void mj2_write_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1617 box.init_pos = cio_tell(cio);
1619 cio_write(cio, MJ2_DINF, 4); /* DINF */
1621 mj2_write_dref(tk, cio);
1623 box.length = cio_tell(cio) - box.init_pos;
1624 cio_seek(cio, box.init_pos);
1625 cio_write(cio, box.length, 4); /* L */
1626 cio_seek(cio, box.init_pos + box.length);
1632 * Data information box
1635 int mj2_read_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1639 mj2_read_boxhdr(&box, cio);
1640 if (MJ2_DINF != box.type) {
1641 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DINF Marker\n");
1645 if (mj2_read_dref(tk, cio))
1648 if (cio_tell(cio) - box.init_pos != box.length) {
1649 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DINF Box size\n");
1656 * Write the VMHD box
1658 * Video Media information box
1661 void mj2_write_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1665 box.init_pos = cio_tell(cio);
1667 cio_write(cio, MJ2_VMHD, 4); /* VMHD */
1669 cio_write(cio, 1, 4); /* Version = 0, flags = 1 */
1671 cio_write(cio, tk->graphicsmode, 2);
1672 cio_write(cio, tk->opcolor[0], 2);
1673 cio_write(cio, tk->opcolor[1], 2);
1674 cio_write(cio, tk->opcolor[2], 2);
1676 box.length = cio_tell(cio) - box.init_pos;
1677 cio_seek(cio, box.init_pos);
1678 cio_write(cio, box.length, 4); /* L */
1679 cio_seek(cio, box.init_pos + box.length);
1685 * Video Media information box
1688 int mj2_read_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1692 mj2_read_boxhdr(&box, cio);
1693 if (MJ2_VMHD != box.type) {
1694 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected VMHD Marker\n");
1698 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1699 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in VMHD box\n");
1703 if (1 != cio_read(cio, 3)) { /* Flags = 1 */
1704 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in VMHD box. Expected flag 1\n");
1709 tk->graphicsmode = cio_read(cio, 2);
1710 tk->opcolor[0] = cio_read(cio, 2);
1711 tk->opcolor[1] = cio_read(cio, 2);
1712 tk->opcolor[2] = cio_read(cio, 2);
1714 if (cio_tell(cio) - box.init_pos != box.length) {
1715 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with VMHD Box size\n");
1722 * Write the SMHD box
1724 * Sound Media information box
1727 void mj2_write_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1731 box.init_pos = cio_tell(cio);
1733 cio_write(cio, MJ2_SMHD, 4); /* SMHD */
1735 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1737 cio_write(cio, tk->balance, 2);
1739 cio_write(cio, 0, 2); /* Reserved */
1741 box.length = cio_tell(cio) - box.init_pos;
1742 cio_seek(cio, box.init_pos);
1743 cio_write(cio, box.length, 4); /* L */
1744 cio_seek(cio, box.init_pos + box.length);
1750 * Sound Media information box
1753 int mj2_read_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1757 mj2_read_boxhdr(&box, cio);
1758 if (MJ2_SMHD != box.type) {
1759 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected SMHD Marker\n");
1763 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1764 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in SMHD box\n");
1768 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1769 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in SMHD box. Expected flag 0\n");
1774 tk->balance = cio_read(cio, 2);
1776 /* Init variables to zero to avoid problems when freeeing memory
1777 The values will possibly be overidded when decoding the track structure */
1783 tk->num_samplestochunk = 0;
1784 tk->num_samples = 0;
1786 cio_skip(cio,2); /* Reserved */
1788 if (cio_tell(cio) - box.init_pos != box.length) {
1789 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with SMHD Box size\n");
1796 * Write the HMHD box
1798 * Hint Media information box
1801 void mj2_write_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1805 box.init_pos = cio_tell(cio);
1807 cio_write(cio, MJ2_HMHD, 4); /* HMHD */
1809 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1811 cio_write(cio, tk->maxPDUsize, 2);
1812 cio_write(cio, tk->avgPDUsize, 2);
1813 cio_write(cio, tk->maxbitrate, 4);
1814 cio_write(cio, tk->avgbitrate, 4);
1815 cio_write(cio, tk->slidingavgbitrate, 4);
1817 box.length = cio_tell(cio) - box.init_pos;
1818 cio_seek(cio, box.init_pos);
1819 cio_write(cio, box.length, 4); /* L */
1820 cio_seek(cio, box.init_pos + box.length);
1826 * Hint Media information box
1829 int mj2_read_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1833 mj2_read_boxhdr(&box, cio);
1834 if (MJ2_HMHD != box.type) {
1835 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HMHD Marker\n");
1839 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1840 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HMHD box\n");
1844 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1845 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HMHD box. Expected flag 0\n");
1850 tk->maxPDUsize = cio_read(cio, 2);
1851 tk->avgPDUsize = cio_read(cio, 2);
1852 tk->maxbitrate = cio_read(cio, 4);
1853 tk->avgbitrate = cio_read(cio, 4);
1854 tk->slidingavgbitrate = cio_read(cio, 4);
1856 /* Init variables to zero to avoid problems when freeeing memory
1857 The values will possibly be overidded when decoding the track structure */
1863 tk->num_samplestochunk = 0;
1864 tk->num_samples = 0;
1867 if (cio_tell(cio) - box.init_pos != box.length) {
1868 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HMHD Box size\n");
1875 * Write the MINF box
1877 * Media information box
1880 void mj2_write_minf(mj2_tk_t * tk, opj_cio_t *cio)
1884 box.init_pos = cio_tell(cio);
1886 cio_write(cio, MJ2_MINF, 4); /* MINF */
1888 if (tk->track_type == 0) {
1889 mj2_write_vmhd(tk, cio);
1890 } else if (tk->track_type == 1) {
1891 mj2_write_smhd(tk, cio);
1892 } else if (tk->track_type == 2) {
1893 mj2_write_hmhd(tk, cio);
1896 mj2_write_dinf(tk, cio);
1897 mj2_write_stbl(tk, cio);
1899 box.length = cio_tell(cio) - box.init_pos;
1900 cio_seek(cio, box.init_pos);
1901 cio_write(cio, box.length, 4); /* L */
1902 cio_seek(cio, box.init_pos + box.length);
1908 * Media information box
1911 int mj2_read_minf(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1914 unsigned int box_type;
1917 mj2_read_boxhdr(&box, cio);
1918 if (MJ2_MINF != box.type) {
1919 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MINF Marker\n");
1924 box_type = cio_read(cio, 4);
1927 if (box_type == MJ2_VMHD) {
1928 if (mj2_read_vmhd(tk, cio))
1930 } else if (box_type == MJ2_SMHD) {
1931 if (mj2_read_smhd(tk, cio))
1933 } else if (box_type == MJ2_HMHD) {
1934 if (mj2_read_hmhd(tk, cio))
1937 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n");
1941 if (mj2_read_dinf(tk, cio))
1944 if (mj2_read_stbl(tk, img, cio))
1947 if (cio_tell(cio) - box.init_pos != box.length) {
1948 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MINF Box size\n");
1955 * Write the HDLR box
1957 * Handler reference box
1960 void mj2_write_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
1964 box.init_pos = cio_tell(cio);
1966 cio_write(cio, MJ2_HDLR, 4); /* HDLR */
1968 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1970 cio_write(cio, 0, 4); /* Predefine */
1972 tk->name = 0; /* The track name is immediately determined by the track type */
1974 if (tk->track_type == 0) {
1975 tk->handler_type = 0x76696465; /* Handler type: vide */
1976 cio_write(cio, tk->handler_type, 4);
1978 cio_write(cio, 0, 4);
1979 cio_write(cio, 0, 4);
1980 cio_write(cio, 0, 4); /* Reserved */
1982 cio_write(cio, 0x76696465, 4);
1983 cio_write(cio, 0x6F206d65, 4);
1984 cio_write(cio, 0x64696120, 4);
1985 cio_write(cio, 0x74726163, 4);
1986 cio_write(cio, 0x6b00, 2); /* String: video media track */
1987 } else if (tk->track_type == 1) {
1988 tk->handler_type = 0x736F756E; /* Handler type: soun */
1989 cio_write(cio, tk->handler_type, 4);
1991 cio_write(cio, 0, 4);
1992 cio_write(cio, 0, 4);
1993 cio_write(cio, 0, 4); /* Reserved */
1995 cio_write(cio, 0x536F756E, 4);
1996 cio_write(cio, 0x6400, 2); /* String: Sound */
1997 } else if (tk->track_type == 2) {
1998 tk->handler_type = 0x68696E74; /* Handler type: hint */
1999 cio_write(cio, tk->handler_type, 4);
2001 cio_write(cio, 0, 4);
2002 cio_write(cio, 0, 4);
2003 cio_write(cio, 0, 4); /* Reserved */
2005 cio_write(cio, 0x48696E74, 4);
2006 cio_write(cio, 0, 2); /* String: Hint */
2009 box.length = cio_tell(cio) - box.init_pos;
2010 cio_seek(cio, box.init_pos);
2011 cio_write(cio, box.length, 4); /* L */
2012 cio_seek(cio, box.init_pos + box.length);
2018 * Handler reference box
2021 int mj2_read_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
2026 mj2_read_boxhdr(&box, cio);
2027 if (MJ2_HDLR != box.type) {
2028 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HDLR Marker\n");
2033 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2034 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HDLR box\n");
2038 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2039 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HDLR box. Expected flag 0\n");
2043 cio_skip(cio,4); /* Reserved */
2045 tk->handler_type = cio_read(cio, 4);
2046 cio_skip(cio,12); /* Reserved */
2048 tk->name_size = box.length - 32;
2050 tk->name = (char *) malloc(tk->name_size * sizeof(char));
2051 for (i = 0; i < tk->name_size; i++) {
2052 tk->name[i] = cio_read(cio, 1); /* Name */
2055 if (cio_tell(cio) - box.init_pos != box.length) {
2056 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HDLR Box size\n");
2063 * Write the MDHD box
2068 void mj2_write_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2073 unsigned int modification_time;
2075 box.init_pos = cio_tell(cio);
2077 cio_write(cio, MJ2_MDHD, 4); /* MDHD */
2079 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2081 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2083 time(<ime); /* Time since 1/1/70 */
2084 modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2086 cio_write(cio, modification_time, 4); /* Modification Time */
2088 cio_write(cio, tk->timescale, 4); /* Timescale */
2092 for (i = 0; i < tk->num_samples; i++)
2093 tk->duration += tk->sample[i].sample_delta;
2095 cio_write(cio, tk->duration, 4); /* Duration */
2097 cio_write(cio, tk->language, 2); /* Language */
2099 cio_write(cio, 0, 2); /* Predefined */
2101 box.length = cio_tell(cio) - box.init_pos;
2102 cio_seek(cio, box.init_pos);
2103 cio_write(cio, box.length, 4); /* L */
2104 cio_seek(cio, box.init_pos + box.length);
2113 int mj2_read_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2117 mj2_read_boxhdr(&box, cio);
2118 if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) { // Kakadu writes MHDR instead of MDHD
2119 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDHD Marker\n");
2123 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2124 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MDHD box\n");
2128 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2129 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MDHD box. Expected flag 0\n");
2134 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2136 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2138 tk->timescale = cio_read(cio, 4); /* Timescale */
2140 tk->duration = cio_read(cio, 4); /* Duration */
2142 tk->language = cio_read(cio, 2); /* Language */
2144 cio_skip(cio,2); /* Predefined */
2146 if (cio_tell(cio) - box.init_pos != box.length) {
2147 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDHD Box size\n");
2154 * Write the MDIA box
2159 void mj2_write_mdia(mj2_tk_t * tk, opj_cio_t *cio)
2163 box.init_pos = cio_tell(cio);
2165 cio_write(cio, MJ2_MDIA, 4); /* MDIA */
2167 mj2_write_mdhd(tk, cio);
2168 mj2_write_hdlr(tk, cio);
2169 mj2_write_minf(tk, cio);
2171 box.length = cio_tell(cio) - box.init_pos;
2172 cio_seek(cio, box.init_pos);
2173 cio_write(cio, box.length, 4); /* L */
2174 cio_seek(cio, box.init_pos + box.length);
2183 int mj2_read_mdia(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2187 mj2_read_boxhdr(&box, cio);
2188 if (MJ2_MDIA != box.type) {
2189 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDIA Marker\n");
2193 if (mj2_read_mdhd(tk, cio))
2195 if (mj2_read_hdlr(tk, cio))
2197 if (mj2_read_minf(tk, img, cio))
2200 if (cio_tell(cio) - box.init_pos != box.length) {
2201 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDIA Box size\n");
2208 * Write the TKHD box
2213 void mj2_write_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2219 box.init_pos = cio_tell(cio);
2222 cio_write(cio, MJ2_TKHD, 4); /* TKHD */
2224 cio_write(cio, 3, 4); /* Version=0, flags=3 */
2226 time(<ime); /* Time since 1/1/70 */
2227 tk->modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2229 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2231 cio_write(cio, tk->modification_time, 4); /* Modification Time */
2233 cio_write(cio, tk->track_ID, 4); /* Track ID */
2235 cio_write(cio, 0, 4); /* Reserved */
2239 for (i = 0; i < tk->num_samples; i++)
2240 tk->duration += tk->sample[i].sample_delta;
2242 cio_write(cio, tk->duration, 4); /* Duration */
2244 cio_write(cio, 0, 4); /* Reserved */
2245 cio_write(cio, 0, 4); /* Reserved */
2247 cio_write(cio, tk->layer, 2); /* Layer */
2249 cio_write(cio, 0, 2); /* Predefined */
2251 cio_write(cio, tk->volume, 2); /* Volume */
2253 cio_write(cio, 0, 2); /* Reserved */
2255 cio_write(cio, tk->trans_matrix[0], 4); /* Transformation matrix for track */
2256 cio_write(cio, tk->trans_matrix[1], 4);
2257 cio_write(cio, tk->trans_matrix[2], 4);
2258 cio_write(cio, tk->trans_matrix[3], 4);
2259 cio_write(cio, tk->trans_matrix[4], 4);
2260 cio_write(cio, tk->trans_matrix[5], 4);
2261 cio_write(cio, tk->trans_matrix[6], 4);
2262 cio_write(cio, tk->trans_matrix[7], 4);
2263 cio_write(cio, tk->trans_matrix[8], 4);
2265 cio_write(cio, tk->visual_w, 4); /* Video Visual Width */
2267 cio_write(cio, tk->visual_h, 4); /* Video Visual Height */
2269 box.length = cio_tell(cio) - box.init_pos;
2270 cio_seek(cio, box.init_pos);
2271 cio_write(cio, box.length, 4); /* L */
2272 cio_seek(cio, box.init_pos + box.length);
2281 int mj2_read_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2287 mj2_read_boxhdr(&box, cio);
2289 if (MJ2_TKHD != box.type) {
2290 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TKHD Marker\n");
2294 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2295 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in TKHD box\n");
2299 flag = cio_read(cio, 3);
2301 if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) { /* Flags = 1,2,3 or 4 */
2302 opj_event_msg(cio->cinfo, EVT_ERROR,
2303 "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2307 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2309 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2311 tk->track_ID = cio_read(cio, 4); /* Track ID */
2313 cio_skip(cio,4); /* Reserved */
2315 tk->duration = cio_read(cio, 4); /* Duration */
2317 cio_skip(cio,8); /* Reserved */
2319 tk->layer = cio_read(cio, 2); /* Layer */
2321 cio_read(cio, 2); /* Predefined */
2323 tk->volume = cio_read(cio, 2); /* Volume */
2325 cio_skip(cio,2); /* Reserved */
2327 tk->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for track */
2328 tk->trans_matrix[1] = cio_read(cio, 4);
2329 tk->trans_matrix[2] = cio_read(cio, 4);
2330 tk->trans_matrix[3] = cio_read(cio, 4);
2331 tk->trans_matrix[4] = cio_read(cio, 4);
2332 tk->trans_matrix[5] = cio_read(cio, 4);
2333 tk->trans_matrix[6] = cio_read(cio, 4);
2334 tk->trans_matrix[7] = cio_read(cio, 4);
2335 tk->trans_matrix[8] = cio_read(cio, 4);
2337 tk->visual_w = cio_read(cio, 4); /* Video Visual Width */
2339 tk->visual_h = cio_read(cio, 4); /* Video Visual Height */
2341 if (cio_tell(cio) - box.init_pos != box.length) {
2342 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TKHD Box size\n");
2349 * Write the TRAK box
2354 void mj2_write_trak(mj2_tk_t * tk, opj_cio_t *cio)
2358 box.init_pos = cio_tell(cio);
2361 cio_write(cio, MJ2_TRAK, 4); /* TRAK */
2363 mj2_write_tkhd(tk, cio);
2364 mj2_write_mdia(tk, cio);
2366 box.length = cio_tell(cio) - box.init_pos;
2367 cio_seek(cio, box.init_pos);
2368 cio_write(cio, box.length, 4); /* L */
2369 cio_seek(cio, box.init_pos + box.length);
2378 int mj2_read_trak(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2382 mj2_read_boxhdr(&box, cio);
2383 if (MJ2_TRAK != box.type) {
2384 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TRAK Marker\n");
2387 if (mj2_read_tkhd(tk, cio))
2389 if (mj2_read_mdia(tk, img, cio))
2391 if (cio_tell(cio) - box.init_pos != box.length) {
2392 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TRAK Box\n");
2399 * Write the MVHD box
2404 void mj2_write_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2412 box.init_pos = cio_tell(cio);
2414 cio_write(cio, MJ2_MVHD, 4); /* MVHD */
2416 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2418 time(<ime); /* Time since 1/1/70 */
2419 movie->modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2421 cio_write(cio, movie->creation_time, 4); /* Creation Time */
2423 cio_write(cio, movie->modification_time, 4); /* Modification Time */
2425 cio_write(cio, movie->timescale, 4); /* Timescale */
2427 movie->duration = 0;
2429 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2430 mj2_tk_t *tk = &movie->tk[i];
2432 for (j = 0; j < tk->num_samples; j++) {
2433 movie->duration += tk->sample[j].sample_delta;
2437 cio_write(cio, movie->duration, 4);
2439 cio_write(cio, movie->rate, 4); /* Rate to play presentation */
2441 cio_write(cio, movie->volume, 2); /* Volume */
2443 cio_write(cio, 0, 2); /* Reserved */
2444 cio_write(cio, 0, 4); /* Reserved */
2445 cio_write(cio, 0, 4); /* Reserved */
2447 cio_write(cio, movie->trans_matrix[0], 4); /* Transformation matrix for video */
2448 cio_write(cio, movie->trans_matrix[1], 4);
2449 cio_write(cio, movie->trans_matrix[2], 4);
2450 cio_write(cio, movie->trans_matrix[3], 4);
2451 cio_write(cio, movie->trans_matrix[4], 4);
2452 cio_write(cio, movie->trans_matrix[5], 4);
2453 cio_write(cio, movie->trans_matrix[6], 4);
2454 cio_write(cio, movie->trans_matrix[7], 4);
2455 cio_write(cio, movie->trans_matrix[8], 4);
2457 cio_write(cio, 0, 4); /* Pre-defined */
2458 cio_write(cio, 0, 4); /* Pre-defined */
2459 cio_write(cio, 0, 4); /* Pre-defined */
2460 cio_write(cio, 0, 4); /* Pre-defined */
2461 cio_write(cio, 0, 4); /* Pre-defined */
2462 cio_write(cio, 0, 4); /* Pre-defined */
2465 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
2466 if (max_tk_num < movie->tk[i].track_ID)
2467 max_tk_num = movie->tk[i].track_ID;
2470 movie->next_tk_id = max_tk_num + 1;
2472 cio_write(cio, movie->next_tk_id, 4); /* ID of Next track to be added */
2474 box.length = cio_tell(cio) - box.init_pos;
2475 cio_seek(cio, box.init_pos);
2476 cio_write(cio, box.length, 4); /* L */
2477 cio_seek(cio, box.init_pos + box.length);
2486 int mj2_read_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2490 mj2_read_boxhdr(&box, cio);
2491 if (MJ2_MVHD != box.type) {
2492 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MVHD Marker\n");
2497 if (0 != cio_read(cio, 4)) { /* Version = 0, flags = 0 */
2498 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MVHD box\n");
2501 movie->creation_time = cio_read(cio, 4); /* Creation Time */
2503 movie->modification_time = cio_read(cio, 4); /* Modification Time */
2505 movie->timescale = cio_read(cio, 4); /* Timescale */
2507 movie->duration = cio_read(cio, 4); /* Duration */
2509 movie->rate = cio_read(cio, 4); /* Rate to play presentation */
2511 movie->volume = cio_read(cio, 2); /* Volume */
2513 cio_skip(cio,10); /* Reserved */
2515 movie->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for video */
2516 movie->trans_matrix[1] = cio_read(cio, 4);
2517 movie->trans_matrix[2] = cio_read(cio, 4);
2518 movie->trans_matrix[3] = cio_read(cio, 4);
2519 movie->trans_matrix[4] = cio_read(cio, 4);
2520 movie->trans_matrix[5] = cio_read(cio, 4);
2521 movie->trans_matrix[6] = cio_read(cio, 4);
2522 movie->trans_matrix[7] = cio_read(cio, 4);
2523 movie->trans_matrix[8] = cio_read(cio, 4);
2525 cio_skip(cio,24); /* Pre-defined */
2527 movie->next_tk_id = cio_read(cio, 4); /* ID of Next track to be added */
2529 if (cio_tell(cio) - box.init_pos != box.length) {
2530 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MVHD Box Size\n");
2538 * Write the MOOV box
2543 void mj2_write_moov(opj_mj2_t * movie, opj_cio_t *cio)
2548 box.init_pos = cio_tell(cio);
2550 cio_write(cio, MJ2_MOOV, 4); /* MOOV */
2552 mj2_write_mvhd(movie, cio);
2554 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2555 mj2_write_trak(&movie->tk[i], cio);
2558 box.length = cio_tell(cio) - box.init_pos;
2559 cio_seek(cio, box.init_pos);
2560 cio_write(cio, box.length, 4); /* L */
2561 cio_seek(cio, box.init_pos + box.length);
2570 int mj2_read_moov(opj_mj2_t * movie, opj_image_t * img, opj_cio_t *cio)
2576 mj2_read_boxhdr(&box, cio);
2577 if (MJ2_MOOV != box.type) {
2578 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MOOV Marker\n");
2582 if (mj2_read_mvhd(movie, cio))
2586 (mj2_tk_t *) malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2588 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
2589 mj2_tk_t *tk = &movie->tk[i];
2590 tk->cinfo = movie->cinfo;
2591 mj2_read_boxhdr(&box2, cio);
2592 if (box2.type == MJ2_TRAK) {
2593 cio_seek(cio, box2.init_pos);
2594 if (mj2_read_trak(tk, img, cio))
2597 if (tk->track_type == 0) {
2599 } else if (tk->track_type == 1) {
2601 } else if (tk->track_type == 2) {
2604 } else if (box2.type == MJ2_MVEX) {
2605 cio_seek(cio, box2.init_pos);
2606 cio_skip(cio,box2.length);
2609 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2616 int mj2_read_struct(FILE *file, opj_mj2_t *movie) {
2624 /* open a byte stream for reading */
2625 src = (char*) malloc (300 * sizeof(char));
2627 /* Assuming that jp and ftyp markers size do
2628 not exceed 300 bytes */
2629 fread(src,300,1, file);
2631 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2633 if (mj2_read_jp(cio))
2635 if (mj2_read_ftyp(movie, cio))
2638 fsresult = fseek(file,cio_tell(cio),SEEK_SET);
2640 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read data after FTYP box\n" );
2644 foffset = cio_tell(cio);
2648 fread(src,30,1,file);
2649 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2650 mj2_read_boxhdr(&box, cio);
2652 while(box.type != MJ2_MOOV) {
2657 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2659 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MDAT box\n" );
2662 foffset += box.length;
2666 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2668 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOF box\n" );
2671 foffset += box.length;
2674 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2676 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read FREE box\n" );
2679 foffset += box.length;
2682 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2684 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read SKIP box\n" );
2687 foffset += box.length;
2690 opj_event_msg(cio->cinfo, EVT_ERROR, "Unknown box in MJ2 stream\n");
2691 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2693 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read end of unknown box\n");
2696 foffset += box.length;
2699 fsresult = fread(src,8,1,file);
2700 if (fsresult != 1) {
2701 opj_event_msg(cio->cinfo, EVT_ERROR, "MOOV box not found in file\n");
2704 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 8);
2705 mj2_read_boxhdr(&box, cio);
2708 fseek(file,foffset,SEEK_SET);
2709 src = realloc(src,box.length);
2710 fsresult = fread(src,box.length,1,file);
2711 if (fsresult != 1) {
2712 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOV box\n");
2716 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, box.length);
2718 if (mj2_read_moov(movie, &img, cio))
2725 /* ----------------------------------------------------------------------- */
2726 /* MJ2 decoder interface */
2727 /* ----------------------------------------------------------------------- */
2729 opj_dinfo_t* mj2_create_decompress() {
2731 opj_dinfo_t *dinfo = (opj_dinfo_t*)opj_malloc(sizeof(opj_dinfo_t));
2732 if(!dinfo) return NULL;
2734 dinfo->is_decompressor = true;
2736 mj2 = (opj_mj2_t*)opj_malloc(sizeof(opj_mj2_t));
2737 dinfo->mj2_handle = mj2;
2739 mj2->cinfo = (opj_common_ptr)dinfo;
2741 mj2->j2k = j2k_create_decompress((opj_common_ptr)dinfo);
2742 dinfo->j2k_handle = mj2->j2k;
2747 void mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters) {
2751 /* setup the J2K decoder parameters */
2752 j2k_setup_decoder(movie->cinfo->j2k_handle, &mj2_parameters->j2k_parameters);
2755 void mj2_destroy_decompress(opj_mj2_t *movie) {
2760 if (movie->cinfo->j2k_handle) {
2761 j2k_destroy_compress(movie->j2k);
2764 if (movie->num_cl != 0)
2765 opj_free(movie->cl);
2767 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2769 if (tk->name_size != 0)
2771 if (tk->track_type == 0) {// Video track
2772 if (tk->jp2_struct.comps != 0)
2773 opj_free(tk->jp2_struct.comps);
2774 if (tk->jp2_struct.cl != 0)
2775 opj_free(tk->jp2_struct.cl);
2776 if (tk->num_jp2x != 0)
2777 opj_free(tk->jp2xdata);
2780 if (tk->num_url != 0)
2782 if (tk->num_urn != 0)
2784 if (tk->num_br != 0)
2786 if (tk->num_tts != 0)
2788 if (tk->num_chunks != 0)
2789 opj_free(tk->chunk);
2790 if (tk->num_samplestochunk != 0)
2791 opj_free(tk->sampletochunk);
2792 if (tk->num_samples != 0)
2793 opj_free(tk->sample);
2796 opj_free(movie->tk);
2801 /* ----------------------------------------------------------------------- */
2802 /* MJ2 encoder interface */
2803 /* ----------------------------------------------------------------------- */
2806 opj_cinfo_t* mj2_create_compress() {
2808 opj_cinfo_t *cinfo = (opj_cinfo_t*)opj_malloc(sizeof(opj_cinfo_t));
2809 if(!cinfo) return NULL;
2811 mj2 = (opj_mj2_t*)opj_malloc(sizeof(opj_mj2_t));
2812 cinfo->mj2_handle = mj2;
2814 mj2->cinfo = (opj_common_ptr)cinfo;
2817 mj2->j2k = j2k_create_compress(mj2->cinfo);
2818 cinfo->j2k_handle = mj2->j2k;
2823 void mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters) {
2824 if(movie && parameters) {
2825 opj_jp2_t *jp2_struct;
2827 movie->num_htk = 0; // No hint tracks
2828 movie->num_stk = 0; // No sound tracks
2829 movie->num_vtk = 1; // One video track
2831 movie->brand = MJ2_MJ2; // One brand: MJ2
2832 movie->num_cl = 2; // Two compatible brands: MJ2 and MJ2S
2833 movie->cl = (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
2834 movie->cl[0] = MJ2_MJ2;
2835 movie->cl[1] = MJ2_MJ2S;
2836 movie->minversion = 0; // Minimum version: 0
2838 movie->tk = (mj2_tk_t*) malloc (sizeof(mj2_tk_t)); //Memory allocation for the video track
2839 movie->tk[0].sample = (mj2_sample_t*) malloc (sizeof(mj2_sample_t));
2840 movie->tk[0].chunk = (mj2_chunk_t *) malloc(sizeof(mj2_chunk_t));
2841 movie->tk[0].track_type = 0; // Video track
2842 movie->tk[0].track_ID = 1; // Track ID = 1
2843 movie->tk[0].Dim[0] = parameters->Dim[0];
2844 movie->tk[0].Dim[1] = parameters->Dim[1];
2845 movie->tk[0].w = parameters->w;
2846 movie->tk[0].h = parameters->h;
2847 movie->tk[0].CbCr_subsampling_dx = parameters->CbCr_subsampling_dx;
2848 movie->tk[0].CbCr_subsampling_dy = parameters->CbCr_subsampling_dy;
2849 movie->tk[0].sample_rate = parameters->frame_rate;
2851 jp2_struct = &movie->tk[0].jp2_struct;
2852 jp2_struct->numcomps = 3; // NC
2854 (opj_jp2_comps_t *) malloc(jp2_struct->numcomps * sizeof(opj_jp2_comps_t));
2855 jp2_struct->precedence = 0; /* PRECEDENCE*/
2856 jp2_struct->approx = 0; /* APPROX*/
2857 jp2_struct->brand = JP2_JP2; /* BR */
2858 jp2_struct->minversion = 0; /* MinV */
2859 jp2_struct->numcl = 1;
2860 jp2_struct->cl = (unsigned int *) malloc(jp2_struct->numcl * sizeof(int));
2861 jp2_struct->cl[0] = JP2_JP2; /* CL0 : JP2 */
2862 jp2_struct->C = 7; /* C : Always 7*/
2863 jp2_struct->UnkC = 0; /* UnkC, colorspace specified in colr box*/
2864 jp2_struct->IPR = 0; /* IPR, no intellectual property*/
2865 jp2_struct->w = parameters->w;
2866 jp2_struct->h = parameters->h;
2867 jp2_struct->bpc = 7;
2868 jp2_struct->meth = 1;
2869 jp2_struct->enumcs = 18; // YUV
2873 void mj2_destroy_compress(opj_mj2_t *movie) {
2878 if (movie->cinfo->j2k_handle) {
2879 j2k_destroy_compress(movie->j2k);
2882 if (movie->num_cl != 0)
2883 opj_free(movie->cl);
2885 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2887 if (tk->name_size != 0)
2889 if (tk->track_type == 0) {// Video track
2890 if (tk->jp2_struct.comps != 0)
2891 opj_free(tk->jp2_struct.comps);
2892 if (tk->jp2_struct.cl != 0)
2893 opj_free(tk->jp2_struct.cl);
2894 if (tk->num_jp2x != 0)
2895 opj_free(tk->jp2xdata);
2898 if (tk->num_url != 0)
2900 if (tk->num_urn != 0)
2902 if (tk->num_br != 0)
2904 if (tk->num_tts != 0)
2906 if (tk->num_chunks != 0)
2907 opj_free(tk->chunk);
2908 if (tk->num_samplestochunk != 0)
2909 opj_free(tk->sampletochunk);
2910 if (tk->num_samples != 0)
2911 opj_free(tk->sample);
2914 opj_free(movie->tk);