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
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)
97 movie->brand = MJ2_MJ2;
98 movie->minversion = 0;
100 movie->cl = (unsigned int*) opj_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 */
142 tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
143 tk->sampletochunk[0].first_chunk = 1;
144 tk->sampletochunk[0].samples_per_chunk = 1;
145 tk->sampletochunk[0].sample_descr_idx = 1;
147 if (tk->sample_rate == 0) {
148 opj_event_msg(tk->cinfo, EVT_ERROR,
149 "Error while initializing MJ2 movie: Sample rate of track %d must be different from zero\n",
154 for (j = 0; j < tk->num_samples; j++) {
155 tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
159 tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
160 tk->tts[0].sample_count = tk->num_samples;
161 tk->tts[0].sample_delta = tk->timescale / tk->sample_rate;
163 tk->horizresolution = 0x00480000; /* Horizontal resolution (typically 72) */
164 tk->vertresolution = 0x00480000; /* Vertical resolution (typically 72) */
165 tk->compressorname[0] = 0x0f4d6f74; /* Compressor Name[]: Motion JPEG2000 */
166 tk->compressorname[1] = 0x696f6e20;
167 tk->compressorname[2] = 0x4a504547;
168 tk->compressorname[3] = 0x32303030;
169 tk->compressorname[4] = 0x00120000;
170 tk->compressorname[5] = 0;
171 tk->compressorname[6] = 0x00000042;
172 tk->compressorname[7] = 0x000000DC;
173 tk->num_url = 0; /* Number of URL */
174 tk->num_urn = 0; /* Number of URN */
175 tk->graphicsmode = 0; /* Graphicsmode */
176 tk->opcolor[0] = 0; /* OpColor */
177 tk->opcolor[1] = 0; /* OpColor */
178 tk->opcolor[2] = 0; /* OpColor */
179 tk->creation_time = movie->creation_time; /* Seconds between 1/1/04 and 1/1/70 */
180 tk->language = 0; /* Language (undefined) */
182 tk->volume = 1 << 8; /* Movie volume (default = 0x0100) */
183 tk->trans_matrix[0] = 0x00010000; /* Transformation matrix for track */
184 tk->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
185 tk->trans_matrix[2] = 0;
186 tk->trans_matrix[3] = 0;
187 tk->trans_matrix[4] = 0x00010000;
188 tk->trans_matrix[5] = 0;
189 tk->trans_matrix[6] = 0;
190 tk->trans_matrix[7] = 0;
191 tk->trans_matrix[8] = 0x40000000;
194 tk->or_fieldcount = 1;
195 tk->or_fieldorder = 0;
197 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
199 tk->br[1] = MJ2_J2P0;
201 tk->hsub = 2; /* 4:2:0 */
202 tk->vsub = 2; /* 4:2:0 */
205 tk->visual_w = tk->w << 16;
206 tk->visual_h = tk->h << 16;
217 * Time To Sample box Decompact
220 void mj2_tts_decompact(mj2_tk_t * tk)
224 for (i = 0; i < tk->num_tts; i++) {
225 tk->num_samples += tk->tts[i].sample_count;
228 tk->sample = (mj2_sample_t*) opj_malloc(tk->num_samples * sizeof(mj2_sample_t));
230 for (i = 0; i < tk->num_tts; i++) {
231 for (j = 0; j < tk->tts[i].sample_count; j++) {
232 tk->sample[j].sample_delta = tk->tts[i].sample_delta;
238 * Sample To Chunk box Decompact
241 void mj2_stsc_decompact(mj2_tk_t * tk)
247 if (tk->num_samplestochunk == 1) {
249 (unsigned int) ceil((double) tk->num_samples /
250 (double) tk->sampletochunk[0].samples_per_chunk);
251 tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_chunks * sizeof(mj2_chunk_t));
252 for (k = 0; k < tk->num_chunks; k++) {
253 tk->chunk[k].num_samples = tk->sampletochunk[0].samples_per_chunk;
257 tk->chunk = (mj2_chunk_t*) opj_malloc(tk->num_samples * sizeof(mj2_chunk_t));
259 for (i = 0; i < tk->num_samplestochunk -1 ; i++) {
260 for (j = tk->sampletochunk[i].first_chunk - 1;
261 j < tk->sampletochunk[i + 1].first_chunk - 1; j++) {
262 tk->chunk[j].num_samples = tk->sampletochunk[i].samples_per_chunk;
264 sampleno += tk->chunk[j].num_samples;
267 tk->num_chunks += (int)(tk->num_samples - sampleno) / tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
268 for (k = tk->sampletochunk[tk->num_samplestochunk - 1].first_chunk - 1;
269 k < tk->num_chunks; k++) {
270 tk->chunk[k].num_samples =
271 tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
273 tk->chunk = (mj2_chunk_t*)
274 opj_realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
281 * Chunk offset box Decompact
284 void mj2_stco_decompact(mj2_tk_t * tk)
289 int intra_chunk_offset;
291 for (i = 0; i < tk->num_chunks; i++) {
292 intra_chunk_offset = 0;
293 for (j = 0; j < tk->chunk[i].num_samples; j++) {
294 tk->sample[k].offset = intra_chunk_offset + tk->chunk[i].offset;
295 intra_chunk_offset += tk->sample[k].sample_size;
307 void mj2_write_jp(opj_cio_t *cio)
310 box.init_pos = cio_tell(cio);
313 cio_write(cio, MJ2_JP, 4); /* JP */
314 cio_write(cio, 0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
316 box.length = cio_tell(cio) - box.init_pos;
317 cio_seek(cio, box.init_pos);
318 cio_write(cio, box.length, 4);
319 cio_seek(cio, box.init_pos + box.length);
325 * JPEG 2000 signature
328 int mj2_read_jp(opj_cio_t *cio)
332 mj2_read_boxhdr(&box, cio);
333 if (MJ2_JP != box.type) { /* Check Marker */
334 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP Marker\n");
337 if (0x0d0a870a != cio_read(cio, 4)) { /* read the 0x0d0a870a required in a JP box */
338 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Marker\n");
341 if (cio_tell(cio) - box.init_pos != box.length) { /* Check box length */
342 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP Box size \n");
355 void mj2_write_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
359 box.init_pos = cio_tell(cio);
362 cio_write(cio, MJ2_FTYP, 4); /* FTYP */
363 cio_write(cio, movie->brand, 4); /* BR */
364 cio_write(cio, movie->minversion, 4); /* MinV */
366 for (i = 0; i < movie->num_cl; i++)
367 cio_write(cio, movie->cl[i], 4); /* CL */
369 box.length = cio_tell(cio) - box.init_pos;
370 cio_seek(cio, box.init_pos);
371 cio_write(cio, box.length, 4); /* Length */
372 cio_seek(cio, box.init_pos + box.length);
381 int mj2_read_ftyp(opj_mj2_t * movie, opj_cio_t *cio)
386 mj2_read_boxhdr(&box, cio); /* Box Size */
387 if (MJ2_FTYP != box.type) {
388 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FTYP Marker\n");
392 movie->brand = cio_read(cio, 4); /* BR */
393 movie->minversion = cio_read(cio, 4); /* MinV */
394 movie->num_cl = (box.length - 16) / 4;
395 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
397 for (i = movie->num_cl - 1; i > -1; i--)
398 movie->cl[i] = cio_read(cio, 4); /* CLi */
400 if (cio_tell(cio) - box.init_pos != box.length) {
401 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FTYP Box\n");
414 void mj2_write_stco(mj2_tk_t * tk, opj_cio_t *cio)
419 box.init_pos = cio_tell(cio);
421 cio_write(cio, MJ2_STCO, 4); /* STCO */
423 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
425 cio_write(cio, tk->num_chunks, 4); /* Entry Count */
427 for (i = 0; i < tk->num_chunks; i++) {
428 cio_write(cio, tk->chunk[i].offset, 4); /* Entry offset */
431 box.length = cio_tell(cio) - box.init_pos;
432 cio_seek(cio, box.init_pos);
433 cio_write(cio, box.length, 4); /* L */
434 cio_seek(cio, box.init_pos + box.length);
443 int mj2_read_stco(mj2_tk_t * tk, opj_cio_t *cio)
448 mj2_read_boxhdr(&box, cio); /* Box Size */
449 if (MJ2_STCO != box.type) {
450 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STCO Marker\n");
454 if (0 != cio_read(cio, 1)) { /* Version = 0 */
455 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STCO box\n");
459 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
460 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STCO box. Expected flag 0\n");
465 if (cio_read(cio, 4) != tk->num_chunks) {
466 opj_event_msg(cio->cinfo, EVT_ERROR,
467 "Error in STCO box: expecting same amount of entry-count as chunks \n");
469 for (i = 0; i < tk->num_chunks; i++) {
470 tk->chunk[i].offset = cio_read(cio, 4); /* Entry offset */
474 mj2_stco_decompact(tk);
477 if (cio_tell(cio) - box.init_pos != box.length) {
478 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STCO Box size\n");
490 void mj2_write_stsz(mj2_tk_t * tk, opj_cio_t *cio)
495 box.init_pos = cio_tell(cio);
497 cio_write(cio, MJ2_STSZ, 4); /* STSZ */
499 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
501 if (tk->same_sample_size == 1) { /* If they all have the same size */
502 cio_write(cio, tk->sample[0].sample_size, 4); /* Size */
504 cio_write(cio, 1, 4); /* Entry count = 1 */
508 cio_write(cio, 0, 4); /* Sample Size = 0 becase they all have different sizes */
510 cio_write(cio, tk->num_samples, 4); /* Sample Count */
512 for (i = 0; i < tk->num_samples; i++) {
513 cio_write(cio, tk->sample[i].sample_size, 4);
517 box.length = cio_tell(cio) - box.init_pos;
518 cio_seek(cio, box.init_pos);
519 cio_write(cio, box.length, 4); /* L */
520 cio_seek(cio, box.init_pos + box.length);
529 int mj2_read_stsz(mj2_tk_t * tk, opj_cio_t *cio)
535 mj2_read_boxhdr(&box, cio); /* Box Size */
536 if (MJ2_STSZ != box.type) {
537 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSZ Marker\n");
542 if (0 != cio_read(cio, 1)) { /* Version = 0 */
543 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSZ box\n");
547 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
548 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSZ box. Expected flag 0\n");
552 sample_size = cio_read(cio, 4);
554 if (sample_size != 0) { /* Samples do have the same size */
555 tk->same_sample_size = 1;
556 for (i = 0; i < tk->num_samples; i++) {
557 tk->sample[i].sample_size = sample_size;
559 cio_skip(cio,4); /* Sample count = 1 */
561 tk->same_sample_size = 0;
562 if (tk->num_samples != cio_read(cio, 4)) { /* Sample count */
563 opj_event_msg(cio->cinfo, EVT_ERROR,
564 "Error in STSZ box. Expected that sample-count is number of samples in track\n");
567 for (i = 0; i < tk->num_samples; i++) {
568 tk->sample[i].sample_size = cio_read(cio, 4); /* Sample Size */
571 if (cio_tell(cio) - box.init_pos != box.length) {
572 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSZ Box size\n");
586 void mj2_write_stsc(mj2_tk_t * tk, opj_cio_t *cio)
591 box.init_pos = cio_tell(cio);
593 cio_write(cio, MJ2_STSC, 4); /* STSC */
595 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
597 cio_write(cio, tk->num_samplestochunk, 4); /* Entry Count */
599 for (i = 0; i < tk->num_samplestochunk; i++) {
600 cio_write(cio, tk->sampletochunk[i].first_chunk, 4); /* First Chunk */
601 cio_write(cio, tk->sampletochunk[i].samples_per_chunk, 4); /* Samples per chunk */
602 cio_write(cio, tk->sampletochunk[i].sample_descr_idx, 4); /* Samples description index */
606 box.length = cio_tell(cio) - box.init_pos;
607 cio_seek(cio, box.init_pos);
608 cio_write(cio, box.length, 4); /* L */
609 cio_seek(cio, box.init_pos + box.length);
618 int mj2_read_stsc(mj2_tk_t * tk, opj_cio_t *cio)
623 mj2_read_boxhdr(&box, cio); /* Box Size */
624 if (MJ2_STSC != box.type) {
625 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSC Marker\n");
630 if (0 != cio_read(cio, 1)) { /* Version = 0 */
631 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSC box\n");
635 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
636 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSC box. Expected flag 0\n");
640 tk->num_samplestochunk = cio_read(cio, 4);
642 tk->sampletochunk = (mj2_sampletochunk_t*) opj_malloc(tk->num_samplestochunk * sizeof(mj2_sampletochunk_t));
644 for (i = 0; i < tk->num_samplestochunk; i++) {
645 tk->sampletochunk[i].first_chunk = cio_read(cio, 4);
646 tk->sampletochunk[i].samples_per_chunk = cio_read(cio, 4);
647 tk->sampletochunk[i].sample_descr_idx = cio_read(cio, 4);
650 mj2_stsc_decompact(tk); /* decompact sample to chunk box */
653 if (cio_tell(cio) - box.init_pos != box.length) {
654 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSC Box size\n");
666 void mj2_write_stts(mj2_tk_t * tk, opj_cio_t *cio)
672 box.init_pos = cio_tell(cio);
674 cio_write(cio, MJ2_STTS, 4); /* STTS */
676 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
678 cio_write(cio, tk->num_tts, 4); /* entry_count */
679 for (i = 0; i < tk->num_tts; i++) {
680 cio_write(cio, tk->tts[i].sample_count, 4); /* Sample-count */
681 cio_write(cio, tk->tts[i].sample_delta, 4); /* Sample-Delta */
684 box.length = cio_tell(cio) - box.init_pos;
685 cio_seek(cio, box.init_pos);
686 cio_write(cio, box.length, 4); /* L */
687 cio_seek(cio, box.init_pos + box.length);
696 int mj2_read_stts(mj2_tk_t * tk, opj_cio_t *cio)
702 mj2_read_boxhdr(&box, cio);
703 if (MJ2_STTS != box.type) {
704 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STTS Marker\n");
709 if (0 != cio_read(cio, 1)) { /* Version = 0 */
710 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STTS box\n");
714 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
715 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STTS box. Expected flag 0\n");
719 tk->num_tts = cio_read(cio, 4);
721 tk->tts = (mj2_tts_t*) opj_malloc(tk->num_tts * sizeof(mj2_tts_t));
723 for (i = 0; i < tk->num_tts; i++) {
724 tk->tts[i].sample_count = cio_read(cio, 4);
725 tk->tts[i].sample_delta = cio_read(cio, 4);
728 mj2_tts_decompact(tk);
730 if (cio_tell(cio) - box.init_pos != box.length) {
731 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STTS Box size\n");
743 void mj2_write_fiel(mj2_tk_t * tk, opj_cio_t *cio)
748 box.init_pos = cio_tell(cio);
750 cio_write(cio, MJ2_FIEL, 4); /* STTS */
752 cio_write(cio, tk->fieldcount, 1); /* Field count */
753 cio_write(cio, tk->fieldorder, 1); /* Field order */
756 box.length = cio_tell(cio) - box.init_pos;
757 cio_seek(cio, box.init_pos);
758 cio_write(cio, box.length, 4); /* L */
759 cio_seek(cio, box.init_pos + box.length);
768 int mj2_read_fiel(mj2_tk_t * tk, opj_cio_t *cio)
773 mj2_read_boxhdr(&box, cio);
774 if (MJ2_FIEL != box.type) {
775 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected FIEL Marker\n");
780 tk->fieldcount = cio_read(cio, 1);
781 tk->fieldorder = cio_read(cio, 1);
783 if (cio_tell(cio) - box.init_pos != box.length) {
784 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with FIEL Box size\n");
793 * Original Format Box
796 void mj2_write_orfo(mj2_tk_t * tk, opj_cio_t *cio)
800 box.init_pos = cio_tell(cio);
802 cio_write(cio, MJ2_ORFO, 4);
804 cio_write(cio, tk->or_fieldcount, 1); /* Original Field count */
805 cio_write(cio, tk->or_fieldorder, 1); /* Original Field order */
808 box.length = cio_tell(cio) - box.init_pos;
809 cio_seek(cio, box.init_pos);
810 cio_write(cio, box.length, 4); /* L */
811 cio_seek(cio, box.init_pos + box.length);
817 * Original Format Box
820 int mj2_read_orfo(mj2_tk_t * tk, opj_cio_t *cio)
825 mj2_read_boxhdr(&box, cio);
826 if (MJ2_ORFO != box.type) {
827 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected ORFO Marker\n");
832 tk->or_fieldcount = cio_read(cio, 1);
833 tk->or_fieldorder = cio_read(cio, 1);
835 if (cio_tell(cio) - box.init_pos != box.length) {
836 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with ORFO Box size\n");
848 void mj2_write_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
854 box.init_pos = cio_tell(cio);
856 cio_write(cio, MJ2_JP2P, 4);
858 cio_write(cio, 0, 4); /* Version 0, flags =0 */
860 for (i = 0; i < tk->num_br; i++) {
861 cio_write(cio, tk->br[i], 4);
864 box.length = cio_tell(cio) - box.init_pos;
865 cio_seek(cio, box.init_pos);
866 cio_write(cio, box.length, 4); /* L */
867 cio_seek(cio, box.init_pos + box.length);
876 int mj2_read_jp2p(mj2_tk_t * tk, opj_cio_t *cio)
882 mj2_read_boxhdr(&box, cio);
883 if (MJ2_JP2P != box.type) {
884 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2P Marker\n");
888 if (0 != cio_read(cio, 1)) { /* Version = 0 */
889 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in JP2P box\n");
893 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
894 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in JP2P box. Expected flag 0\n");
899 tk->num_br = (box.length - 12) / 4;
900 tk->br = (unsigned int*) opj_malloc(tk->num_br * sizeof(unsigned int));
902 for (i = 0; i < tk->num_br; i++) {
903 tk->br[i] = cio_read(cio, 4);
906 if (cio_tell(cio) - box.init_pos != box.length) {
907 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2P Box size\n");
919 void mj2_write_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
925 box.init_pos = cio_tell(cio);
927 cio_write(cio, MJ2_JP2X, 4);
929 for (i = 0; i < tk->num_jp2x; i++) {
930 cio_write(cio, tk->jp2xdata[i], 1);
933 box.length = cio_tell(cio) - box.init_pos;
934 cio_seek(cio, box.init_pos);
935 cio_write(cio, box.length, 4); /* L */
936 cio_seek(cio, box.init_pos + box.length);
945 int mj2_read_jp2x(mj2_tk_t * tk, opj_cio_t *cio)
951 mj2_read_boxhdr(&box, cio);
952 if (MJ2_JP2X != box.type) {
953 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JP2X Marker\n");
958 tk->num_jp2x = (box.length - 8);
959 tk->jp2xdata = (unsigned char*) opj_malloc(tk->num_jp2x * sizeof(unsigned char));
961 for (i = 0; i < tk->num_jp2x; i++) {
962 tk->jp2xdata[i] = cio_read(cio, 1);
965 if (cio_tell(cio) - box.init_pos != box.length) {
966 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JP2X Box size\n");
975 * MJP2 Subsampling Box
978 void mj2_write_jsub(mj2_tk_t * tk, opj_cio_t *cio)
983 box.init_pos = cio_tell(cio);
985 cio_write(cio, MJ2_JSUB, 4);
987 cio_write(cio, tk->hsub, 1);
988 cio_write(cio, tk->vsub, 1);
989 cio_write(cio, tk->hoff, 1);
990 cio_write(cio, tk->voff, 1);
992 box.length = cio_tell(cio) - box.init_pos;
993 cio_seek(cio, box.init_pos);
994 cio_write(cio, box.length, 4); /* L */
995 cio_seek(cio, box.init_pos + box.length);
1001 * MJP2 Subsampling Box
1004 int mj2_read_jsub(mj2_tk_t * tk, opj_cio_t *cio)
1008 mj2_read_boxhdr(&box, cio);
1009 if (MJ2_JSUB != box.type) {
1010 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected JSUB Marker\n");
1014 tk->hsub = cio_read(cio, 1);
1015 tk->vsub = cio_read(cio, 1);
1016 tk->hoff = cio_read(cio, 1);;
1017 tk->voff = cio_read(cio, 1);
1019 if (cio_tell(cio) - box.init_pos != box.length) {
1020 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with JSUB Box size\n");
1027 * Write the SMJ2 box
1029 * Visual Sample Entry Description
1032 void mj2_write_smj2(mj2_tk_t * tk, opj_cio_t *cio)
1036 box.init_pos = cio_tell(cio);
1038 cio_write(cio, MJ2_MJ2, 4); /* MJ2 */
1040 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1042 cio_write(cio, 1, 4);
1044 cio_write(cio, 0, 2); /* Pre-defined */
1046 cio_write(cio, 0, 2); /* Reserved */
1048 cio_write(cio, 0, 4); /* Pre-defined */
1049 cio_write(cio, 0, 4); /* Pre-defined */
1050 cio_write(cio, 0, 4); /* Pre-defined */
1052 cio_write(cio, tk->w, 2); /* Width */
1053 cio_write(cio, tk->h, 2); /* Height */
1055 cio_write(cio, tk->horizresolution, 4); /* Horizontal resolution */
1056 cio_write(cio, tk->vertresolution, 4); /* Vertical resolution */
1058 cio_write(cio, 0, 4); /* Reserved */
1060 cio_write(cio, 1, 2); /* Pre-defined = 1 */
1062 cio_write(cio, tk->compressorname[0], 4); /* Compressor Name */
1063 cio_write(cio, tk->compressorname[1], 4);
1064 cio_write(cio, tk->compressorname[2], 4);
1065 cio_write(cio, tk->compressorname[3], 4);
1066 cio_write(cio, tk->compressorname[4], 4);
1067 cio_write(cio, tk->compressorname[5], 4);
1068 cio_write(cio, tk->compressorname[6], 4);
1069 cio_write(cio, tk->compressorname[7], 4);
1071 cio_write(cio, tk->depth, 2); /* Depth */
1073 cio_write(cio, 0xffff, 2); /* Pre-defined = -1 */
1075 jp2_write_jp2h(&tk->jp2_struct, cio);
1077 mj2_write_fiel(tk, cio);
1079 if (tk->num_br != 0)
1080 mj2_write_jp2p(tk, cio);
1081 if (tk->num_jp2x != 0)
1082 mj2_write_jp2x(tk, cio);
1084 mj2_write_jsub(tk, cio);
1085 mj2_write_orfo(tk, cio);
1087 box.length = cio_tell(cio) - box.init_pos;
1088 cio_seek(cio, box.init_pos);
1089 cio_write(cio, box.length, 4); /* L */
1090 cio_seek(cio, box.init_pos + box.length);
1096 * Visual Sample Entry Description
1099 int mj2_read_smj2(opj_image_t * img, mj2_tk_t * tk, opj_cio_t *cio)
1105 mj2_read_boxhdr(&box, cio);
1107 if (MJ2_MJ2 != box.type) {
1108 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n");
1112 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1113 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MJP2 box\n");
1117 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1118 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MJP2 box. Expected flag 0\n");
1124 cio_skip(cio,2); /* Pre-defined */
1126 cio_skip(cio,2); /* Reserved */
1128 cio_skip(cio,4); /* Pre-defined */
1129 cio_skip(cio,4); /* Pre-defined */
1130 cio_skip(cio,4); /* Pre-defined */
1132 tk->w = cio_read(cio, 2); /* Width */
1133 tk->h = cio_read(cio, 2); /* Height */
1135 tk->horizresolution = cio_read(cio, 4); /* Horizontal resolution */
1136 tk->vertresolution = cio_read(cio, 4); /* Vertical resolution */
1138 cio_skip(cio,4); /* Reserved */
1140 cio_skip(cio,2); /* Pre-defined = 1 */
1142 tk->compressorname[0] = cio_read(cio, 4); /* Compressor Name */
1143 tk->compressorname[1] = cio_read(cio, 4);
1144 tk->compressorname[2] = cio_read(cio, 4);
1145 tk->compressorname[3] = cio_read(cio, 4);
1146 tk->compressorname[4] = cio_read(cio, 4);
1147 tk->compressorname[5] = cio_read(cio, 4);
1148 tk->compressorname[6] = cio_read(cio, 4);
1149 tk->compressorname[7] = cio_read(cio, 4);
1151 tk->depth = cio_read(cio, 2); /* Depth */
1153 /* Init std value */
1157 tk->or_fieldcount = 1;
1158 tk->or_fieldorder = 0;
1160 cio_skip(cio,2); /* Pre-defined = -1 */
1162 if (!jp2_read_jp2h(&tk->jp2_struct, cio)) {
1163 opj_event_msg(tk->cinfo, EVT_ERROR, "Error reading JP2H Box\n");
1167 tk->jp2_struct.comps = (opj_jp2_comps_t*) opj_malloc(tk->jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
1168 tk->jp2_struct.cl = (unsigned int*) opj_malloc(sizeof(unsigned int));
1173 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
1174 mj2_read_boxhdr(&box2, cio);
1175 cio_seek(cio, box2.init_pos);
1176 switch (box2.type) {
1178 if (mj2_read_fiel(tk, cio))
1183 if (mj2_read_jp2p(tk, cio))
1188 if (mj2_read_jp2x(tk, cio))
1193 if (mj2_read_jsub(tk, cio))
1198 if (mj2_read_orfo(tk, cio))
1203 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MJP2 Box size\n");
1214 * Write the STSD box
1216 * Sample Description
1219 void mj2_write_stsd(mj2_tk_t * tk, opj_cio_t *cio)
1223 box.init_pos = cio_tell(cio);
1225 cio_write(cio, MJ2_STSD, 4); /* STSD */
1227 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1229 cio_write(cio, 1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
1231 if (tk->track_type == 0) {
1232 mj2_write_smj2(tk, cio);
1233 } else if (tk->track_type == 1) {
1236 if (tk->track_type == 2) {
1241 box.length = cio_tell(cio) - box.init_pos;
1242 cio_seek(cio, box.init_pos);
1243 cio_write(cio, box.length, 4); /* L */
1244 cio_seek(cio, box.init_pos + box.length);
1250 * Sample Description
1253 int mj2_read_stsd(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1256 int entry_count, len_2skip;
1260 mj2_read_boxhdr(&box, cio);
1262 if (MJ2_STSD != box.type) {
1263 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSD Marker\n");
1267 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1268 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSD box\n");
1272 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1273 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSD box. Expected flag 0\n");
1277 entry_count = cio_read(cio, 4);
1279 if (tk->track_type == 0) {
1280 for (i = 0; i < entry_count; i++) {
1281 if (mj2_read_smj2(img, tk, cio))
1284 } else if (tk->track_type == 1) {
1285 len_2skip = cio_read(cio, 4); // Not implemented -> skipping box
1286 cio_skip(cio,len_2skip - 4);
1287 } else if (tk->track_type == 2) {
1288 len_2skip = cio_read(cio, 4); // Not implemented -> skipping box
1289 cio_skip(cio,len_2skip - 4);
1293 if (cio_tell(cio) - box.init_pos != box.length) {
1294 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSD Box size\n");
1301 * Write the STBL box
1303 * Sample table box box
1306 void mj2_write_stbl(mj2_tk_t * tk, opj_cio_t *cio)
1310 box.init_pos = cio_tell(cio);
1312 cio_write(cio, MJ2_STBL, 4); /* STBL */
1314 mj2_write_stsd(tk, cio);
1315 mj2_write_stts(tk, cio);
1316 mj2_write_stsc(tk, cio);
1317 mj2_write_stsz(tk, cio);
1318 mj2_write_stco(tk, cio);
1320 box.length = cio_tell(cio) - box.init_pos;
1321 cio_seek(cio, box.init_pos);
1322 cio_write(cio, box.length, 4); /* L */
1323 cio_seek(cio, box.init_pos + box.length);
1329 * Sample table box box
1332 int mj2_read_stbl(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1336 mj2_read_boxhdr(&box, cio);
1337 if (MJ2_STBL != box.type) {
1338 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STBL Marker\n");
1342 if (mj2_read_stsd(tk, img, cio))
1344 if (mj2_read_stts(tk, cio))
1346 if (mj2_read_stsc(tk, cio))
1348 if (mj2_read_stsz(tk, cio))
1350 if (mj2_read_stco(tk, cio))
1353 if (cio_tell(cio) - box.init_pos != box.length) {
1354 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STBL Box size\n");
1366 void mj2_write_url(mj2_tk_t * tk, int url_num, opj_cio_t *cio)
1370 box.init_pos = cio_tell(cio);
1372 cio_write(cio, MJ2_URL, 4); /* URL */
1375 cio_write(cio, 1, 4); /* Version = 0, flags = 1 because stored in same file */
1377 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1378 cio_write(cio, tk->url[url_num - 1].location[0], 4);
1379 cio_write(cio, tk->url[url_num - 1].location[1], 4);
1380 cio_write(cio, tk->url[url_num - 1].location[2], 4);
1381 cio_write(cio, tk->url[url_num - 1].location[3], 4);
1384 box.length = cio_tell(cio) - box.init_pos;
1385 cio_seek(cio, box.init_pos);
1386 cio_write(cio, box.length, 4); /* L */
1387 cio_seek(cio, box.init_pos + box.length);
1396 int mj2_read_url(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1400 mj2_read_boxhdr(&box, cio);
1401 if (MJ2_URL != box.type) {
1402 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URL Marker\n");
1406 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1407 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URL box\n");
1411 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1412 tk->url[urn_num].location[0] = cio_read(cio, 4);
1413 tk->url[urn_num].location[1] = cio_read(cio, 4);
1414 tk->url[urn_num].location[2] = cio_read(cio, 4);
1415 tk->url[urn_num].location[3] = cio_read(cio, 4);
1421 if (cio_tell(cio) - box.init_pos != box.length) {
1422 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URL Box size\n");
1434 void mj2_write_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1438 box.init_pos = cio_tell(cio);
1440 cio_write(cio, MJ2_URN, 4); /* URN */
1442 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1444 cio_write(cio, tk->urn[urn_num].name[0], 4);
1445 cio_write(cio, tk->urn[urn_num].name[1], 4);
1446 cio_write(cio, tk->urn[urn_num].name[2], 4);
1447 cio_write(cio, tk->urn[urn_num].name[3], 4);
1448 cio_write(cio, tk->urn[urn_num].location[0], 4);
1449 cio_write(cio, tk->urn[urn_num].location[1], 4);
1450 cio_write(cio, tk->urn[urn_num].location[2], 4);
1451 cio_write(cio, tk->urn[urn_num].location[3], 4);
1453 box.length = cio_tell(cio) - box.init_pos;
1454 cio_seek(cio, box.init_pos);
1455 cio_write(cio, box.length, 4); /* L */
1456 cio_seek(cio, box.init_pos + box.length);
1465 int mj2_read_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1470 mj2_read_boxhdr(&box, cio);
1471 if (MJ2_URN != box.type) {
1472 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URN Marker\n");
1476 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1477 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URN box\n");
1481 if (1 != cio_read(cio, 3)) { /* If flags = 1 --> media data in file */
1482 tk->urn[urn_num].name[0] = cio_read(cio, 4);
1483 tk->urn[urn_num].name[1] = cio_read(cio, 4);
1484 tk->urn[urn_num].name[2] = cio_read(cio, 4);
1485 tk->urn[urn_num].name[3] = cio_read(cio, 4);
1486 tk->urn[urn_num].location[0] = cio_read(cio, 4);
1487 tk->urn[urn_num].location[1] = cio_read(cio, 4);
1488 tk->urn[urn_num].location[2] = cio_read(cio, 4);
1489 tk->urn[urn_num].location[3] = cio_read(cio, 4);
1493 if (cio_tell(cio) - box.init_pos != box.length) {
1494 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URN Box size\n");
1502 * Write the DREF box
1504 * Data reference box
1507 void mj2_write_dref(mj2_tk_t * tk, opj_cio_t *cio)
1512 box.init_pos = cio_tell(cio);
1514 cio_write(cio, MJ2_DREF, 4); /* DREF */
1516 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1518 if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
1519 cio_write(cio, 1, 4); /* entry_count = 1 */
1520 mj2_write_url(tk, 0, cio);
1522 cio_write(cio, tk->num_url + tk->num_urn, 4); /* entry_count */
1524 for (i = 0; i < tk->num_url; i++)
1525 mj2_write_url(tk, i + 1, cio);
1527 for (i = 0; i < tk->num_urn; i++)
1528 mj2_write_urn(tk, i, cio);
1531 box.length = cio_tell(cio) - box.init_pos;
1532 cio_seek(cio, box.init_pos);
1533 cio_write(cio, box.length, 4); /* L */
1534 cio_seek(cio, box.init_pos + box.length);
1540 * Data reference box
1543 int mj2_read_dref(mj2_tk_t * tk, opj_cio_t *cio)
1547 int entry_count, marker;
1550 mj2_read_boxhdr(&box, cio);
1551 if (MJ2_DREF != box.type) {
1552 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DREF Marker\n");
1556 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1557 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in DREF box\n");
1561 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1562 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in DREF box. Expected flag 0\n");
1566 entry_count = cio_read(cio, 4);
1570 for (i = 0; i < entry_count; i++) {
1572 marker = cio_read(cio, 4);
1573 if (marker == MJ2_URL) {
1576 if (mj2_read_url(tk, tk->num_url, cio))
1578 } else if (marker == MJ2_URN) {
1581 if (mj2_read_urn(tk, tk->num_urn, cio))
1584 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n");
1591 if (cio_tell(cio) - box.init_pos != box.length) {
1592 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DREF Box size\n");
1599 * Write the DINF box
1601 * Data information box
1604 void mj2_write_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1608 box.init_pos = cio_tell(cio);
1610 cio_write(cio, MJ2_DINF, 4); /* DINF */
1612 mj2_write_dref(tk, cio);
1614 box.length = cio_tell(cio) - box.init_pos;
1615 cio_seek(cio, box.init_pos);
1616 cio_write(cio, box.length, 4); /* L */
1617 cio_seek(cio, box.init_pos + box.length);
1623 * Data information box
1626 int mj2_read_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1630 mj2_read_boxhdr(&box, cio);
1631 if (MJ2_DINF != box.type) {
1632 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DINF Marker\n");
1636 if (mj2_read_dref(tk, cio))
1639 if (cio_tell(cio) - box.init_pos != box.length) {
1640 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DINF Box size\n");
1647 * Write the VMHD box
1649 * Video Media information box
1652 void mj2_write_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1656 box.init_pos = cio_tell(cio);
1658 cio_write(cio, MJ2_VMHD, 4); /* VMHD */
1660 cio_write(cio, 1, 4); /* Version = 0, flags = 1 */
1662 cio_write(cio, tk->graphicsmode, 2);
1663 cio_write(cio, tk->opcolor[0], 2);
1664 cio_write(cio, tk->opcolor[1], 2);
1665 cio_write(cio, tk->opcolor[2], 2);
1667 box.length = cio_tell(cio) - box.init_pos;
1668 cio_seek(cio, box.init_pos);
1669 cio_write(cio, box.length, 4); /* L */
1670 cio_seek(cio, box.init_pos + box.length);
1676 * Video Media information box
1679 int mj2_read_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1683 mj2_read_boxhdr(&box, cio);
1684 if (MJ2_VMHD != box.type) {
1685 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected VMHD Marker\n");
1689 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1690 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in VMHD box\n");
1694 if (1 != cio_read(cio, 3)) { /* Flags = 1 */
1695 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in VMHD box. Expected flag 1\n");
1700 tk->graphicsmode = cio_read(cio, 2);
1701 tk->opcolor[0] = cio_read(cio, 2);
1702 tk->opcolor[1] = cio_read(cio, 2);
1703 tk->opcolor[2] = cio_read(cio, 2);
1705 if (cio_tell(cio) - box.init_pos != box.length) {
1706 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with VMHD Box size\n");
1713 * Write the SMHD box
1715 * Sound Media information box
1718 void mj2_write_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1722 box.init_pos = cio_tell(cio);
1724 cio_write(cio, MJ2_SMHD, 4); /* SMHD */
1726 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1728 cio_write(cio, tk->balance, 2);
1730 cio_write(cio, 0, 2); /* Reserved */
1732 box.length = cio_tell(cio) - box.init_pos;
1733 cio_seek(cio, box.init_pos);
1734 cio_write(cio, box.length, 4); /* L */
1735 cio_seek(cio, box.init_pos + box.length);
1741 * Sound Media information box
1744 int mj2_read_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1748 mj2_read_boxhdr(&box, cio);
1749 if (MJ2_SMHD != box.type) {
1750 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected SMHD Marker\n");
1754 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1755 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in SMHD box\n");
1759 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1760 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in SMHD box. Expected flag 0\n");
1765 tk->balance = cio_read(cio, 2);
1767 /* Init variables to zero to avoid problems when freeeing memory
1768 The values will possibly be overidded when decoding the track structure */
1774 tk->num_samplestochunk = 0;
1775 tk->num_samples = 0;
1777 cio_skip(cio,2); /* Reserved */
1779 if (cio_tell(cio) - box.init_pos != box.length) {
1780 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with SMHD Box size\n");
1787 * Write the HMHD box
1789 * Hint Media information box
1792 void mj2_write_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1796 box.init_pos = cio_tell(cio);
1798 cio_write(cio, MJ2_HMHD, 4); /* HMHD */
1800 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1802 cio_write(cio, tk->maxPDUsize, 2);
1803 cio_write(cio, tk->avgPDUsize, 2);
1804 cio_write(cio, tk->maxbitrate, 4);
1805 cio_write(cio, tk->avgbitrate, 4);
1806 cio_write(cio, tk->slidingavgbitrate, 4);
1808 box.length = cio_tell(cio) - box.init_pos;
1809 cio_seek(cio, box.init_pos);
1810 cio_write(cio, box.length, 4); /* L */
1811 cio_seek(cio, box.init_pos + box.length);
1817 * Hint Media information box
1820 int mj2_read_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1824 mj2_read_boxhdr(&box, cio);
1825 if (MJ2_HMHD != box.type) {
1826 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HMHD Marker\n");
1830 if (0 != cio_read(cio, 1)) { /* Version = 0 */
1831 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HMHD box\n");
1835 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
1836 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HMHD box. Expected flag 0\n");
1841 tk->maxPDUsize = cio_read(cio, 2);
1842 tk->avgPDUsize = cio_read(cio, 2);
1843 tk->maxbitrate = cio_read(cio, 4);
1844 tk->avgbitrate = cio_read(cio, 4);
1845 tk->slidingavgbitrate = cio_read(cio, 4);
1847 /* Init variables to zero to avoid problems when freeeing memory
1848 The values will possibly be overidded when decoding the track structure */
1854 tk->num_samplestochunk = 0;
1855 tk->num_samples = 0;
1858 if (cio_tell(cio) - box.init_pos != box.length) {
1859 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HMHD Box size\n");
1866 * Write the MINF box
1868 * Media information box
1871 void mj2_write_minf(mj2_tk_t * tk, opj_cio_t *cio)
1875 box.init_pos = cio_tell(cio);
1877 cio_write(cio, MJ2_MINF, 4); /* MINF */
1879 if (tk->track_type == 0) {
1880 mj2_write_vmhd(tk, cio);
1881 } else if (tk->track_type == 1) {
1882 mj2_write_smhd(tk, cio);
1883 } else if (tk->track_type == 2) {
1884 mj2_write_hmhd(tk, cio);
1887 mj2_write_dinf(tk, cio);
1888 mj2_write_stbl(tk, cio);
1890 box.length = cio_tell(cio) - box.init_pos;
1891 cio_seek(cio, box.init_pos);
1892 cio_write(cio, box.length, 4); /* L */
1893 cio_seek(cio, box.init_pos + box.length);
1899 * Media information box
1902 int mj2_read_minf(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1905 unsigned int box_type;
1908 mj2_read_boxhdr(&box, cio);
1909 if (MJ2_MINF != box.type) {
1910 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MINF Marker\n");
1915 box_type = cio_read(cio, 4);
1918 if (box_type == MJ2_VMHD) {
1919 if (mj2_read_vmhd(tk, cio))
1921 } else if (box_type == MJ2_SMHD) {
1922 if (mj2_read_smhd(tk, cio))
1924 } else if (box_type == MJ2_HMHD) {
1925 if (mj2_read_hmhd(tk, cio))
1928 opj_event_msg(cio->cinfo, EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n");
1932 if (mj2_read_dinf(tk, cio))
1935 if (mj2_read_stbl(tk, img, cio))
1938 if (cio_tell(cio) - box.init_pos != box.length) {
1939 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MINF Box size\n");
1946 * Write the HDLR box
1948 * Handler reference box
1951 void mj2_write_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
1955 box.init_pos = cio_tell(cio);
1957 cio_write(cio, MJ2_HDLR, 4); /* HDLR */
1959 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
1961 cio_write(cio, 0, 4); /* Predefine */
1963 tk->name = 0; /* The track name is immediately determined by the track type */
1965 if (tk->track_type == 0) {
1966 tk->handler_type = 0x76696465; /* Handler type: vide */
1967 cio_write(cio, tk->handler_type, 4);
1969 cio_write(cio, 0, 4);
1970 cio_write(cio, 0, 4);
1971 cio_write(cio, 0, 4); /* Reserved */
1973 cio_write(cio, 0x76696465, 4);
1974 cio_write(cio, 0x6F206d65, 4);
1975 cio_write(cio, 0x64696120, 4);
1976 cio_write(cio, 0x74726163, 4);
1977 cio_write(cio, 0x6b00, 2); /* String: video media track */
1978 } else if (tk->track_type == 1) {
1979 tk->handler_type = 0x736F756E; /* Handler type: soun */
1980 cio_write(cio, tk->handler_type, 4);
1982 cio_write(cio, 0, 4);
1983 cio_write(cio, 0, 4);
1984 cio_write(cio, 0, 4); /* Reserved */
1986 cio_write(cio, 0x536F756E, 4);
1987 cio_write(cio, 0x6400, 2); /* String: Sound */
1988 } else if (tk->track_type == 2) {
1989 tk->handler_type = 0x68696E74; /* Handler type: hint */
1990 cio_write(cio, tk->handler_type, 4);
1992 cio_write(cio, 0, 4);
1993 cio_write(cio, 0, 4);
1994 cio_write(cio, 0, 4); /* Reserved */
1996 cio_write(cio, 0x48696E74, 4);
1997 cio_write(cio, 0, 2); /* String: Hint */
2000 box.length = cio_tell(cio) - box.init_pos;
2001 cio_seek(cio, box.init_pos);
2002 cio_write(cio, box.length, 4); /* L */
2003 cio_seek(cio, box.init_pos + box.length);
2009 * Handler reference box
2012 int mj2_read_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
2017 mj2_read_boxhdr(&box, cio);
2018 if (MJ2_HDLR != box.type) {
2019 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HDLR Marker\n");
2024 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2025 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HDLR box\n");
2029 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2030 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HDLR box. Expected flag 0\n");
2034 cio_skip(cio,4); /* Reserved */
2036 tk->handler_type = cio_read(cio, 4);
2037 cio_skip(cio,12); /* Reserved */
2039 tk->name_size = box.length - 32;
2041 tk->name = (char*) opj_malloc(tk->name_size * sizeof(char));
2042 for (i = 0; i < tk->name_size; i++) {
2043 tk->name[i] = cio_read(cio, 1); /* Name */
2046 if (cio_tell(cio) - box.init_pos != box.length) {
2047 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HDLR Box size\n");
2054 * Write the MDHD box
2059 void mj2_write_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2064 unsigned int modification_time;
2066 box.init_pos = cio_tell(cio);
2068 cio_write(cio, MJ2_MDHD, 4); /* MDHD */
2070 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2072 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2074 time(<ime); /* Time since 1/1/70 */
2075 modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2077 cio_write(cio, modification_time, 4); /* Modification Time */
2079 cio_write(cio, tk->timescale, 4); /* Timescale */
2083 for (i = 0; i < tk->num_samples; i++)
2084 tk->duration += tk->sample[i].sample_delta;
2086 cio_write(cio, tk->duration, 4); /* Duration */
2088 cio_write(cio, tk->language, 2); /* Language */
2090 cio_write(cio, 0, 2); /* Predefined */
2092 box.length = cio_tell(cio) - box.init_pos;
2093 cio_seek(cio, box.init_pos);
2094 cio_write(cio, box.length, 4); /* L */
2095 cio_seek(cio, box.init_pos + box.length);
2104 int mj2_read_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2108 mj2_read_boxhdr(&box, cio);
2109 if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) { // Kakadu writes MHDR instead of MDHD
2110 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDHD Marker\n");
2114 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2115 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MDHD box\n");
2119 if (0 != cio_read(cio, 3)) { /* Flags = 0 */
2120 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MDHD box. Expected flag 0\n");
2125 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2127 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2129 tk->timescale = cio_read(cio, 4); /* Timescale */
2131 tk->duration = cio_read(cio, 4); /* Duration */
2133 tk->language = cio_read(cio, 2); /* Language */
2135 cio_skip(cio,2); /* Predefined */
2137 if (cio_tell(cio) - box.init_pos != box.length) {
2138 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDHD Box size\n");
2145 * Write the MDIA box
2150 void mj2_write_mdia(mj2_tk_t * tk, opj_cio_t *cio)
2154 box.init_pos = cio_tell(cio);
2156 cio_write(cio, MJ2_MDIA, 4); /* MDIA */
2158 mj2_write_mdhd(tk, cio);
2159 mj2_write_hdlr(tk, cio);
2160 mj2_write_minf(tk, cio);
2162 box.length = cio_tell(cio) - box.init_pos;
2163 cio_seek(cio, box.init_pos);
2164 cio_write(cio, box.length, 4); /* L */
2165 cio_seek(cio, box.init_pos + box.length);
2174 int mj2_read_mdia(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2178 mj2_read_boxhdr(&box, cio);
2179 if (MJ2_MDIA != box.type) {
2180 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDIA Marker\n");
2184 if (mj2_read_mdhd(tk, cio))
2186 if (mj2_read_hdlr(tk, cio))
2188 if (mj2_read_minf(tk, img, cio))
2191 if (cio_tell(cio) - box.init_pos != box.length) {
2192 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDIA Box size\n");
2199 * Write the TKHD box
2204 void mj2_write_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2210 box.init_pos = cio_tell(cio);
2213 cio_write(cio, MJ2_TKHD, 4); /* TKHD */
2215 cio_write(cio, 3, 4); /* Version=0, flags=3 */
2217 time(<ime); /* Time since 1/1/70 */
2218 tk->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2220 cio_write(cio, tk->creation_time, 4); /* Creation Time */
2222 cio_write(cio, tk->modification_time, 4); /* Modification Time */
2224 cio_write(cio, tk->track_ID, 4); /* Track ID */
2226 cio_write(cio, 0, 4); /* Reserved */
2230 for (i = 0; i < tk->num_samples; i++)
2231 tk->duration += tk->sample[i].sample_delta;
2233 cio_write(cio, tk->duration, 4); /* Duration */
2235 cio_write(cio, 0, 4); /* Reserved */
2236 cio_write(cio, 0, 4); /* Reserved */
2238 cio_write(cio, tk->layer, 2); /* Layer */
2240 cio_write(cio, 0, 2); /* Predefined */
2242 cio_write(cio, tk->volume, 2); /* Volume */
2244 cio_write(cio, 0, 2); /* Reserved */
2246 cio_write(cio, tk->trans_matrix[0], 4); /* Transformation matrix for track */
2247 cio_write(cio, tk->trans_matrix[1], 4);
2248 cio_write(cio, tk->trans_matrix[2], 4);
2249 cio_write(cio, tk->trans_matrix[3], 4);
2250 cio_write(cio, tk->trans_matrix[4], 4);
2251 cio_write(cio, tk->trans_matrix[5], 4);
2252 cio_write(cio, tk->trans_matrix[6], 4);
2253 cio_write(cio, tk->trans_matrix[7], 4);
2254 cio_write(cio, tk->trans_matrix[8], 4);
2256 cio_write(cio, tk->visual_w, 4); /* Video Visual Width */
2258 cio_write(cio, tk->visual_h, 4); /* Video Visual Height */
2260 box.length = cio_tell(cio) - box.init_pos;
2261 cio_seek(cio, box.init_pos);
2262 cio_write(cio, box.length, 4); /* L */
2263 cio_seek(cio, box.init_pos + box.length);
2272 int mj2_read_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2278 mj2_read_boxhdr(&box, cio);
2280 if (MJ2_TKHD != box.type) {
2281 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TKHD Marker\n");
2285 if (0 != cio_read(cio, 1)) { /* Version = 0 */
2286 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in TKHD box\n");
2290 flag = cio_read(cio, 3);
2292 if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) { /* Flags = 1,2,3 or 4 */
2293 opj_event_msg(cio->cinfo, EVT_ERROR,
2294 "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2298 tk->creation_time = cio_read(cio, 4); /* Creation Time */
2300 tk->modification_time = cio_read(cio, 4); /* Modification Time */
2302 tk->track_ID = cio_read(cio, 4); /* Track ID */
2304 cio_skip(cio,4); /* Reserved */
2306 tk->duration = cio_read(cio, 4); /* Duration */
2308 cio_skip(cio,8); /* Reserved */
2310 tk->layer = cio_read(cio, 2); /* Layer */
2312 cio_read(cio, 2); /* Predefined */
2314 tk->volume = cio_read(cio, 2); /* Volume */
2316 cio_skip(cio,2); /* Reserved */
2318 tk->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for track */
2319 tk->trans_matrix[1] = cio_read(cio, 4);
2320 tk->trans_matrix[2] = cio_read(cio, 4);
2321 tk->trans_matrix[3] = cio_read(cio, 4);
2322 tk->trans_matrix[4] = cio_read(cio, 4);
2323 tk->trans_matrix[5] = cio_read(cio, 4);
2324 tk->trans_matrix[6] = cio_read(cio, 4);
2325 tk->trans_matrix[7] = cio_read(cio, 4);
2326 tk->trans_matrix[8] = cio_read(cio, 4);
2328 tk->visual_w = cio_read(cio, 4); /* Video Visual Width */
2330 tk->visual_h = cio_read(cio, 4); /* Video Visual Height */
2332 if (cio_tell(cio) - box.init_pos != box.length) {
2333 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TKHD Box size\n");
2340 * Write the TRAK box
2345 void mj2_write_trak(mj2_tk_t * tk, opj_cio_t *cio)
2349 box.init_pos = cio_tell(cio);
2352 cio_write(cio, MJ2_TRAK, 4); /* TRAK */
2354 mj2_write_tkhd(tk, cio);
2355 mj2_write_mdia(tk, cio);
2357 box.length = cio_tell(cio) - box.init_pos;
2358 cio_seek(cio, box.init_pos);
2359 cio_write(cio, box.length, 4); /* L */
2360 cio_seek(cio, box.init_pos + box.length);
2369 int mj2_read_trak(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2373 mj2_read_boxhdr(&box, cio);
2374 if (MJ2_TRAK != box.type) {
2375 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TRAK Marker\n");
2378 if (mj2_read_tkhd(tk, cio))
2380 if (mj2_read_mdia(tk, img, cio))
2382 if (cio_tell(cio) - box.init_pos != box.length) {
2383 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TRAK Box\n");
2390 * Write the MVHD box
2395 void mj2_write_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2403 box.init_pos = cio_tell(cio);
2405 cio_write(cio, MJ2_MVHD, 4); /* MVHD */
2407 cio_write(cio, 0, 4); /* Version = 0, flags = 0 */
2409 time(<ime); /* Time since 1/1/70 */
2410 movie->modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2412 cio_write(cio, movie->creation_time, 4); /* Creation Time */
2414 cio_write(cio, movie->modification_time, 4); /* Modification Time */
2416 cio_write(cio, movie->timescale, 4); /* Timescale */
2418 movie->duration = 0;
2420 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2421 mj2_tk_t *tk = &movie->tk[i];
2423 for (j = 0; j < tk->num_samples; j++) {
2424 movie->duration += tk->sample[j].sample_delta;
2428 cio_write(cio, movie->duration, 4);
2430 cio_write(cio, movie->rate, 4); /* Rate to play presentation */
2432 cio_write(cio, movie->volume, 2); /* Volume */
2434 cio_write(cio, 0, 2); /* Reserved */
2435 cio_write(cio, 0, 4); /* Reserved */
2436 cio_write(cio, 0, 4); /* Reserved */
2438 cio_write(cio, movie->trans_matrix[0], 4); /* Transformation matrix for video */
2439 cio_write(cio, movie->trans_matrix[1], 4);
2440 cio_write(cio, movie->trans_matrix[2], 4);
2441 cio_write(cio, movie->trans_matrix[3], 4);
2442 cio_write(cio, movie->trans_matrix[4], 4);
2443 cio_write(cio, movie->trans_matrix[5], 4);
2444 cio_write(cio, movie->trans_matrix[6], 4);
2445 cio_write(cio, movie->trans_matrix[7], 4);
2446 cio_write(cio, movie->trans_matrix[8], 4);
2448 cio_write(cio, 0, 4); /* Pre-defined */
2449 cio_write(cio, 0, 4); /* Pre-defined */
2450 cio_write(cio, 0, 4); /* Pre-defined */
2451 cio_write(cio, 0, 4); /* Pre-defined */
2452 cio_write(cio, 0, 4); /* Pre-defined */
2453 cio_write(cio, 0, 4); /* Pre-defined */
2456 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
2457 if (max_tk_num < movie->tk[i].track_ID)
2458 max_tk_num = movie->tk[i].track_ID;
2461 movie->next_tk_id = max_tk_num + 1;
2463 cio_write(cio, movie->next_tk_id, 4); /* ID of Next track to be added */
2465 box.length = cio_tell(cio) - box.init_pos;
2466 cio_seek(cio, box.init_pos);
2467 cio_write(cio, box.length, 4); /* L */
2468 cio_seek(cio, box.init_pos + box.length);
2477 int mj2_read_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2481 mj2_read_boxhdr(&box, cio);
2482 if (MJ2_MVHD != box.type) {
2483 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MVHD Marker\n");
2488 if (0 != cio_read(cio, 4)) { /* Version = 0, flags = 0 */
2489 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MVHD box\n");
2492 movie->creation_time = cio_read(cio, 4); /* Creation Time */
2494 movie->modification_time = cio_read(cio, 4); /* Modification Time */
2496 movie->timescale = cio_read(cio, 4); /* Timescale */
2498 movie->duration = cio_read(cio, 4); /* Duration */
2500 movie->rate = cio_read(cio, 4); /* Rate to play presentation */
2502 movie->volume = cio_read(cio, 2); /* Volume */
2504 cio_skip(cio,10); /* Reserved */
2506 movie->trans_matrix[0] = cio_read(cio, 4); /* Transformation matrix for video */
2507 movie->trans_matrix[1] = cio_read(cio, 4);
2508 movie->trans_matrix[2] = cio_read(cio, 4);
2509 movie->trans_matrix[3] = cio_read(cio, 4);
2510 movie->trans_matrix[4] = cio_read(cio, 4);
2511 movie->trans_matrix[5] = cio_read(cio, 4);
2512 movie->trans_matrix[6] = cio_read(cio, 4);
2513 movie->trans_matrix[7] = cio_read(cio, 4);
2514 movie->trans_matrix[8] = cio_read(cio, 4);
2516 cio_skip(cio,24); /* Pre-defined */
2518 movie->next_tk_id = cio_read(cio, 4); /* ID of Next track to be added */
2520 if (cio_tell(cio) - box.init_pos != box.length) {
2521 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MVHD Box Size\n");
2529 * Write the MOOV box
2534 void mj2_write_moov(opj_mj2_t * movie, opj_cio_t *cio)
2539 box.init_pos = cio_tell(cio);
2541 cio_write(cio, MJ2_MOOV, 4); /* MOOV */
2543 mj2_write_mvhd(movie, cio);
2545 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2546 mj2_write_trak(&movie->tk[i], cio);
2549 box.length = cio_tell(cio) - box.init_pos;
2550 cio_seek(cio, box.init_pos);
2551 cio_write(cio, box.length, 4); /* L */
2552 cio_seek(cio, box.init_pos + box.length);
2561 int mj2_read_moov(opj_mj2_t * movie, opj_image_t * img, opj_cio_t *cio)
2567 mj2_read_boxhdr(&box, cio);
2568 if (MJ2_MOOV != box.type) {
2569 opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MOOV Marker\n");
2573 if (mj2_read_mvhd(movie, cio))
2576 movie->tk = (mj2_tk_t*) opj_malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2578 for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
2579 mj2_tk_t *tk = &movie->tk[i];
2580 tk->cinfo = movie->cinfo;
2581 mj2_read_boxhdr(&box2, cio);
2582 if (box2.type == MJ2_TRAK) {
2583 cio_seek(cio, box2.init_pos);
2584 if (mj2_read_trak(tk, img, cio))
2587 if (tk->track_type == 0) {
2589 } else if (tk->track_type == 1) {
2591 } else if (tk->track_type == 2) {
2594 } else if (box2.type == MJ2_MVEX) {
2595 cio_seek(cio, box2.init_pos);
2596 cio_skip(cio,box2.length);
2599 opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2606 int mj2_read_struct(FILE *file, opj_mj2_t *movie) {
2609 unsigned char * src;
2614 /* open a byte stream for reading */
2615 src = (unsigned char*) opj_malloc(300 * sizeof(unsigned char));
2617 /* Assuming that jp and ftyp markers size do
2618 not exceed 300 bytes */
2619 fread(src,300,1, file);
2621 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2623 if (mj2_read_jp(cio))
2625 if (mj2_read_ftyp(movie, cio))
2628 fsresult = fseek(file,cio_tell(cio),SEEK_SET);
2630 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read data after FTYP box\n" );
2634 foffset = cio_tell(cio);
2638 fread(src,30,1,file);
2639 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2640 mj2_read_boxhdr(&box, cio);
2642 while(box.type != MJ2_MOOV) {
2647 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2649 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MDAT box\n" );
2652 foffset += box.length;
2656 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2658 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOF box\n" );
2661 foffset += box.length;
2664 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2666 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read FREE box\n" );
2669 foffset += box.length;
2672 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2674 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read SKIP box\n" );
2677 foffset += box.length;
2680 opj_event_msg(cio->cinfo, EVT_ERROR, "Unknown box in MJ2 stream\n");
2681 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2683 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read end of unknown box\n");
2686 foffset += box.length;
2689 fsresult = fread(src,8,1,file);
2690 if (fsresult != 1) {
2691 opj_event_msg(cio->cinfo, EVT_ERROR, "MOOV box not found in file\n");
2694 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 8);
2695 mj2_read_boxhdr(&box, cio);
2698 fseek(file,foffset,SEEK_SET);
2699 src = (unsigned char*)opj_realloc(src,box.length);
2700 fsresult = fread(src,box.length,1,file);
2701 if (fsresult != 1) {
2702 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOV box\n");
2706 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, box.length);
2708 if (mj2_read_moov(movie, &img, cio))
2715 /* ----------------------------------------------------------------------- */
2716 /* MJ2 decoder interface */
2717 /* ----------------------------------------------------------------------- */
2719 opj_dinfo_t* mj2_create_decompress() {
2721 opj_dinfo_t *dinfo = (opj_dinfo_t*) opj_calloc(1, sizeof(opj_dinfo_t));
2722 if(!dinfo) return NULL;
2724 dinfo->is_decompressor = true;
2726 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2727 dinfo->mj2_handle = mj2;
2729 mj2->cinfo = (opj_common_ptr)dinfo;
2731 mj2->j2k = j2k_create_decompress((opj_common_ptr)dinfo);
2732 dinfo->j2k_handle = mj2->j2k;
2737 void mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters) {
2742 /* setup the J2K decoder parameters */
2743 j2k_setup_decoder((opj_j2k_t*)movie->cinfo->j2k_handle,
2744 &mj2_parameters->j2k_parameters);
2748 void mj2_destroy_decompress(opj_mj2_t *movie) {
2753 if (movie->cinfo->j2k_handle)
2754 j2k_destroy_compress(movie->j2k);
2756 if (movie->num_cl != 0)
2757 opj_free(movie->cl);
2759 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2761 if (tk->name_size != 0)
2763 if (tk->track_type == 0) {// Video track
2764 if (tk->jp2_struct.comps != 0)
2765 opj_free(tk->jp2_struct.comps);
2766 if (tk->jp2_struct.cl != 0)
2767 opj_free(tk->jp2_struct.cl);
2768 if (tk->num_jp2x != 0)
2769 opj_free(tk->jp2xdata);
2772 if (tk->num_url != 0)
2774 if (tk->num_urn != 0)
2776 if (tk->num_br != 0)
2778 if (tk->num_tts != 0)
2780 if (tk->num_chunks != 0)
2781 opj_free(tk->chunk);
2782 if (tk->num_samplestochunk != 0)
2783 opj_free(tk->sampletochunk);
2784 if (tk->num_samples != 0)
2785 opj_free(tk->sample);
2788 opj_free(movie->tk);
2793 /* ----------------------------------------------------------------------- */
2794 /* MJ2 encoder interface */
2795 /* ----------------------------------------------------------------------- */
2798 opj_cinfo_t* mj2_create_compress() {
2800 opj_cinfo_t *cinfo = (opj_cinfo_t*) opj_calloc(1, sizeof(opj_cinfo_t));
2801 if(!cinfo) return NULL;
2803 mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2804 cinfo->mj2_handle = mj2;
2806 mj2->cinfo = (opj_common_ptr)cinfo;
2809 mj2->j2k = j2k_create_compress(mj2->cinfo);
2810 cinfo->j2k_handle = mj2->j2k;
2815 void mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters) {
2816 if(movie && parameters) {
2817 opj_jp2_t *jp2_struct;
2819 movie->num_htk = 0; // No hint tracks
2820 movie->num_stk = 0; // No sound tracks
2821 movie->num_vtk = 1; // One video track
2823 movie->brand = MJ2_MJ2; // One brand: MJ2
2824 movie->num_cl = 2; // Two compatible brands: MJ2 and MJ2S
2825 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
2826 movie->cl[0] = MJ2_MJ2;
2827 movie->cl[1] = MJ2_MJ2S;
2828 movie->minversion = 0; // Minimum version: 0
2830 movie->tk = (mj2_tk_t*) opj_malloc(sizeof(mj2_tk_t)); //Memory allocation for the video track
2831 movie->tk[0].track_ID = 1; // Track ID = 1
2832 movie->tk[0].track_type = 0; // Video track
2833 movie->tk[0].Dim[0] = parameters->Dim[0];
2834 movie->tk[0].Dim[1] = parameters->Dim[1];
2835 movie->tk[0].w = parameters->w;
2836 movie->tk[0].h = parameters->h;
2837 movie->tk[0].CbCr_subsampling_dx = parameters->CbCr_subsampling_dx;
2838 movie->tk[0].CbCr_subsampling_dy = parameters->CbCr_subsampling_dy;
2839 movie->tk[0].sample_rate = parameters->frame_rate;
2840 movie->tk[0].name_size = 0;
2841 movie->tk[0].chunk = (mj2_chunk_t*) opj_malloc(sizeof(mj2_chunk_t));
2842 movie->tk[0].sample = (mj2_sample_t*) opj_malloc(sizeof(mj2_sample_t));
2844 jp2_struct = &movie->tk[0].jp2_struct;
2845 jp2_struct->numcomps = 3; // NC
2846 jp2_struct->comps = (opj_jp2_comps_t*) opj_malloc(jp2_struct->numcomps * sizeof(opj_jp2_comps_t));
2847 jp2_struct->precedence = 0; /* PRECEDENCE*/
2848 jp2_struct->approx = 0; /* APPROX*/
2849 jp2_struct->brand = JP2_JP2; /* BR */
2850 jp2_struct->minversion = 0; /* MinV */
2851 jp2_struct->numcl = 1;
2852 jp2_struct->cl = (unsigned int*) opj_malloc(jp2_struct->numcl * sizeof(unsigned int));
2853 jp2_struct->cl[0] = JP2_JP2; /* CL0 : JP2 */
2854 jp2_struct->C = 7; /* C : Always 7*/
2855 jp2_struct->UnkC = 0; /* UnkC, colorspace specified in colr box*/
2856 jp2_struct->IPR = 0; /* IPR, no intellectual property*/
2857 jp2_struct->w = parameters->w;
2858 jp2_struct->h = parameters->h;
2859 jp2_struct->bpc = 7;
2860 jp2_struct->meth = 1;
2861 jp2_struct->enumcs = 18; // YUV
2865 void mj2_destroy_compress(opj_mj2_t *movie) {
2870 if (movie->cinfo->j2k_handle) {
2871 j2k_destroy_compress(movie->j2k);
2874 if (movie->num_cl != 0)
2875 opj_free(movie->cl);
2877 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2879 if (tk->name_size != 0)
2881 if (tk->track_type == 0) {// Video track
2882 if (tk->jp2_struct.comps != 0)
2883 opj_free(tk->jp2_struct.comps);
2884 if (tk->jp2_struct.cl != 0)
2885 opj_free(tk->jp2_struct.cl);
2886 if (tk->num_jp2x != 0)
2887 opj_free(tk->jp2xdata);
2890 if (tk->num_url != 0)
2892 if (tk->num_urn != 0)
2894 if (tk->num_br != 0)
2896 if (tk->num_tts != 0)
2898 if (tk->num_chunks != 0)
2899 opj_free(tk->chunk);
2900 if (tk->num_samplestochunk != 0)
2901 opj_free(tk->sampletochunk);
2902 if (tk->num_samples != 0)
2903 opj_free(tk->sample);
2906 opj_free(movie->tk);