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 "../libopenjpeg/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
46 static bool jp2_read_boxhdr(opj_common_ptr cinfo, opj_cio_t *cio, opj_jp2_box_t *box);
54 int mj2_read_boxhdr(mj2_box_t * box, opj_cio_t *cio)
56 box->init_pos = cio_tell(cio);
57 box->length = cio_read(cio, 4);
58 box->type = cio_read(cio, 4);
59 if (box->length == 1) {
60 if (cio_read(cio, 4) != 0) {
61 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Cannot handle box sizes higher than 2^32\n");
64 box->length = cio_read(cio, 4);
66 box->length = cio_numbytesleft(cio) + 12;
68 else if (box->length == 0) {
69 box->length = cio_numbytesleft(cio) + 8;
76 * Initialisation of a Standard Movie, given a simple movie structure defined by the user
77 * The movie will have one sample per chunk
79 * Arguments: opj_mj2_t * movie
80 * Several variables of "movie" must be defined in order to enable a correct execution of
82 * - The number of tracks of each type (movie->num_vtk, movie->num_stk, movie->num_htk)
83 * - The memory for each must be allocated (movie->tk)
85 * The track type (tk->track_type)
86 * The number of sample (tk->num_samples)
87 * The sample rate (tk->sample_rate)
91 int mj2_init_stdmovie(opj_mj2_t * movie)
98 movie->brand = MJ2_MJ2;
99 movie->minversion = 0;
101 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
103 movie->cl[0] = MJ2_MJ2;
104 movie->cl[1] = MJ2_MJ2S;
105 time(<ime); /* Time since 1/1/70 */
106 movie->creation_time = (unsigned int) ltime + 2082844800; /* Seconds between 1/1/04 and 1/1/70 */
107 movie->timescale = 1000;
109 movie->rate = 1 << 16; /* Rate to play presentation (default = 0x00010000) */
110 movie->volume = 1 << 8; /* Movie volume (default = 0x0100) */
111 movie->trans_matrix[0] = 0x00010000; /* Transformation matrix for video */
112 movie->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
113 movie->trans_matrix[2] = 0;
114 movie->trans_matrix[3] = 0;
115 movie->trans_matrix[4] = 0x00010000;
116 movie->trans_matrix[5] = 0;
117 movie->trans_matrix[6] = 0;
118 movie->trans_matrix[7] = 0;
119 movie->trans_matrix[8] = 0x40000000;
120 movie->next_tk_id = 1;
123 w = tk0->w; h = tk0->h; prec = tk0->depth;
125 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++)
127 mj2_tk_t *tk = &movie->tk[i];
130 tk->jp2_struct.comps = NULL;
131 tk->jp2_struct.cl = NULL;
133 if (tk->track_type == 0) /* no sound or hint track */
135 if (tk->num_samples == 0)
138 tk->w = w; tk->h = h; tk->depth = prec;
142 tk->timescale = 1000; /* Timescale = 1 ms */
144 tk->chunk[0].num_samples = 1;
145 tk->chunk[0].sample_descr_idx = 1;
147 tk->same_sample_size = 0;
149 tk->num_samplestochunk = 1; /* One sample per chunk */
150 tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
151 tk->sampletochunk[0].first_chunk = 1;
152 tk->sampletochunk[0].samples_per_chunk = 1;
153 tk->sampletochunk[0].sample_descr_idx = 1;
155 if (tk->sample_rate == 0)
157 opj_event_msg(tk->cinfo, EVT_ERROR,
158 "Error while initializing MJ2 movie: Sample rate of track"
159 " %d must be different from zero\n", tk->track_ID);
163 for (j = 0; j < tk->num_samples; j++)
165 tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
169 tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
170 tk->tts[0].sample_count = tk->num_samples;
171 tk->tts[0].sample_delta = tk->timescale / tk->sample_rate;
173 tk->horizresolution = 0x00480000; /* Horizontal resolution (typically 72) */
174 tk->vertresolution = 0x00480000; /* Vertical resolution (typically 72) */
175 tk->compressorname[0] = 0x0f4d6f74; /* Compressor Name[]: Motion JPEG2000 */
176 tk->compressorname[1] = 0x696f6e20;
177 tk->compressorname[2] = 0x4a504547;
178 tk->compressorname[3] = 0x32303030;
179 tk->compressorname[4] = 0x00120000;
180 tk->compressorname[5] = 0;
181 tk->compressorname[6] = 0x00000042;
182 tk->compressorname[7] = 0x000000DC;
183 tk->num_url = 0; /* Number of URL */
184 tk->num_urn = 0; /* Number of URN */
185 tk->graphicsmode = 0; /* Graphicsmode */
186 tk->opcolor[0] = 0; /* OpColor */
187 tk->opcolor[1] = 0; /* OpColor */
188 tk->opcolor[2] = 0; /* OpColor */
189 tk->creation_time = movie->creation_time; /* Seconds between 1/1/04 and 1/1/70 */
190 tk->language = 0; /* Language (undefined) */
192 tk->volume = 1 << 8; /* Movie volume (default = 0x0100) */
193 tk->trans_matrix[0] = 0x00010000; /* Transformation matrix for track */
194 tk->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
195 tk->trans_matrix[2] = 0;
196 tk->trans_matrix[3] = 0;
197 tk->trans_matrix[4] = 0x00010000;
198 tk->trans_matrix[5] = 0;
199 tk->trans_matrix[6] = 0;
200 tk->trans_matrix[7] = 0;
201 tk->trans_matrix[8] = 0x40000000;
204 tk->or_fieldcount = 1;
205 tk->or_fieldorder = 0;
207 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
209 tk->br[1] = MJ2_J2P0;
211 tk->hsub = 2; /* 4:2:0 */
212 tk->vsub = 2; /* 4:2:0 */
215 tk->visual_w = tk->w << 16;
216 tk->visual_h = tk->h << 16;
227 * Time To Sample box Decompact
230 void mj2_tts_decompact(mj2_tk_t * tk)
234 for (i = 0; i < tk->num_tts; i++) {
235 tk->num_samples += tk->tts[i].sample_count;
238 tk->sample = (mj2_sample_t*) opj_malloc(tk->num_samples * sizeof(mj2_sample_t));
240 for (i = 0; i < tk->num_tts; i++) {
241 for (j = 0; j < tk->tts[i].sample_count; j++) {
242 tk->sample[j].sample_delta = tk->tts[i].sample_delta;
248 * Sample To Chunk box Decompact
251 void mj2_stsc_decompact(mj2_tk_t * tk)
257 if (tk->num_samplestochunk == 1) {
259 (unsigned int) ceil((double) tk->num_samples /
260 (double) tk->sampletochunk[0].samples_per_chunk);
261 tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_chunks * sizeof(mj2_chunk_t));
262 for (k = 0; k < tk->num_chunks; k++) {
263 tk->chunk[k].num_samples = tk->sampletochunk[0].samples_per_chunk;
267 tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_samples * sizeof(mj2_chunk_t));
269 for (i = 0; i < tk->num_samplestochunk -1 ; i++) {
270 for (j = tk->sampletochunk[i].first_chunk - 1;
271 j < tk->sampletochunk[i + 1].first_chunk - 1; j++) {
272 tk->chunk[j].num_samples = tk->sampletochunk[i].samples_per_chunk;
274 sampleno += tk->chunk[j].num_samples;
277 tk->num_chunks += (int)(tk->num_samples - sampleno) / tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
278 for (k = tk->sampletochunk[tk->num_samplestochunk - 1].first_chunk - 1;
279 k < tk->num_chunks; k++) {
280 tk->chunk[k].num_samples =
281 tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
283 tk->chunk = (mj2_chunk_t*)
284 opj_realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
291 * Chunk offset box Decompact
294 void mj2_stco_decompact(mj2_tk_t * tk)
299 int intra_chunk_offset;
301 for (i = 0; i < tk->num_chunks; i++) {
302 intra_chunk_offset = 0;
303 for (j = 0; j < tk->chunk[i].num_samples; j++) {
304 tk->sample[k].offset = intra_chunk_offset + tk->chunk[i].offset;
305 intra_chunk_offset += tk->sample[k].sample_size;
317 void mj2_write_jp(opj_cio_t *cio)
320 box.init_pos = cio_tell(cio);
323 cio_write(cio, MJ2_JP, 4); /* JP */
324 cio_write(cio, 0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
326 box.length = cio_tell(cio) - box.init_pos;
327 cio_seek(cio, box.init_pos);
328 cio_write(cio, box.length, 4);
329 cio_seek(cio, box.init_pos + box.length);
335 * JPEG 2000 signature
338 int mj2_read_jp(opj_cio_t *cio)
342 mj2_read_boxhdr(&box, cio);
343 if (MJ2_JP != box.type) { /* Check Marker */
344 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP Marker\n");
347 if (0x0d0a870a != cio_read(cio, 4)) { /* read the 0x0d0a870a required in a JP box */
348 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Marker\n");
351 if (cio_tell(cio) - box.init_pos != box.length) { /* Check box length */
352 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Box size \n");
365 void mj2_write_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
369 box.init_pos = cio_tell(cio);
372 cio_write(cio, MJ2_FTYP, 4); /* FTYP */
373 cio_write(cio, movie->brand, 4); /* BR */
374 cio_write(cio, movie->minversion, 4); /* MinV */
376 for (i = 0; i < movie->num_cl; i++)
377 cio_write(cio, movie->cl[i], 4); /* CL */
379 box.length = cio_tell(cio) - box.init_pos;
380 cio_seek(cio, box.init_pos);
381 cio_write(cio, box.length, 4); /* Length */
382 cio_seek(cio, box.init_pos + box.length);
391 int mj2_read_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
396 mj2_read_boxhdr(&box, cio); /* Box Size */
397 if (MJ2_FTYP != box.type) {
398 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FTYP Marker\n");
402 movie->brand = cio_read(cio, 4); /* BR */
403 movie->minversion = cio_read(cio, 4); /* MinV */
404 movie->num_cl = (box.length - 16) / 4;
405 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
407 for (i = movie->num_cl - 1; i > -1; i--)
408 movie->cl[i] = cio_read(cio, 4); /* CLi */
410 if (cio_tell(cio) - box.init_pos != box.length) {
411 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FTYP Box\n");
424 void mj2_write_stco(mj2_tk_t * tk, opj_cio_t *cio)
429 box.init_pos = cio_tell(cio);
431 cio_write(cio, MJ2_STCO, 4); /* STCO */
433 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
435 cio_write(cio, tk->num_chunks, 4); /* Entry Count */
437 for (i = 0; i < tk->num_chunks; i++) {
438 cio_write(cio, tk->chunk[i].offset, 4); /* Entry offset */
441 box.length = cio_tell(cio) - box.init_pos;
442 cio_seek(cio, box.init_pos);
443 cio_write(cio, box.length, 4); /* L */
444 cio_seek(cio, box.init_pos + box.length);
453 int mj2_read_stco(mj2_tk_t * tk, opj_cio_t *cio)
458 mj2_read_boxhdr(&box, cio); /* Box Size */
459 if (MJ2_STCO != box.type) {
460 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STCO Marker\n");
464 if (0 != cio_read(cio, 1)) { /* Version = 0 */
465 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STCO box\n");
469 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
470 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STCO box. Expected flag 0\n");
475 if (cio_read(cio, 4) != tk->num_chunks) {
476 opj_event_msg(cio->cinfo, EVT_ERROR,
477 "Error in STCO box: expecting same amount of entry-count as chunks \n");
479 for (i = 0; i < tk->num_chunks; i++) {
480 tk->chunk[i].offset = cio_read(cio, 4); /* Entry offset */
484 mj2_stco_decompact(tk);
487 if (cio_tell(cio) - box.init_pos != box.length) {
488 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STCO Box size\n");
500 void mj2_write_stsz(mj2_tk_t * tk, opj_cio_t *cio)
505 box.init_pos = cio_tell(cio);
507 cio_write(cio, MJ2_STSZ, 4); /* STSZ */
509 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
511 if (tk->same_sample_size == 1) { /* If they all have the same size */
512 cio_write(cio, tk->sample[0].sample_size, 4); /* Size */
514 cio_write(cio, 1, 4); /* Entry count = 1 */
518 cio_write(cio, 0, 4); /* Sample Size = 0 becase they all have different sizes */
520 cio_write(cio, tk->num_samples, 4); /* Sample Count */
522 for (i = 0; i < tk->num_samples; i++) {
523 cio_write(cio, tk->sample[i].sample_size, 4);
527 box.length = cio_tell(cio) - box.init_pos;
528 cio_seek(cio, box.init_pos);
529 cio_write(cio, box.length, 4); /* L */
530 cio_seek(cio, box.init_pos + box.length);
539 int mj2_read_stsz(mj2_tk_t * tk, opj_cio_t *cio)
545 mj2_read_boxhdr(&box, cio); /* Box Size */
546 if (MJ2_STSZ != box.type) {
547 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSZ Marker\n");
552 if (0 != cio_read(cio, 1)) { /* Version = 0 */
553 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSZ box\n");
557 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
558 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSZ box. Expected flag 0\n");
562 sample_size = cio_read(cio, 4);
564 if (sample_size != 0) { /* Samples do have the same size */
565 tk->same_sample_size = 1;
566 for (i = 0; i < tk->num_samples; i++) {
567 tk->sample[i].sample_size = sample_size;
569 cio_skip(cio,4); /* Sample count = 1 */
571 tk->same_sample_size = 0;
572 if (tk->num_samples != cio_read(cio, 4)) { /* Sample count */
573 opj_event_msg(cio->cinfo, EVT_ERROR,
574 "Error in STSZ box. Expected that sample-count is number of samples in track\n");
577 for (i = 0; i < tk->num_samples; i++) {
578 tk->sample[i].sample_size = cio_read(cio, 4); /* Sample Size */
581 if (cio_tell(cio) - box.init_pos != box.length) {
582 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSZ Box size\n");
596 void mj2_write_stsc(mj2_tk_t * tk, opj_cio_t *cio)
601 box.init_pos = cio_tell(cio);
603 cio_write(cio, MJ2_STSC, 4); /* STSC */
605 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
607 cio_write(cio, tk->num_samplestochunk, 4); /* Entry Count */
609 for (i = 0; i < tk->num_samplestochunk; i++) {
610 cio_write(cio, tk->sampletochunk[i].first_chunk, 4); /* First Chunk */
611 cio_write(cio, tk->sampletochunk[i].samples_per_chunk, 4); /* Samples per chunk */
612 cio_write(cio, tk->sampletochunk[i].sample_descr_idx, 4); /* Samples description index */
616 box.length = cio_tell(cio) - box.init_pos;
617 cio_seek(cio, box.init_pos);
618 cio_write(cio, box.length, 4); /* L */
619 cio_seek(cio, box.init_pos + box.length);
628 int mj2_read_stsc(mj2_tk_t * tk, opj_cio_t *cio)
633 mj2_read_boxhdr(&box, cio); /* Box Size */
634 if (MJ2_STSC != box.type) {
635 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSC Marker\n");
640 if (0 != cio_read(cio, 1)) { /* Version = 0 */
641 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSC box\n");
645 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
646 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSC box. Expected flag 0\n");
650 tk->num_samplestochunk = cio_read(cio, 4);
652 tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
654 for (i = 0; i < tk->num_samplestochunk; i++) {
655 tk->sampletochunk[i].first_chunk = cio_read(cio, 4);
656 tk->sampletochunk[i].samples_per_chunk = cio_read(cio, 4);
657 tk->sampletochunk[i].sample_descr_idx = cio_read(cio, 4);
660 mj2_stsc_decompact(tk); /* decompact sample to chunk box */
663 if (cio_tell(cio) - box.init_pos != box.length) {
664 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSC Box size\n");
676 void mj2_write_stts(mj2_tk_t * tk, opj_cio_t *cio)
682 box.init_pos = cio_tell(cio);
684 cio_write(cio, MJ2_STTS, 4); /* STTS */
686 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
688 cio_write(cio, tk->num_tts, 4); /* entry_count */
689 for (i = 0; i < tk->num_tts; i++) {
690 cio_write(cio, tk->tts[i].sample_count, 4); /* Sample-count */
691 cio_write(cio, tk->tts[i].sample_delta, 4); /* Sample-Delta */
694 box.length = cio_tell(cio) - box.init_pos;
695 cio_seek(cio, box.init_pos);
696 cio_write(cio, box.length, 4); /* L */
697 cio_seek(cio, box.init_pos + box.length);
706 int mj2_read_stts(mj2_tk_t * tk, opj_cio_t *cio)
712 mj2_read_boxhdr(&box, cio);
713 if (MJ2_STTS != box.type) {
714 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STTS Marker\n");
719 if (0 != cio_read(cio, 1)) { /* Version = 0 */
720 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STTS box\n");
724 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
725 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STTS box. Expected flag 0\n");
729 tk->num_tts = cio_read(cio, 4);
731 tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
733 for (i = 0; i < tk->num_tts; i++) {
734 tk->tts[i].sample_count = cio_read(cio, 4);
735 tk->tts[i].sample_delta = cio_read(cio, 4);
738 mj2_tts_decompact(tk);
740 if (cio_tell(cio) - box.init_pos != box.length) {
741 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STTS Box size\n");
753 void mj2_write_fiel(mj2_tk_t * tk, opj_cio_t *cio)
758 box.init_pos = cio_tell(cio);
760 cio_write(cio, MJ2_FIEL, 4); /* STTS */
762 cio_write(cio, tk->fieldcount, 1); /* Field count */
763 cio_write(cio, tk->fieldorder, 1); /* Field order */
766 box.length = cio_tell(cio) - box.init_pos;
767 cio_seek(cio, box.init_pos);
768 cio_write(cio, box.length, 4); /* L */
769 cio_seek(cio, box.init_pos + box.length);
778 int mj2_read_fiel(mj2_tk_t * tk, opj_cio_t *cio)
783 mj2_read_boxhdr(&box, cio);
784 if (MJ2_FIEL != box.type) {
785 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FIEL Marker\n");
790 tk->fieldcount = cio_read(cio, 1);
791 tk->fieldorder = cio_read(cio, 1);
793 if (cio_tell(cio) - box.init_pos != box.length) {
794 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FIEL Box size\n");
803 * Original Format Box
806 void mj2_write_orfo(mj2_tk_t * tk, opj_cio_t *cio)
810 box.init_pos = cio_tell(cio);
812 cio_write(cio, MJ2_ORFO, 4);
814 cio_write(cio, tk->or_fieldcount, 1); /* Original Field count */
815 cio_write(cio, tk->or_fieldorder, 1); /* Original Field order */
818 box.length = cio_tell(cio) - box.init_pos;
819 cio_seek(cio, box.init_pos);
820 cio_write(cio, box.length, 4); /* L */
821 cio_seek(cio, box.init_pos + box.length);
827 * Original Format Box
830 int mj2_read_orfo(mj2_tk_t * tk, opj_cio_t *cio)
835 mj2_read_boxhdr(&box, cio);
836 if (MJ2_ORFO != box.type) {
837 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected ORFO Marker\n");
842 tk->or_fieldcount = cio_read(cio, 1);
843 tk->or_fieldorder = cio_read(cio, 1);
845 if (cio_tell(cio) - box.init_pos != box.length) {
846 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with ORFO Box size\n");
858 void mj2_write_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
864 box.init_pos = cio_tell(cio);
866 cio_write(cio, MJ2_JP2P, 4);
868 cio_write(cio, 0, 4); /* Version 0, flags =0 */
870 for (i = 0; i < tk->num_br; i++) {
871 cio_write(cio, tk->br[i], 4);
874 box.length = cio_tell(cio) - box.init_pos;
875 cio_seek(cio, box.init_pos);
876 cio_write(cio, box.length, 4); /* L */
877 cio_seek(cio, box.init_pos + box.length);
886 int mj2_read_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
892 mj2_read_boxhdr(&box, cio);
893 if (MJ2_JP2P != box.type) {
894 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2P Marker\n");
898 if (0 != cio_read(cio, 1)) { /* Version = 0 */
899 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in JP2P box\n");
903 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
904 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in JP2P box. Expected flag 0\n");
909 tk->num_br = (box.length - 12) / 4;
910 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
912 for (i = 0; i < tk->num_br; i++) {
913 tk->br[i] = cio_read(cio, 4);
916 if (cio_tell(cio) - box.init_pos != box.length) {
917 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2P Box size\n");
929 void mj2_write_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
935 box.init_pos = cio_tell(cio);
937 cio_write(cio, MJ2_JP2X, 4);
939 for (i = 0; i < tk->num_jp2x; i++) {
940 cio_write(cio, tk->jp2xdata[i], 1);
943 box.length = cio_tell(cio) - box.init_pos;
944 cio_seek(cio, box.init_pos);
945 cio_write(cio, box.length, 4); /* L */
946 cio_seek(cio, box.init_pos + box.length);
955 int mj2_read_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
961 mj2_read_boxhdr(&box, cio);
962 if (MJ2_JP2X != box.type) {
963 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2X Marker\n");
968 tk->num_jp2x = (box.length - 8);
969 tk->jp2xdata = (unsigned char*) opj_malloc(tk->num_jp2x * sizeof(unsigned char));
971 for (i = 0; i < tk->num_jp2x; i++) {
972 tk->jp2xdata[i] = cio_read(cio, 1);
975 if (cio_tell(cio) - box.init_pos != box.length) {
976 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2X Box size\n");
985 * MJP2 Subsampling Box
988 void mj2_write_jsub(mj2_tk_t * tk, opj_cio_t *cio)
993 box.init_pos = cio_tell(cio);
995 cio_write(cio, MJ2_JSUB, 4);
997 cio_write(cio, tk->hsub, 1);
998 cio_write(cio, tk->vsub, 1);
999 cio_write(cio, tk->hoff, 1);
1000 cio_write(cio, tk->voff, 1);
1002 box.length = cio_tell(cio) - box.init_pos;
1003 cio_seek(cio, box.init_pos);
1004 cio_write(cio, box.length, 4); /* L */
1005 cio_seek(cio, box.init_pos + box.length);
1011 * MJP2 Subsampling Box
1014 int mj2_read_jsub(mj2_tk_t * tk, opj_cio_t *cio)
1018 mj2_read_boxhdr(&box, cio);
1019 if (MJ2_JSUB != box.type) {
1020 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JSUB Marker\n");
1024 tk->hsub = cio_read(cio, 1);
1025 tk->vsub = cio_read(cio, 1);
1026 tk->hoff = cio_read(cio, 1);;
1027 tk->voff = cio_read(cio, 1);
1029 if (cio_tell(cio) - box.init_pos != box.length) {
1030 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JSUB Box size\n");
1037 * Write the SMJ2 box
1039 * Visual Sample Entry Description
1042 void mj2_write_smj2(mj2_tk_t * tk, opj_cio_t *cio)
1046 box.init_pos = cio_tell(cio);
1048 cio_write(cio, MJ2_MJ2, 4); /* MJ2 */
1050 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1052 cio_write(cio, 1, 4);
1054 cio_write(cio, 0, 2); /* Pre-defined */
1056 cio_write(cio, 0, 2); /* Reserved */
1058 cio_write(cio, 0, 4); /* Pre-defined */
1059 cio_write(cio, 0, 4); /* Pre-defined */
1060 cio_write(cio, 0, 4); /* Pre-defined */
1062 cio_write(cio, tk->w, 2); /* Width */
1063 cio_write(cio, tk->h, 2); /* Height */
1065 cio_write(cio, tk->horizresolution, 4); /* Horizontal resolution */
1066 cio_write(cio, tk->vertresolution, 4); /* Vertical resolution */
1068 cio_write(cio, 0, 4); /* Reserved */
1070 cio_write(cio, 1, 2); /* Pre-defined = 1 */
1072 cio_write(cio, tk->compressorname[0], 4); /* Compressor Name */
1073 cio_write(cio, tk->compressorname[1], 4);
1074 cio_write(cio, tk->compressorname[2], 4);
1075 cio_write(cio, tk->compressorname[3], 4);
1076 cio_write(cio, tk->compressorname[4], 4);
1077 cio_write(cio, tk->compressorname[5], 4);
1078 cio_write(cio, tk->compressorname[6], 4);
1079 cio_write(cio, tk->compressorname[7], 4);
1081 cio_write(cio, tk->depth, 2); /* Depth */
1083 cio_write(cio, 0xffff, 2); /* Pre-defined = -1 */
1085 jp2_write_jp2h(&tk->jp2_struct, cio);
1087 mj2_write_fiel(tk, cio);
1089 if (tk->num_br != 0)
1090 mj2_write_jp2p(tk, cio);
1091 if (tk->num_jp2x != 0)
1092 mj2_write_jp2x(tk, cio);
1094 mj2_write_jsub(tk, cio);
1095 mj2_write_orfo(tk, cio);
1097 box.length = cio_tell(cio) - box.init_pos;
1098 cio_seek(cio, box.init_pos);
1099 cio_write(cio, box.length, 4); /* L */
1100 cio_seek(cio, box.init_pos + box.length);
1106 * Visual Sample Entry Description
1109 int mj2_read_smj2(opj_image_t * img, mj2_tk_t * tk, opj_cio_t *cio)
1114 opj_jp2_color_t color;
1116 mj2_read_boxhdr(&box, cio);
1118 if (MJ2_MJ2 != box.type) {
1119 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n");
1123 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1124 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MJP2 box\n");
1128 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1129 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MJP2 box. Expected flag 0\n");
1135 cio_skip(cio,2); /* Pre-defined */
1137 cio_skip(cio,2); /* Reserved */
1139 cio_skip(cio,4); /* Pre-defined */
1140 cio_skip(cio,4); /* Pre-defined */
1141 cio_skip(cio,4); /* Pre-defined */
1143 tk->w = cio_read(cio, 2); /* Width */
1144 tk->h = cio_read(cio, 2); /* Height */
1146 tk->horizresolution = cio_read(cio, 4); /* Horizontal resolution */
1147 tk->vertresolution = cio_read(cio, 4); /* Vertical resolution */
1149 cio_skip(cio,4); /* Reserved */
1151 cio_skip(cio,2); /* Pre-defined = 1 */
1153 tk->compressorname[0] = cio_read(cio, 4); /* Compressor Name */
1154 tk->compressorname[1] = cio_read(cio, 4);
1155 tk->compressorname[2] = cio_read(cio, 4);
1156 tk->compressorname[3] = cio_read(cio, 4);
1157 tk->compressorname[4] = cio_read(cio, 4);
1158 tk->compressorname[5] = cio_read(cio, 4);
1159 tk->compressorname[6] = cio_read(cio, 4);
1160 tk->compressorname[7] = cio_read(cio, 4);
1162 tk->depth = cio_read(cio, 2); /* Depth */
1164 /* Init std value */
1168 tk->or_fieldcount = 1;
1169 tk->or_fieldorder = 0;
1171 cio_skip(cio,2); /* Pre-defined = -1 */
1172 memset(&color, 0, sizeof(opj_jp2_color_t));
1174 if (!jp2_read_jp2h(&tk->jp2_struct, cio, &color)) {
1175 opj_event_msg(tk->cinfo, EVT_ERROR, "Error reading JP2H Box\n");
1179 tk->jp2_struct.comps = (opj_jp2_comps_t*) opj_malloc(tk->jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
1180 tk->jp2_struct.cl = (unsigned int*) opj_malloc(sizeof(unsigned int));
1185 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
1186 mj2_read_boxhdr(&box2, cio);
1187 cio_seek(cio, box2.init_pos);
1188 switch (box2.type) {
1190 if (mj2_read_fiel(tk, cio))
1195 if (mj2_read_jp2p(tk, cio))
1200 if (mj2_read_jp2x(tk, cio))
1205 if (mj2_read_jsub(tk, cio))
1210 if (mj2_read_orfo(tk, cio))
1215 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MJP2 Box size\n");
1226 * Write the STSD box
1228 * Sample Description
1231 void mj2_write_stsd(mj2_tk_t * tk, opj_cio_t *cio)
1235 box.init_pos = cio_tell(cio);
1237 cio_write(cio, MJ2_STSD, 4); /* STSD */
1239 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1241 cio_write(cio, 1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
1243 if (tk->track_type == 0) {
1244 mj2_write_smj2(tk, cio);
1245 } else if (tk->track_type == 1) {
1248 if (tk->track_type == 2) {
1253 box.length = cio_tell(cio) - box.init_pos;
1254 cio_seek(cio, box.init_pos);
1255 cio_write(cio, box.length, 4); /* L */
1256 cio_seek(cio, box.init_pos + box.length);
1262 * Sample Description
1265 int mj2_read_stsd(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1268 int entry_count, len_2skip;
1272 mj2_read_boxhdr(&box, cio);
1274 if (MJ2_STSD != box.type) {
1275 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSD Marker\n");
1279 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1280 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSD box\n");
1284 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1285 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSD box. Expected flag 0\n");
1289 entry_count = cio_read(cio, 4);
1291 if (tk->track_type == 0) {
1292 for (i = 0; i < entry_count; i++) {
1293 if (mj2_read_smj2(img, tk, cio))
1296 } else if (tk->track_type == 1) {
1297 len_2skip = cio_read(cio, 4); // Not implemented -> skipping box
1298 cio_skip(cio,len_2skip - 4);
1299 } else if (tk->track_type == 2) {
1300 len_2skip = cio_read(cio, 4); // Not implemented -> skipping box
1301 cio_skip(cio,len_2skip - 4);
1305 if (cio_tell(cio) - box.init_pos != box.length) {
1306 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSD Box size\n");
1313 * Write the STBL box
1315 * Sample table box box
1318 void mj2_write_stbl(mj2_tk_t * tk, opj_cio_t *cio)
1322 box.init_pos = cio_tell(cio);
1324 cio_write(cio, MJ2_STBL, 4); /* STBL */
1326 mj2_write_stsd(tk, cio);
1327 mj2_write_stts(tk, cio);
1328 mj2_write_stsc(tk, cio);
1329 mj2_write_stsz(tk, cio);
1330 mj2_write_stco(tk, cio);
1332 box.length = cio_tell(cio) - box.init_pos;
1333 cio_seek(cio, box.init_pos);
1334 cio_write(cio, box.length, 4); /* L */
1335 cio_seek(cio, box.init_pos + box.length);
1341 * Sample table box box
1344 int mj2_read_stbl(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1348 mj2_read_boxhdr(&box, cio);
1349 if (MJ2_STBL != box.type) {
1350 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STBL Marker\n");
1354 if (mj2_read_stsd(tk, img, cio))
1356 if (mj2_read_stts(tk, cio))
1358 if (mj2_read_stsc(tk, cio))
1360 if (mj2_read_stsz(tk, cio))
1362 if (mj2_read_stco(tk, cio))
1365 if (cio_tell(cio) - box.init_pos != box.length) {
1366 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STBL Box size\n");
1378 void mj2_write_url(mj2_tk_t * tk, int url_num, opj_cio_t *cio)
1382 box.init_pos = cio_tell(cio);
1384 cio_write(cio, MJ2_URL, 4); /* URL */
1387 cio_write(cio, 1, 4); /* Version = 0, flags = 1 because stored in same file */
1389 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1390 cio_write(cio, tk->url[url_num - 1].location[0], 4);
1391 cio_write(cio, tk->url[url_num - 1].location[1], 4);
1392 cio_write(cio, tk->url[url_num - 1].location[2], 4);
1393 cio_write(cio, tk->url[url_num - 1].location[3], 4);
1396 box.length = cio_tell(cio) - box.init_pos;
1397 cio_seek(cio, box.init_pos);
1398 cio_write(cio, box.length, 4); /* L */
1399 cio_seek(cio, box.init_pos + box.length);
1408 int mj2_read_url(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1412 mj2_read_boxhdr(&box, cio);
1413 if (MJ2_URL != box.type) {
1414 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URL Marker\n");
1418 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1419 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URL box\n");
1423 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1424 tk->url[urn_num].location[0] = cio_read(cio, 4);
1425 tk->url[urn_num].location[1] = cio_read(cio, 4);
1426 tk->url[urn_num].location[2] = cio_read(cio, 4);
1427 tk->url[urn_num].location[3] = cio_read(cio, 4);
1433 if (cio_tell(cio) - box.init_pos != box.length) {
1434 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URL Box size\n");
1446 void mj2_write_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1450 box.init_pos = cio_tell(cio);
1452 cio_write(cio, MJ2_URN, 4); /* URN */
1454 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1456 cio_write(cio, tk->urn[urn_num].name[0], 4);
1457 cio_write(cio, tk->urn[urn_num].name[1], 4);
1458 cio_write(cio, tk->urn[urn_num].name[2], 4);
1459 cio_write(cio, tk->urn[urn_num].name[3], 4);
1460 cio_write(cio, tk->urn[urn_num].location[0], 4);
1461 cio_write(cio, tk->urn[urn_num].location[1], 4);
1462 cio_write(cio, tk->urn[urn_num].location[2], 4);
1463 cio_write(cio, tk->urn[urn_num].location[3], 4);
1465 box.length = cio_tell(cio) - box.init_pos;
1466 cio_seek(cio, box.init_pos);
1467 cio_write(cio, box.length, 4); /* L */
1468 cio_seek(cio, box.init_pos + box.length);
1477 int mj2_read_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1482 mj2_read_boxhdr(&box, cio);
1483 if (MJ2_URN != box.type) {
1484 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URN Marker\n");
1488 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1489 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URN box\n");
1493 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1494 tk->urn[urn_num].name[0] = cio_read(cio, 4);
1495 tk->urn[urn_num].name[1] = cio_read(cio, 4);
1496 tk->urn[urn_num].name[2] = cio_read(cio, 4);
1497 tk->urn[urn_num].name[3] = cio_read(cio, 4);
1498 tk->urn[urn_num].location[0] = cio_read(cio, 4);
1499 tk->urn[urn_num].location[1] = cio_read(cio, 4);
1500 tk->urn[urn_num].location[2] = cio_read(cio, 4);
1501 tk->urn[urn_num].location[3] = cio_read(cio, 4);
1505 if (cio_tell(cio) - box.init_pos != box.length) {
1506 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URN Box size\n");
1514 * Write the DREF box
1516 * Data reference box
1519 void mj2_write_dref(mj2_tk_t * tk, opj_cio_t *cio)
1524 box.init_pos = cio_tell(cio);
1526 cio_write(cio, MJ2_DREF, 4); /* DREF */
1528 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1530 if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
1531 cio_write(cio, 1, 4); /* entry_count = 1 */
1532 mj2_write_url(tk, 0, cio);
1534 cio_write(cio, tk->num_url + tk->num_urn, 4); /* entry_count */
1536 for (i = 0; i < tk->num_url; i++)
1537 mj2_write_url(tk, i + 1, cio);
1539 for (i = 0; i < tk->num_urn; i++)
1540 mj2_write_urn(tk, i, cio);
1543 box.length = cio_tell(cio) - box.init_pos;
1544 cio_seek(cio, box.init_pos);
1545 cio_write(cio, box.length, 4); /* L */
1546 cio_seek(cio, box.init_pos + box.length);
1552 * Data reference box
1555 int mj2_read_dref(mj2_tk_t * tk, opj_cio_t *cio)
1559 int entry_count, marker;
1562 mj2_read_boxhdr(&box, cio);
1563 if (MJ2_DREF != box.type) {
1564 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DREF Marker\n");
1568 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1569 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in DREF box\n");
1573 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1574 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in DREF box. Expected flag 0\n");
1578 entry_count = cio_read(cio, 4);
1582 for (i = 0; i < entry_count; i++) {
1584 marker = cio_read(cio, 4);
1585 if (marker == MJ2_URL) {
1588 if (mj2_read_url(tk, tk->num_url, cio))
1590 } else if (marker == MJ2_URN) {
1593 if (mj2_read_urn(tk, tk->num_urn, cio))
1596 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n");
1603 if (cio_tell(cio) - box.init_pos != box.length) {
1604 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DREF Box size\n");
1611 * Write the DINF box
1613 * Data information box
1616 void mj2_write_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1620 box.init_pos = cio_tell(cio);
1622 cio_write(cio, MJ2_DINF, 4); /* DINF */
1624 mj2_write_dref(tk, cio);
1626 box.length = cio_tell(cio) - box.init_pos;
1627 cio_seek(cio, box.init_pos);
1628 cio_write(cio, box.length, 4); /* L */
1629 cio_seek(cio, box.init_pos + box.length);
1635 * Data information box
1638 int mj2_read_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1642 mj2_read_boxhdr(&box, cio);
1643 if (MJ2_DINF != box.type) {
1644 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DINF Marker\n");
1648 if (mj2_read_dref(tk, cio))
1651 if (cio_tell(cio) - box.init_pos != box.length) {
1652 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DINF Box size\n");
1659 * Write the VMHD box
1661 * Video Media information box
1664 void mj2_write_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1668 box.init_pos = cio_tell(cio);
1670 cio_write(cio, MJ2_VMHD, 4); /* VMHD */
1672 cio_write(cio, 1, 4); /* Version = 0, flags = 1 */
1674 cio_write(cio, tk->graphicsmode, 2);
1675 cio_write(cio, tk->opcolor[0], 2);
1676 cio_write(cio, tk->opcolor[1], 2);
1677 cio_write(cio, tk->opcolor[2], 2);
1679 box.length = cio_tell(cio) - box.init_pos;
1680 cio_seek(cio, box.init_pos);
1681 cio_write(cio, box.length, 4); /* L */
1682 cio_seek(cio, box.init_pos + box.length);
1688 * Video Media information box
1691 int mj2_read_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1695 mj2_read_boxhdr(&box, cio);
1696 if (MJ2_VMHD != box.type) {
1697 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected VMHD Marker\n");
1701 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1702 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in VMHD box\n");
1706 if (1 != cio_read(cio, 3)) { /* Flags = 1 */
1707 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in VMHD box. Expected flag 1\n");
1712 tk->graphicsmode = cio_read(cio, 2);
1713 tk->opcolor[0] = cio_read(cio, 2);
1714 tk->opcolor[1] = cio_read(cio, 2);
1715 tk->opcolor[2] = cio_read(cio, 2);
1717 if (cio_tell(cio) - box.init_pos != box.length) {
1718 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with VMHD Box size\n");
1725 * Write the SMHD box
1727 * Sound Media information box
1730 void mj2_write_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1734 box.init_pos = cio_tell(cio);
1736 cio_write(cio, MJ2_SMHD, 4); /* SMHD */
1738 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1740 cio_write(cio, tk->balance, 2);
1742 cio_write(cio, 0, 2); /* Reserved */
1744 box.length = cio_tell(cio) - box.init_pos;
1745 cio_seek(cio, box.init_pos);
1746 cio_write(cio, box.length, 4); /* L */
1747 cio_seek(cio, box.init_pos + box.length);
1753 * Sound Media information box
1756 int mj2_read_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1760 mj2_read_boxhdr(&box, cio);
1761 if (MJ2_SMHD != box.type) {
1762 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected SMHD Marker\n");
1766 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1767 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in SMHD box\n");
1771 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1772 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in SMHD box. Expected flag 0\n");
1777 tk->balance = cio_read(cio, 2);
1779 /* Init variables to zero to avoid problems when freeeing memory
1780 The values will possibly be overidded when decoding the track structure */
1786 tk->num_samplestochunk = 0;
1787 tk->num_samples = 0;
1789 cio_skip(cio,2); /* Reserved */
1791 if (cio_tell(cio) - box.init_pos != box.length) {
1792 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with SMHD Box size\n");
1799 * Write the HMHD box
1801 * Hint Media information box
1804 void mj2_write_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1808 box.init_pos = cio_tell(cio);
1810 cio_write(cio, MJ2_HMHD, 4); /* HMHD */
1812 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1814 cio_write(cio, tk->maxPDUsize, 2);
1815 cio_write(cio, tk->avgPDUsize, 2);
1816 cio_write(cio, tk->maxbitrate, 4);
1817 cio_write(cio, tk->avgbitrate, 4);
1818 cio_write(cio, tk->slidingavgbitrate, 4);
1820 box.length = cio_tell(cio) - box.init_pos;
1821 cio_seek(cio, box.init_pos);
1822 cio_write(cio, box.length, 4); /* L */
1823 cio_seek(cio, box.init_pos + box.length);
1829 * Hint Media information box
1832 int mj2_read_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1836 mj2_read_boxhdr(&box, cio);
1837 if (MJ2_HMHD != box.type) {
1838 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HMHD Marker\n");
1842 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1843 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HMHD box\n");
1847 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1848 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HMHD box. Expected flag 0\n");
1853 tk->maxPDUsize = cio_read(cio, 2);
1854 tk->avgPDUsize = cio_read(cio, 2);
1855 tk->maxbitrate = cio_read(cio, 4);
1856 tk->avgbitrate = cio_read(cio, 4);
1857 tk->slidingavgbitrate = cio_read(cio, 4);
1859 /* Init variables to zero to avoid problems when freeeing memory
1860 The values will possibly be overidded when decoding the track structure */
1866 tk->num_samplestochunk = 0;
1867 tk->num_samples = 0;
1870 if (cio_tell(cio) - box.init_pos != box.length) {
1871 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HMHD Box size\n");
1878 * Write the MINF box
1880 * Media information box
1883 void mj2_write_minf(mj2_tk_t * tk, opj_cio_t *cio)
1887 box.init_pos = cio_tell(cio);
1889 cio_write(cio, MJ2_MINF, 4); /* MINF */
1891 if (tk->track_type == 0) {
1892 mj2_write_vmhd(tk, cio);
1893 } else if (tk->track_type == 1) {
1894 mj2_write_smhd(tk, cio);
1895 } else if (tk->track_type == 2) {
1896 mj2_write_hmhd(tk, cio);
1899 mj2_write_dinf(tk, cio);
1900 mj2_write_stbl(tk, cio);
1902 box.length = cio_tell(cio) - box.init_pos;
1903 cio_seek(cio, box.init_pos);
1904 cio_write(cio, box.length, 4); /* L */
1905 cio_seek(cio, box.init_pos + box.length);
1911 * Media information box
1914 int mj2_read_minf(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1917 unsigned int box_type;
1920 mj2_read_boxhdr(&box, cio);
1921 if (MJ2_MINF != box.type) {
1922 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MINF Marker\n");
1927 box_type = cio_read(cio, 4);
1930 if (box_type == MJ2_VMHD) {
1931 if (mj2_read_vmhd(tk, cio))
1933 } else if (box_type == MJ2_SMHD) {
1934 if (mj2_read_smhd(tk, cio))
1936 } else if (box_type == MJ2_HMHD) {
1937 if (mj2_read_hmhd(tk, cio))
1940 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n");
1944 if (mj2_read_dinf(tk, cio))
1947 if (mj2_read_stbl(tk, img, cio))
1950 if (cio_tell(cio) - box.init_pos != box.length) {
1951 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MINF Box size\n");
1958 * Write the HDLR box
1960 * Handler reference box
1963 void mj2_write_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
1967 box.init_pos = cio_tell(cio);
1969 cio_write(cio, MJ2_HDLR, 4); /* HDLR */
1971 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1973 cio_write(cio, 0, 4); /* Predefine */
1975 tk->name = 0; /* The track name is immediately determined by the track type */
1977 if (tk->track_type == 0) {
1978 tk->handler_type = 0x76696465; /* Handler type: vide */
1979 cio_write(cio, tk->handler_type, 4);
1981 cio_write(cio, 0, 4);
1982 cio_write(cio, 0, 4);
1983 cio_write(cio, 0, 4); /* Reserved */
1985 cio_write(cio, 0x76696465, 4);
1986 cio_write(cio, 0x6F206d65, 4);
1987 cio_write(cio, 0x64696120, 4);
1988 cio_write(cio, 0x74726163, 4);
1989 cio_write(cio, 0x6b00, 2); /* String: video media track */
1990 } else if (tk->track_type == 1) {
1991 tk->handler_type = 0x736F756E; /* Handler type: soun */
1992 cio_write(cio, tk->handler_type, 4);
1994 cio_write(cio, 0, 4);
1995 cio_write(cio, 0, 4);
1996 cio_write(cio, 0, 4); /* Reserved */
1998 cio_write(cio, 0x536F756E, 4);
1999 cio_write(cio, 0x6400, 2); /* String: Sound */
2000 } else if (tk->track_type == 2) {
2001 tk->handler_type = 0x68696E74; /* Handler type: hint */
2002 cio_write(cio, tk->handler_type, 4);
2004 cio_write(cio, 0, 4);
2005 cio_write(cio, 0, 4);
2006 cio_write(cio, 0, 4); /* Reserved */
2008 cio_write(cio, 0x48696E74, 4);
2009 cio_write(cio, 0, 2); /* String: Hint */
2012 box.length = cio_tell(cio) - box.init_pos;
2013 cio_seek(cio, box.init_pos);
2014 cio_write(cio, box.length, 4); /* L */
2015 cio_seek(cio, box.init_pos + box.length);
2021 * Handler reference box
2024 int mj2_read_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
2029 mj2_read_boxhdr(&box, cio);
2030 if (MJ2_HDLR != box.type) {
2031 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HDLR Marker\n");
2036 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2037 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HDLR box\n");
2041 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2042 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HDLR box. Expected flag 0\n");
2046 cio_skip(cio,4); /* Reserved */
2048 tk->handler_type = cio_read(cio, 4);
2049 cio_skip(cio,12); /* Reserved */
2051 tk->name_size = box.length - 32;
2053 tk->name = (char*) opj_malloc(tk->name_size * sizeof(char));
2054 for (i = 0; i < tk->name_size; i++) {
2055 tk->name[i] = cio_read(cio, 1); /* Name */
2058 if (cio_tell(cio) - box.init_pos != box.length) {
2059 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HDLR Box size\n");
2066 * Write the MDHD box
2071 void mj2_write_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2076 unsigned int modification_time;
2078 box.init_pos = cio_tell(cio);
2080 cio_write(cio, MJ2_MDHD, 4); /* MDHD */
2082 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2084 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2086 time(<ime); /* Time since 1/1/70 */
2087 modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2089 cio_write(cio, modification_time, 4); /* Modification Time */
2091 cio_write(cio, tk->timescale, 4); /* Timescale */
2095 for (i = 0; i < tk->num_samples; i++)
2096 tk->duration += tk->sample[i].sample_delta;
2098 cio_write(cio, tk->duration, 4); /* Duration */
2100 cio_write(cio, tk->language, 2); /* Language */
2102 cio_write(cio, 0, 2); /* Predefined */
2104 box.length = cio_tell(cio) - box.init_pos;
2105 cio_seek(cio, box.init_pos);
2106 cio_write(cio, box.length, 4); /* L */
2107 cio_seek(cio, box.init_pos + box.length);
2116 int mj2_read_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2120 mj2_read_boxhdr(&box, cio);
2121 if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) { // Kakadu writes MHDR instead of MDHD
2122 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDHD Marker\n");
2126 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2127 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MDHD box\n");
2131 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2132 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MDHD box. Expected flag 0\n");
2137 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2139 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2141 tk->timescale = cio_read(cio, 4); /* Timescale */
2143 tk->duration = cio_read(cio, 4); /* Duration */
2145 tk->language = cio_read(cio, 2); /* Language */
2147 cio_skip(cio,2); /* Predefined */
2149 if (cio_tell(cio) - box.init_pos != box.length) {
2150 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDHD Box size\n");
2157 * Write the MDIA box
2162 void mj2_write_mdia(mj2_tk_t * tk, opj_cio_t *cio)
2166 box.init_pos = cio_tell(cio);
2168 cio_write(cio, MJ2_MDIA, 4); /* MDIA */
2170 mj2_write_mdhd(tk, cio);
2171 mj2_write_hdlr(tk, cio);
2172 mj2_write_minf(tk, cio);
2174 box.length = cio_tell(cio) - box.init_pos;
2175 cio_seek(cio, box.init_pos);
2176 cio_write(cio, box.length, 4); /* L */
2177 cio_seek(cio, box.init_pos + box.length);
2186 int mj2_read_mdia(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2190 mj2_read_boxhdr(&box, cio);
2191 if (MJ2_MDIA != box.type) {
2192 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDIA Marker\n");
2196 if (mj2_read_mdhd(tk, cio))
2198 if (mj2_read_hdlr(tk, cio))
2200 if (mj2_read_minf(tk, img, cio))
2203 if (cio_tell(cio) - box.init_pos != box.length) {
2204 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDIA Box size\n");
2211 * Write the TKHD box
2216 void mj2_write_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2222 box.init_pos = cio_tell(cio);
2225 cio_write(cio, MJ2_TKHD, 4); /* TKHD */
2227 cio_write(cio, 3, 4); /* Version=0, flags=3 */
2229 time(<ime); /* Time since 1/1/70 */
2230 tk->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2232 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2234 cio_write(cio, tk->modification_time, 4); /* Modification Time */
2236 cio_write(cio, tk->track_ID, 4); /* Track ID */
2238 cio_write(cio, 0, 4); /* Reserved */
2242 for (i = 0; i < tk->num_samples; i++)
2243 tk->duration += tk->sample[i].sample_delta;
2245 cio_write(cio, tk->duration, 4); /* Duration */
2247 cio_write(cio, 0, 4); /* Reserved */
2248 cio_write(cio, 0, 4); /* Reserved */
2250 cio_write(cio, tk->layer, 2); /* Layer */
2252 cio_write(cio, 0, 2); /* Predefined */
2254 cio_write(cio, tk->volume, 2); /* Volume */
2256 cio_write(cio, 0, 2); /* Reserved */
2258 cio_write(cio, tk->trans_matrix[0], 4); /* Transformation matrix for track */
2259 cio_write(cio, tk->trans_matrix[1], 4);
2260 cio_write(cio, tk->trans_matrix[2], 4);
2261 cio_write(cio, tk->trans_matrix[3], 4);
2262 cio_write(cio, tk->trans_matrix[4], 4);
2263 cio_write(cio, tk->trans_matrix[5], 4);
2264 cio_write(cio, tk->trans_matrix[6], 4);
2265 cio_write(cio, tk->trans_matrix[7], 4);
2266 cio_write(cio, tk->trans_matrix[8], 4);
2268 cio_write(cio, tk->visual_w, 4); /* Video Visual Width */
2270 cio_write(cio, tk->visual_h, 4); /* Video Visual Height */
2272 box.length = cio_tell(cio) - box.init_pos;
2273 cio_seek(cio, box.init_pos);
2274 cio_write(cio, box.length, 4); /* L */
2275 cio_seek(cio, box.init_pos + box.length);
2284 int mj2_read_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2290 mj2_read_boxhdr(&box, cio);
2292 if (MJ2_TKHD != box.type) {
2293 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TKHD Marker\n");
2297 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2298 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in TKHD box\n");
2302 flag = cio_read(cio, 3);
2304 if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) { /* Flags = 1,2,3 or 4 */
2305 opj_event_msg(cio->cinfo, EVT_ERROR,
2306 "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2310 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2312 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2314 tk->track_ID = cio_read(cio, 4); /* Track ID */
2316 cio_skip(cio,4); /* Reserved */
2318 tk->duration = cio_read(cio, 4); /* Duration */
2320 cio_skip(cio,8); /* Reserved */
2322 tk->layer = cio_read(cio, 2); /* Layer */
2324 cio_read(cio, 2); /* Predefined */
2326 tk->volume = cio_read(cio, 2); /* Volume */
2328 cio_skip(cio,2); /* Reserved */
2330 tk->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for track */
2331 tk->trans_matrix[1] = cio_read(cio, 4);
2332 tk->trans_matrix[2] = cio_read(cio, 4);
2333 tk->trans_matrix[3] = cio_read(cio, 4);
2334 tk->trans_matrix[4] = cio_read(cio, 4);
2335 tk->trans_matrix[5] = cio_read(cio, 4);
2336 tk->trans_matrix[6] = cio_read(cio, 4);
2337 tk->trans_matrix[7] = cio_read(cio, 4);
2338 tk->trans_matrix[8] = cio_read(cio, 4);
2340 tk->visual_w = cio_read(cio, 4); /* Video Visual Width */
2342 tk->visual_h = cio_read(cio, 4); /* Video Visual Height */
2344 if (cio_tell(cio) - box.init_pos != box.length) {
2345 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TKHD Box size\n");
2352 * Write the TRAK box
2357 void mj2_write_trak(mj2_tk_t * tk, opj_cio_t *cio)
2361 box.init_pos = cio_tell(cio);
2364 cio_write(cio, MJ2_TRAK, 4); /* TRAK */
2366 mj2_write_tkhd(tk, cio);
2367 mj2_write_mdia(tk, cio);
2369 box.length = cio_tell(cio) - box.init_pos;
2370 cio_seek(cio, box.init_pos);
2371 cio_write(cio, box.length, 4); /* L */
2372 cio_seek(cio, box.init_pos + box.length);
2381 int mj2_read_trak(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2385 mj2_read_boxhdr(&box, cio);
2386 if (MJ2_TRAK != box.type) {
2387 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TRAK Marker\n");
2390 if (mj2_read_tkhd(tk, cio))
2392 if (mj2_read_mdia(tk, img, cio))
2394 if (cio_tell(cio) - box.init_pos != box.length) {
2395 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TRAK Box\n");
2402 * Write the MVHD box
2407 void mj2_write_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2415 box.init_pos = cio_tell(cio);
2417 cio_write(cio, MJ2_MVHD, 4); /* MVHD */
2419 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2421 time(<ime); /* Time since 1/1/70 */
2422 movie->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2424 cio_write(cio, movie->creation_time, 4); /* Creation Time */
2426 cio_write(cio, movie->modification_time, 4); /* Modification Time */
2428 cio_write(cio, movie->timescale, 4); /* Timescale */
2430 movie->duration = 0;
2432 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2433 mj2_tk_t *tk = &movie->tk[i];
2435 for (j = 0; j < tk->num_samples; j++) {
2436 movie->duration += tk->sample[j].sample_delta;
2440 cio_write(cio, movie->duration, 4);
2442 cio_write(cio, movie->rate, 4); /* Rate to play presentation */
2444 cio_write(cio, movie->volume, 2); /* Volume */
2446 cio_write(cio, 0, 2); /* Reserved */
2447 cio_write(cio, 0, 4); /* Reserved */
2448 cio_write(cio, 0, 4); /* Reserved */
2450 cio_write(cio, movie->trans_matrix[0], 4); /* Transformation matrix for video */
2451 cio_write(cio, movie->trans_matrix[1], 4);
2452 cio_write(cio, movie->trans_matrix[2], 4);
2453 cio_write(cio, movie->trans_matrix[3], 4);
2454 cio_write(cio, movie->trans_matrix[4], 4);
2455 cio_write(cio, movie->trans_matrix[5], 4);
2456 cio_write(cio, movie->trans_matrix[6], 4);
2457 cio_write(cio, movie->trans_matrix[7], 4);
2458 cio_write(cio, movie->trans_matrix[8], 4);
2460 cio_write(cio, 0, 4); /* Pre-defined */
2461 cio_write(cio, 0, 4); /* Pre-defined */
2462 cio_write(cio, 0, 4); /* Pre-defined */
2463 cio_write(cio, 0, 4); /* Pre-defined */
2464 cio_write(cio, 0, 4); /* Pre-defined */
2465 cio_write(cio, 0, 4); /* Pre-defined */
2468 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
2469 if (max_tk_num < movie->tk[i].track_ID)
2470 max_tk_num = movie->tk[i].track_ID;
2473 movie->next_tk_id = max_tk_num + 1;
2475 cio_write(cio, movie->next_tk_id, 4); /* ID of Next track to be added */
2477 box.length = cio_tell(cio) - box.init_pos;
2478 cio_seek(cio, box.init_pos);
2479 cio_write(cio, box.length, 4); /* L */
2480 cio_seek(cio, box.init_pos + box.length);
2489 int mj2_read_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2493 mj2_read_boxhdr(&box, cio);
2494 if (MJ2_MVHD != box.type) {
2495 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MVHD Marker\n");
2500 if (0 != cio_read(cio, 4)) { /* Version = 0, flags = 0 */
2501 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MVHD box\n");
2504 movie->creation_time = cio_read(cio, 4); /* Creation Time */
2506 movie->modification_time = cio_read(cio, 4); /* Modification Time */
2508 movie->timescale = cio_read(cio, 4); /* Timescale */
2510 movie->duration = cio_read(cio, 4); /* Duration */
2512 movie->rate = cio_read(cio, 4); /* Rate to play presentation */
2514 movie->volume = cio_read(cio, 2); /* Volume */
2516 cio_skip(cio,10); /* Reserved */
2518 movie->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for video */
2519 movie->trans_matrix[1] = cio_read(cio, 4);
2520 movie->trans_matrix[2] = cio_read(cio, 4);
2521 movie->trans_matrix[3] = cio_read(cio, 4);
2522 movie->trans_matrix[4] = cio_read(cio, 4);
2523 movie->trans_matrix[5] = cio_read(cio, 4);
2524 movie->trans_matrix[6] = cio_read(cio, 4);
2525 movie->trans_matrix[7] = cio_read(cio, 4);
2526 movie->trans_matrix[8] = cio_read(cio, 4);
2528 cio_skip(cio,24); /* Pre-defined */
2530 movie->next_tk_id = cio_read(cio, 4); /* ID of Next track to be added */
2532 if (cio_tell(cio) - box.init_pos != box.length) {
2533 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MVHD Box Size\n");
2541 * Write the MOOV box
2546 void mj2_write_moov(opj_mj2_t * movie, opj_cio_t *cio)
2551 box.init_pos = cio_tell(cio);
2553 cio_write(cio, MJ2_MOOV, 4); /* MOOV */
2555 mj2_write_mvhd(movie, cio);
2557 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2558 mj2_write_trak(&movie->tk[i], cio);
2561 box.length = cio_tell(cio) - box.init_pos;
2562 cio_seek(cio, box.init_pos);
2563 cio_write(cio, box.length, 4); /* L */
2564 cio_seek(cio, box.init_pos + box.length);
2573 int mj2_read_moov(opj_mj2_t * movie, opj_image_t * img, opj_cio_t *cio)
2579 mj2_read_boxhdr(&box, cio);
2580 if (MJ2_MOOV != box.type) {
2581 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MOOV Marker\n");
2585 if (mj2_read_mvhd(movie, cio))
2588 movie->tk = (mj2_tk_t*) opj_malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2590 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
2591 mj2_tk_t *tk = &movie->tk[i];
2592 tk->cinfo = movie->cinfo;
2593 mj2_read_boxhdr(&box2, cio);
2594 if (box2.type == MJ2_TRAK) {
2595 cio_seek(cio, box2.init_pos);
2596 if (mj2_read_trak(tk, img, cio))
2599 if (tk->track_type == 0) {
2601 } else if (tk->track_type == 1) {
2603 } else if (tk->track_type == 2) {
2606 } else if (box2.type == MJ2_MVEX) {
2607 cio_seek(cio, box2.init_pos);
2608 cio_skip(cio,box2.length);
2611 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2618 int mj2_read_struct(FILE *file, opj_mj2_t *movie) {
2621 unsigned char * src;
2626 /* open a byte stream for reading */
2627 src = (unsigned char*) opj_malloc(300 * sizeof(unsigned char));
2629 /* Assuming that jp and ftyp markers size do
2630 not exceed 300 bytes */
2631 fread(src,300,1, file);
2633 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2635 if (mj2_read_jp(cio))
2637 if (mj2_read_ftyp(movie, cio))
2640 fsresult = fseek(file,cio_tell(cio),SEEK_SET);
2642 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read data after FTYP box\n" );
2646 foffset = cio_tell(cio);
2650 fread(src,30,1,file);
2651 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2652 mj2_read_boxhdr(&box, cio);
2654 while(box.type != MJ2_MOOV) {
2659 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2661 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MDAT box\n" );
2664 foffset += box.length;
2668 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2670 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOF box\n" );
2673 foffset += box.length;
2676 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2678 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read FREE box\n" );
2681 foffset += box.length;
2684 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2686 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read SKIP box\n" );
2689 foffset += box.length;
2692 opj_event_msg(cio->cinfo, EVT_ERROR, "Unknown box in MJ2 stream\n");
2693 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2695 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read end of unknown box\n");
2698 foffset += box.length;
2701 fsresult = fread(src,8,1,file);
2702 if (fsresult != 1) {
2703 opj_event_msg(cio->cinfo, EVT_ERROR, "MOOV box not found in file\n");
2706 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 8);
2707 mj2_read_boxhdr(&box, cio);
2710 fseek(file,foffset,SEEK_SET);
2711 src = (unsigned char*)opj_realloc(src,box.length);
2712 fsresult = fread(src,box.length,1,file);
2713 if (fsresult != 1) {
2714 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOV box\n");
2718 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, box.length);
2720 if (mj2_read_moov(movie, &img, cio))
2727 /* ----------------------------------------------------------------------- */
2728 /* MJ2 decoder interface */
2729 /* ----------------------------------------------------------------------- */
2731 opj_dinfo_t* mj2_create_decompress() {
2733 opj_dinfo_t *dinfo = (opj_dinfo_t*) opj_calloc(1, sizeof(opj_dinfo_t));
2734 if(!dinfo) return NULL;
2736 dinfo->is_decompressor = true;
2738 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2739 dinfo->mj2_handle = mj2;
2741 mj2->cinfo = (opj_common_ptr)dinfo;
2743 mj2->j2k = j2k_create_decompress((opj_common_ptr)dinfo);
2744 dinfo->j2k_handle = mj2->j2k;
2749 void mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters) {
2754 /* setup the J2K decoder parameters */
2755 j2k_setup_decoder((opj_j2k_t*)movie->cinfo->j2k_handle,
2756 &mj2_parameters->j2k_parameters);
2760 void mj2_destroy_decompress(opj_mj2_t *movie) {
2765 if (movie->cinfo->j2k_handle)
2766 j2k_destroy_compress(movie->j2k);
2768 if (movie->num_cl != 0)
2769 opj_free(movie->cl);
2771 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2773 if (tk->name_size != 0)
2775 if (tk->track_type == 0) {// Video track
2776 if (tk->jp2_struct.comps != 0)
2777 opj_free(tk->jp2_struct.comps);
2778 if (tk->jp2_struct.cl != 0)
2779 opj_free(tk->jp2_struct.cl);
2780 if (tk->num_jp2x != 0)
2781 opj_free(tk->jp2xdata);
2784 if (tk->num_url != 0)
2786 if (tk->num_urn != 0)
2788 if (tk->num_br != 0)
2790 if (tk->num_tts != 0)
2792 if (tk->num_chunks != 0)
2793 opj_free(tk->chunk);
2794 if (tk->num_samplestochunk != 0)
2795 opj_free(tk->sampletochunk);
2796 if (tk->num_samples != 0)
2797 opj_free(tk->sample);
2800 opj_free(movie->tk);
2805 /* ----------------------------------------------------------------------- */
2806 /* MJ2 encoder interface */
2807 /* ----------------------------------------------------------------------- */
2810 opj_cinfo_t* mj2_create_compress() {
2812 opj_cinfo_t *cinfo = (opj_cinfo_t*) opj_calloc(1, sizeof(opj_cinfo_t));
2813 if(!cinfo) return NULL;
2815 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2816 cinfo->mj2_handle = mj2;
2818 mj2->cinfo = (opj_common_ptr)cinfo;
2821 mj2->j2k = j2k_create_compress(mj2->cinfo);
2822 cinfo->j2k_handle = mj2->j2k;
2827 void mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters) {
2828 if(movie && parameters) {
2829 opj_jp2_t *jp2_struct;
2831 movie->num_htk = 0; // No hint tracks
2832 movie->num_stk = 0; // No sound tracks
2833 movie->num_vtk = 1; // One video track
2835 movie->brand = MJ2_MJ2; // One brand: MJ2
2836 movie->num_cl = 2; // Two compatible brands: MJ2 and MJ2S
2837 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
2838 movie->cl[0] = MJ2_MJ2;
2839 movie->cl[1] = MJ2_MJ2S;
2840 movie->minversion = 0; // Minimum version: 0
2842 movie->tk = (mj2_tk_t*) opj_malloc(sizeof(mj2_tk_t)); //Memory allocation for the video track
2843 movie->tk[0].track_ID = 1; // Track ID = 1
2844 movie->tk[0].track_type = 0; // Video track
2845 movie->tk[0].Dim[0] = parameters->Dim[0];
2846 movie->tk[0].Dim[1] = parameters->Dim[1];
2847 movie->tk[0].w = parameters->w;
2848 movie->tk[0].h = parameters->h;
2849 movie->tk[0].CbCr_subsampling_dx = parameters->CbCr_subsampling_dx;
2850 movie->tk[0].CbCr_subsampling_dy = parameters->CbCr_subsampling_dy;
2851 movie->tk[0].sample_rate = parameters->frame_rate;
2852 movie->tk[0].name_size = 0;
2853 movie->tk[0].chunk = (mj2_chunk_t*) opj_malloc(sizeof(mj2_chunk_t));
2854 movie->tk[0].sample = (mj2_sample_t*) opj_malloc(sizeof(mj2_sample_t));
2855 movie->tk[0].depth = parameters->prec;
2857 jp2_struct = &movie->tk[0].jp2_struct;
2858 jp2_struct->numcomps = parameters->numcomps; // NC
2859 jp2_struct->comps = (opj_jp2_comps_t*) opj_malloc(jp2_struct->numcomps * sizeof(opj_jp2_comps_t));
2860 jp2_struct->precedence = 0; /* PRECEDENCE*/
2861 jp2_struct->approx = 0; /* APPROX*/
2862 jp2_struct->brand = JP2_JP2; /* BR */
2863 jp2_struct->minversion = 0; /* MinV */
2864 jp2_struct->numcl = 1;
2865 jp2_struct->cl = (unsigned int*) opj_malloc(jp2_struct->numcl * sizeof(unsigned int));
2866 jp2_struct->cl[0] = JP2_JP2; /* CL0 : JP2 */
2867 jp2_struct->C = 7; /* C : Always 7*/
2868 jp2_struct->UnkC = 0; /* UnkC, colorspace specified in colr box*/
2869 jp2_struct->IPR = 0; /* IPR, no intellectual property*/
2870 jp2_struct->w = parameters->w;
2871 jp2_struct->h = parameters->h;
2872 jp2_struct->bpc = 7;
2873 jp2_struct->meth = parameters->meth;
2874 jp2_struct->enumcs = parameters->enumcs;
2878 void mj2_destroy_compress(opj_mj2_t *movie) {
2883 if (movie->cinfo->j2k_handle) {
2884 j2k_destroy_compress(movie->j2k);
2887 if (movie->num_cl != 0)
2888 opj_free(movie->cl);
2890 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2892 if (tk->name_size != 0)
2894 if (tk->track_type == 0) {// Video track
2895 if (tk->jp2_struct.comps != 0)
2896 opj_free(tk->jp2_struct.comps);
2897 if (tk->jp2_struct.cl != 0)
2898 opj_free(tk->jp2_struct.cl);
2899 if (tk->num_jp2x != 0)
2900 opj_free(tk->jp2xdata);
2903 if (tk->num_url != 0)
2905 if (tk->num_urn != 0)
2907 if (tk->num_br != 0)
2909 if (tk->num_tts != 0)
2911 if (tk->num_chunks != 0)
2912 opj_free(tk->chunk);
2913 if (tk->num_samplestochunk != 0)
2914 opj_free(tk->sampletochunk);
2915 if (tk->num_samples != 0)
2916 opj_free(tk->sample);
2919 opj_free(movie->tk);