2 * Copyright (c) 2003-2004, Fran�ois-Olivier Devaux
3 * Copyright (c) 2003-2004, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
37 #define MJ2_JP 0x6a502020
38 #define MJ2_FTYP 0x66747970
39 #define MJ2_MJ2 0x6d6a7032
40 #define MJ2_MJ2S 0x6d6a3273
41 #define MJ2_MDAT 0x6d646174
42 #define MJ2_MOOV 0x6d6f6f76
43 #define MJ2_MVHD 0x6d766864
44 #define MJ2_TRAK 0x7472616b
45 #define MJ2_TKHD 0x746b6864
46 #define MJ2_MDIA 0x6d646961
47 #define MJ2_MDHD 0x6d646864
48 #define MJ2_MHDR 0x6d686472
49 #define MJ2_HDLR 0x68646C72
50 #define MJ2_MINF 0x6d696e66
51 #define MJ2_VMHD 0x766d6864
52 #define MJ2_SMHD 0x736d6864
53 #define MJ2_HMHD 0x686d6864
54 #define MJ2_DINF 0x64696e66
55 #define MJ2_DREF 0x64726566
56 #define MJ2_URL 0x75726c20
57 #define MJ2_URN 0x75726e20
58 #define MJ2_STBL 0x7374626c
59 #define MJ2_STSD 0x73747364
60 #define MJ2_STTS 0x73747473
61 #define MJ2_STSC 0x73747363
62 #define MJ2_STSZ 0x7374737A
63 #define MJ2_STCO 0x7374636f
64 #define MJ2_MOOF 0x6d6f6f66
65 #define MJ2_FREE 0x66726565
66 #define MJ2_SKIP 0x736b6970
67 #define MJ2_JP2C 0x6a703263
68 #define MJ2_FIEL 0x6669656c
69 #define MJ2_JP2P 0x6a703270
70 #define MJ2_JP2X 0x6a703278
71 #define MJ2_JSUB 0x6a737562
72 #define MJ2_ORFO 0x6f72666f
73 #define MJ2_MVEX 0x6d766578
74 #define MJ2_JP2 0x6a703220
75 #define MJ2_J2P0 0x4a325030
79 * Free movie structure memory
82 void mj2_memory_free(mj2_movie_t * movie)
87 if (movie->num_cl != 0)
90 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
92 if (tk->name_size != 0)
94 if (tk->jp2_struct.comps != 0)
95 free(tk->jp2_struct.comps);
96 if (tk->jp2_struct.cl != 0)
97 free(tk->jp2_struct.cl);
100 if (tk->num_urn != 0)
104 if (tk->num_jp2x != 0)
106 if (tk->num_tts != 0)
108 if (tk->num_chunks != 0)
110 if (tk->num_samplestochunk != 0)
111 free(tk->sampletochunk);
112 if (tk->num_samples != 0)
125 int mj2_read_boxhdr(mj2_box_t * box)
127 box->init_pos = cio_tell();
128 box->length = cio_read(4);
129 box->type = cio_read(4);
130 if (box->length == 1) {
131 if (cio_read(4) != 0) {
132 fprintf(stderr, "Error: Cannot handle box sizes higher than 2^32\n");
135 box->length = cio_read(4);
136 if (box->length == 0)
137 box->length = cio_numbytesleft() + 12;
139 else if (box->length == 0) {
140 box->length = cio_numbytesleft() + 8;
147 * Initialisation of a Standard Video Track
148 * with one sample per chunk
151 int mj2_init_stdmovie(mj2_movie_t * movie)
156 movie->brand = MJ2_MJ2;
157 movie->minversion = 0;
158 if (!((movie->num_cl<100) && (movie->num_cl>-1))) {
161 (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
164 movie->cl[0] = MJ2_MJ2;
165 movie->cl[1] = MJ2_MJ2S;
166 time(<ime); /* Time since 1/1/70 */
167 movie->creation_time = (unsigned int) ltime + 2082844800; /* Seconds between 1/1/04 and 1/1/70 */
168 movie->timescale = 1000;
170 movie->rate = 1; /* Rate to play presentation (default = 0x00010000) */
171 movie->volume = 1; /* Movie volume (default = 0x0100) */
172 movie->trans_matrix[0] = 0x00010000; /* Transformation matrix for video */
173 movie->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
174 movie->trans_matrix[2] = 0;
175 movie->trans_matrix[3] = 0;
176 movie->trans_matrix[4] = 0x00010000;
177 movie->trans_matrix[5] = 0;
178 movie->trans_matrix[6] = 0;
179 movie->trans_matrix[7] = 0;
180 movie->trans_matrix[8] = 0x40000000;
181 movie->next_tk_id = 1;
183 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
184 mj2_tk_t *tk = &movie->tk[i];
186 if (tk->track_type == 0) {
187 if (tk->num_samples == 0)
193 tk->timescale = 1000; /* Timescale = 1 ms */
195 tk->chunk[0].num_samples = 1;
196 tk->chunk[0].sample_descr_idx = 1;
198 tk->same_sample_size = 0;
200 tk->num_samplestochunk = 1; /* One sample per chunk */
202 (mj2_sampletochunk_t *) malloc(tk->num_samplestochunk *
203 sizeof(mj2_sampletochunk_t));
204 tk->sampletochunk[0].first_chunk = 1;
205 tk->sampletochunk[0].samples_per_chunk = 1;
206 tk->sampletochunk[0].sample_descr_idx = 1;
208 for (j = 0; j < tk->num_samples; j++)
209 tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
212 tk->tts = (mj2_tts_t *) malloc(tk->num_tts * sizeof(mj2_tts_t));
213 tk->tts[0].sample_count = tk->num_samples;
214 tk->tts[0].sample_delta = tk->timescale / tk->sample_rate;
216 tk->horizresolution = 0x00480000; /* Horizontal resolution (typically 72) */
217 tk->vertresolution = 0x00480000; /* Vertical resolution (typically 72) */
218 tk->compressorname[0] = 0x0f4d6f74; /* Compressor Name[]: Motion JPEG2000 */
219 tk->compressorname[1] = 0x696f6e20;
220 tk->compressorname[2] = 0x4a504547;
221 tk->compressorname[3] = 0x32303030;
222 tk->compressorname[4] = 0x00120000;
223 tk->compressorname[5] = 0;
224 tk->compressorname[6] = 0x00000042;
225 tk->compressorname[7] = 0x000000DC;
226 tk->num_url = 0; /* Number of URL */
227 tk->num_urn = 0; /* Number of URN */
228 tk->graphicsmode = 0; /* Graphicsmode */
229 tk->opcolor[0] = 0; /* OpColor */
230 tk->opcolor[1] = 0; /* OpColor */
231 tk->opcolor[2] = 0; /* OpColor */
232 tk->creation_time = movie->creation_time; /* Seconds between 1/1/04 and 1/1/70 */
233 tk->language = 0; /* Language (undefined) */
236 tk->trans_matrix[0] = 0x00010000; /* Transformation matrix for track */
237 tk->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
238 tk->trans_matrix[2] = 0;
239 tk->trans_matrix[3] = 0;
240 tk->trans_matrix[4] = 0x00010000;
241 tk->trans_matrix[5] = 0;
242 tk->trans_matrix[6] = 0;
243 tk->trans_matrix[7] = 0;
244 tk->trans_matrix[8] = 0x40000000;
247 tk->or_fieldcount = 1;
248 tk->or_fieldorder = 0;
250 tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
252 tk->br[1] = MJ2_J2P0;
254 tk->hsub = 2; /* 4:2:0 */
255 tk->vsub = 2; /* 4:2:0 */
264 * Time To Sample box Decompact
267 void mj2_tts_decompact(mj2_tk_t * tk)
271 for (i = 0; i < tk->num_tts; i++) {
272 tk->num_samples += tk->tts[i].sample_count;
276 (mj2_sample_t *) malloc(tk->num_samples * sizeof(mj2_sample_t));
278 for (i = 0; i < tk->num_tts; i++) {
279 for (j = 0; j < tk->tts[i].sample_count; j++) {
280 tk->sample[j].sample_delta = tk->tts[i].sample_delta;
286 * Sample To Chunk box Decompact
289 void mj2_stsc_decompact(mj2_tk_t * tk)
295 if (tk->num_samplestochunk == 1) {
297 (unsigned int) ceil((double) tk->num_samples /
298 (double) tk->sampletochunk[0].samples_per_chunk);
300 (mj2_chunk_t *) malloc(tk->num_chunks * sizeof(mj2_chunk_t));
301 for (k = 0; k < tk->num_chunks; k++) {
302 tk->chunk[k].num_samples = tk->sampletochunk[0].samples_per_chunk;
307 (mj2_chunk_t *) malloc(tk->num_samples * sizeof(mj2_chunk_t));
309 for (i = 0; i < tk->num_samplestochunk -1 ; i++) {
310 for (j = tk->sampletochunk[i].first_chunk - 1;
311 j < tk->sampletochunk[i + 1].first_chunk - 1; j++) {
312 tk->chunk[j].num_samples = tk->sampletochunk[i].samples_per_chunk;
314 sampleno += tk->chunk[j].num_samples;
317 tk->num_chunks += (int)(tk->num_samples - sampleno) / tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
318 for (k = tk->sampletochunk[tk->num_samplestochunk - 1].first_chunk - 1;
319 k < tk->num_chunks; k++) {
320 tk->chunk[k].num_samples =
321 tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
323 tk->chunk = realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
330 * Chunk offset box Decompact
333 void mj2_stco_decompact(mj2_tk_t * tk)
338 int intra_chunk_offset;
340 for (i = 0; i < tk->num_chunks; i++) {
341 intra_chunk_offset = 0;
342 for (j = 0; j < tk->chunk[i].num_samples; j++) {
343 tk->sample[k].offset = intra_chunk_offset + tk->chunk[i].offset;
344 intra_chunk_offset += tk->sample[k].sample_size;
359 box.init_pos = cio_tell();
362 cio_write(MJ2_JP, 4); /* JP */
363 cio_write(0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
365 box.length = cio_tell() - box.init_pos;
366 cio_seek(box.init_pos);
367 cio_write(box.length, 4);
368 cio_seek(box.init_pos + box.length);
374 * JPEG 2000 signature
381 mj2_read_boxhdr(&box);
382 if (MJ2_JP != box.type) { /* Check Marker */
383 fprintf(stderr, "Error: Expected JP Marker\n");
386 if (0x0d0a870a != cio_read(4)) { /* read the 0x0d0a870a required in a JP box */
387 fprintf(stderr, "Error with JP Marker\n");
390 if (cio_tell() - box.init_pos != box.length) { /* Check box length */
391 fprintf(stderr, "Error with JP Box size \n");
404 void mj2_write_ftyp(mj2_movie_t * movie)
408 box.init_pos = cio_tell();
411 cio_write(MJ2_FTYP, 4); /* FTYP */
412 cio_write(movie->brand, 4); /* BR */
413 cio_write(movie->minversion, 4); /* MinV */
415 for (i = 0; i < movie->num_cl; i++)
416 cio_write(movie->cl[i], 4); /* CL */
418 box.length = cio_tell() - box.init_pos;
419 cio_seek(box.init_pos);
420 cio_write(box.length, 4); /* Length */
421 cio_seek(box.init_pos + box.length);
430 int mj2_read_ftyp(mj2_movie_t * movie)
435 mj2_read_boxhdr(&box); /* Box Size */
436 if (MJ2_FTYP != box.type) {
437 fprintf(stderr, "Error: Expected FTYP Marker\n");
441 movie->brand = cio_read(4); /* BR */
442 movie->minversion = cio_read(4); /* MinV */
443 movie->num_cl = (box.length - 16) / 4;
445 (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
447 for (i = movie->num_cl - 1; i > -1; i--)
448 movie->cl[i] = cio_read(4); /* CLi */
450 if (cio_tell() - box.init_pos != box.length) {
451 fprintf(stderr, "Error with FTYP Box\n");
464 void mj2_write_stco(mj2_tk_t * tk)
469 box.init_pos = cio_tell();
471 cio_write(MJ2_STCO, 4); /* STCO */
473 cio_write(0, 4); /* Version = 0, flags = 0 */
475 cio_write(tk->num_chunks, 4); /* Entry Count */
477 for (i = 0; i < tk->num_chunks; i++) {
478 cio_write(tk->chunk[i].offset, 4); /* Entry offset */
481 box.length = cio_tell() - box.init_pos;
482 cio_seek(box.init_pos);
483 cio_write(box.length, 4); /* L */
484 cio_seek(box.init_pos + box.length);
493 int mj2_read_stco(mj2_tk_t * tk)
498 mj2_read_boxhdr(&box); /* Box Size */
499 if (MJ2_STCO != box.type) {
500 fprintf(stderr, "Error: Expected STCO Marker\n");
504 if (0 != cio_read(1)) { /* Version = 0 */
505 fprintf(stderr, "Error: Only Version 0 handled in STCO box\n");
509 if (0 != cio_read(3)) { /* Flags = 0 */
510 fprintf(stderr, "Error with flag in STCO box. Expected flag 0\n");
515 if (cio_read(4) != tk->num_chunks) {
517 "Error in STCO box: expecting same amount of entry-count as chunks \n");
519 for (i = 0; i < tk->num_chunks; i++) {
520 tk->chunk[i].offset = cio_read(4); /* Entry offset */
524 mj2_stco_decompact(tk);
527 if (cio_tell() - box.init_pos != box.length) {
528 fprintf(stderr, "Error with STCO Box size\n");
540 void mj2_write_stsz(mj2_tk_t * tk)
545 box.init_pos = cio_tell();
547 cio_write(MJ2_STSZ, 4); /* STSZ */
549 cio_write(0, 4); /* Version = 0, flags = 0 */
551 if (tk->same_sample_size == 1) { /* If they all have the same size */
552 cio_write(tk->sample[0].sample_size, 4); /* Size */
554 cio_write(1, 4); /* Entry count = 1 */
558 cio_write(0, 4); /* Sample Size = 0 becase they all have different sizes */
560 cio_write(tk->num_samples, 4); /* Sample Count */
562 for (i = 0; i < tk->num_samples; i++) {
563 cio_write(tk->sample[i].sample_size, 4);
567 box.length = cio_tell() - box.init_pos;
568 cio_seek(box.init_pos);
569 cio_write(box.length, 4); /* L */
570 cio_seek(box.init_pos + box.length);
579 int mj2_read_stsz(mj2_tk_t * tk)
585 mj2_read_boxhdr(&box); /* Box Size */
586 if (MJ2_STSZ != box.type) {
587 fprintf(stderr, "Error: Expected STSZ Marker\n");
592 if (0 != cio_read(1)) { /* Version = 0 */
593 fprintf(stderr, "Error: Only Version 0 handled in STSZ box\n");
597 if (0 != cio_read(3)) { /* Flags = 0 */
598 fprintf(stderr, "Error with flag in STSZ box. Expected flag 0\n");
602 sample_size = cio_read(4);
604 if (sample_size != 0) { /* Samples do have the same size */
605 tk->same_sample_size = 1;
606 for (i = 0; i < tk->num_samples; i++) {
607 tk->sample[i].sample_size = sample_size;
609 cio_skip(4); /* Sample count = 1 */
611 tk->same_sample_size = 0;
612 if (tk->num_samples != cio_read(4)) { /* Sample count */
614 "Error in STSZ box. Expected that sample-count is number of samples in track\n");
617 for (i = 0; i < tk->num_samples; i++) {
618 tk->sample[i].sample_size = cio_read(4); /* Sample Size */
621 if (cio_tell() - box.init_pos != box.length) {
622 fprintf(stderr, "Error with STSZ Box size\n");
636 void mj2_write_stsc(mj2_tk_t * tk)
641 box.init_pos = cio_tell();
643 cio_write(MJ2_STSC, 4); /* STSC */
645 cio_write(0, 4); /* Version = 0, flags = 0 */
647 cio_write(tk->num_samplestochunk, 4); /* Entry Count */
649 for (i = 0; i < tk->num_samplestochunk; i++) {
650 cio_write(tk->sampletochunk[i].first_chunk, 4); /* First Chunk */
651 cio_write(tk->sampletochunk[i].samples_per_chunk, 4); /* Samples per chunk */
652 cio_write(tk->sampletochunk[i].sample_descr_idx, 4); /* Samples description index */
656 box.length = cio_tell() - box.init_pos;
657 cio_seek(box.init_pos);
658 cio_write(box.length, 4); /* L */
659 cio_seek(box.init_pos + box.length);
668 int mj2_read_stsc(mj2_tk_t * tk)
673 mj2_read_boxhdr(&box); /* Box Size */
674 if (MJ2_STSC != box.type) {
675 fprintf(stderr, "Error: Expected STSC Marker\n");
680 if (0 != cio_read(1)) { /* Version = 0 */
681 fprintf(stderr, "Error: Only Version 0 handled in STSC box\n");
685 if (0 != cio_read(3)) { /* Flags = 0 */
686 fprintf(stderr, "Error with flag in STSC box. Expected flag 0\n");
690 tk->num_samplestochunk = cio_read(4);
693 (mj2_sampletochunk_t *) malloc(tk->num_samplestochunk *
694 sizeof(mj2_sampletochunk_t));
697 for (i = 0; i < tk->num_samplestochunk; i++) {
698 tk->sampletochunk[i].first_chunk = cio_read(4);
699 tk->sampletochunk[i].samples_per_chunk = cio_read(4);
700 tk->sampletochunk[i].sample_descr_idx = cio_read(4);
703 mj2_stsc_decompact(tk); /* decompact sample to chunk box */
706 if (cio_tell() - box.init_pos != box.length) {
707 fprintf(stderr, "Error with STSC Box size\n");
719 void mj2_write_stts(mj2_tk_t * tk)
725 box.init_pos = cio_tell();
727 cio_write(MJ2_STTS, 4); /* STTS */
729 cio_write(0, 4); /* Version = 0, flags = 0 */
731 cio_write(tk->num_tts, 4); /* entry_count */
732 for (i = 0; i < tk->num_tts; i++) {
733 cio_write(tk->tts[i].sample_count, 4); /* Sample-count */
734 cio_write(tk->tts[i].sample_delta, 4); /* Sample-Delta */
737 box.length = cio_tell() - box.init_pos;
738 cio_seek(box.init_pos);
739 cio_write(box.length, 4); /* L */
740 cio_seek(box.init_pos + box.length);
749 int mj2_read_stts(mj2_tk_t * tk)
755 mj2_read_boxhdr(&box);
756 if (MJ2_STTS != box.type) {
757 fprintf(stderr, "Error: Expected STTS Marker\n");
762 if (0 != cio_read(1)) { /* Version = 0 */
763 fprintf(stderr, "Error: Only Version 0 handled in STTS box\n");
767 if (0 != cio_read(3)) { /* Flags = 0 */
768 fprintf(stderr, "Error with flag in STTS box. Expected flag 0\n");
772 tk->num_tts = cio_read(4);
774 tk->tts = (mj2_tts_t *) malloc(tk->num_tts * sizeof(mj2_tts_t));
776 for (i = 0; i < tk->num_tts; i++) {
777 tk->tts[i].sample_count = cio_read(4);
778 tk->tts[i].sample_delta = cio_read(4);
781 mj2_tts_decompact(tk);
783 if (cio_tell() - box.init_pos != box.length) {
784 fprintf(stderr, "Error with STTS Box size\n");
796 void mj2_write_fiel(mj2_tk_t * tk)
801 box.init_pos = cio_tell();
803 cio_write(MJ2_FIEL, 4); /* STTS */
805 cio_write(tk->fieldcount, 1); /* Field count */
806 cio_write(tk->fieldorder, 1); /* Field order */
809 box.length = cio_tell() - box.init_pos;
810 cio_seek(box.init_pos);
811 cio_write(box.length, 4); /* L */
812 cio_seek(box.init_pos + box.length);
821 int mj2_read_fiel(mj2_tk_t * tk)
826 mj2_read_boxhdr(&box);
827 if (MJ2_FIEL != box.type) {
828 fprintf(stderr, "Error: Expected FIEL Marker\n");
833 tk->fieldcount = cio_read(1);
834 tk->fieldorder = cio_read(1);
836 if (cio_tell() - box.init_pos != box.length) {
837 fprintf(stderr, "Error with FIEL Box size\n");
846 * Original Format Box
849 void mj2_write_orfo(mj2_tk_t * tk)
853 box.init_pos = cio_tell();
855 cio_write(MJ2_ORFO, 4);
857 cio_write(tk->or_fieldcount, 1); /* Original Field count */
858 cio_write(tk->or_fieldorder, 1); /* Original Field order */
861 box.length = cio_tell() - box.init_pos;
862 cio_seek(box.init_pos);
863 cio_write(box.length, 4); /* L */
864 cio_seek(box.init_pos + box.length);
870 * Original Format Box
873 int mj2_read_orfo(mj2_tk_t * tk)
878 mj2_read_boxhdr(&box);
879 if (MJ2_ORFO != box.type) {
880 fprintf(stderr, "Error: Expected ORFO Marker\n");
885 tk->or_fieldcount = cio_read(1);
886 tk->or_fieldorder = cio_read(1);
888 if (cio_tell() - box.init_pos != box.length) {
889 fprintf(stderr, "Error with ORFO Box size\n");
901 void mj2_write_jp2p(mj2_tk_t * tk)
907 box.init_pos = cio_tell();
909 cio_write(MJ2_JP2P, 4);
911 cio_write(0, 4); /* Version 0, flags =0 */
913 for (i = 0; i < tk->num_br; i++) {
914 cio_write(tk->br[i], 4);
917 box.length = cio_tell() - box.init_pos;
918 cio_seek(box.init_pos);
919 cio_write(box.length, 4); /* L */
920 cio_seek(box.init_pos + box.length);
929 int mj2_read_jp2p(mj2_tk_t * tk)
935 mj2_read_boxhdr(&box);
936 if (MJ2_JP2P != box.type) {
937 fprintf(stderr, "Error: Expected JP2P Marker\n");
941 if (0 != cio_read(1)) { /* Version = 0 */
942 fprintf(stderr, "Error: Only Version 0 handled in JP2P box\n");
946 if (0 != cio_read(3)) { /* Flags = 0 */
947 fprintf(stderr, "Error with flag in JP2P box. Expected flag 0\n");
952 tk->num_br = (box.length - 12) / 4;
953 tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
955 for (i = 0; i < tk->num_br; i++) {
956 tk->br[i] = cio_read(4);
959 if (cio_tell() - box.init_pos != box.length) {
960 fprintf(stderr, "Error with JP2P Box size\n");
972 void mj2_write_jp2x(mj2_tk_t * tk)
978 box.init_pos = cio_tell();
980 cio_write(MJ2_JP2X, 4);
982 for (i = 0; i < tk->num_jp2x; i++) {
983 cio_write(tk->jp2xdata[i], 1);
986 box.length = cio_tell() - box.init_pos;
987 cio_seek(box.init_pos);
988 cio_write(box.length, 4); /* L */
989 cio_seek(box.init_pos + box.length);
998 int mj2_read_jp2x(mj2_tk_t * tk)
1004 mj2_read_boxhdr(&box);
1005 if (MJ2_JP2X != box.type) {
1006 fprintf(stderr, "Error: Expected JP2X Marker\n");
1011 tk->num_jp2x = (box.length - 8);
1013 (unsigned char *) malloc(tk->num_jp2x * sizeof(unsigned char));
1015 for (i = 0; i < tk->num_jp2x; i++) {
1016 tk->jp2xdata[i] = cio_read(1);
1019 if (cio_tell() - box.init_pos != box.length) {
1020 fprintf(stderr, "Error with JP2X Box size\n");
1027 * Write the JSUB box
1029 * MJP2 Subsampling Box
1032 void mj2_write_jsub(mj2_tk_t * tk)
1037 box.init_pos = cio_tell();
1039 cio_write(MJ2_JSUB, 4);
1041 cio_write(tk->hsub, 1);
1042 cio_write(tk->vsub, 1);
1043 cio_write(tk->hoff, 1);
1044 cio_write(tk->voff, 1);
1046 box.length = cio_tell() - box.init_pos;
1047 cio_seek(box.init_pos);
1048 cio_write(box.length, 4); /* L */
1049 cio_seek(box.init_pos + box.length);
1055 * MJP2 Subsampling Box
1058 int mj2_read_jsub(mj2_tk_t * tk)
1062 mj2_read_boxhdr(&box);
1063 if (MJ2_JSUB != box.type) {
1064 fprintf(stderr, "Error: Expected JSUB Marker\n");
1068 tk->hsub = cio_read(1);
1069 tk->vsub = cio_read(1);
1070 tk->hoff = cio_read(1);;
1071 tk->voff = cio_read(1);
1073 if (cio_tell() - box.init_pos != box.length) {
1074 fprintf(stderr, "Error with JSUB Box size\n");
1081 * Write the SMJ2 box
1083 * Visual Sample Entry Description
1086 void mj2_write_smj2(mj2_tk_t * tk)
1090 box.init_pos = cio_tell();
1092 cio_write(MJ2_MJ2, 4); /* MJ2 */
1094 cio_write(0, 4); /* Version = 0, flags = 0 */
1098 cio_write(0, 2); /* Pre-defined */
1100 cio_write(0, 2); /* Reserved */
1102 cio_write(0, 4); /* Pre-defined */
1103 cio_write(0, 4); /* Pre-defined */
1104 cio_write(0, 4); /* Pre-defined */
1106 cio_write(tk->w, 2); /* Width */
1107 cio_write(tk->h, 2); /* Height */
1109 cio_write(tk->horizresolution, 4); /* Horizontal resolution */
1110 cio_write(tk->vertresolution, 4); /* Vertical resolution */
1112 cio_write(0, 4); /* Reserved */
1114 cio_write(1, 2); /* Pre-defined = 1 */
1116 cio_write(tk->compressorname[0], 4); /* Compressor Name */
1117 cio_write(tk->compressorname[1], 4);
1118 cio_write(tk->compressorname[2], 4);
1119 cio_write(tk->compressorname[3], 4);
1120 cio_write(tk->compressorname[4], 4);
1121 cio_write(tk->compressorname[5], 4);
1122 cio_write(tk->compressorname[6], 4);
1123 cio_write(tk->compressorname[7], 4);
1125 cio_write(tk->depth, 2); /* Depth */
1127 cio_write(0xffff, 2); /* Pre-defined = -1 */
1129 jp2_write_jp2h(&tk->jp2_struct);
1133 if (tk->num_br != 0)
1135 if (tk->num_jp2x != 0)
1141 box.length = cio_tell() - box.init_pos;
1142 cio_seek(box.init_pos);
1143 cio_write(box.length, 4); /* L */
1144 cio_seek(box.init_pos + box.length);
1150 * Visual Sample Entry Description
1153 int mj2_read_smj2(j2k_image_t * img, mj2_tk_t * tk)
1159 mj2_read_boxhdr(&box);
1161 if (MJ2_MJ2 != box.type) {
1162 fprintf(stderr, "Error in SMJ2 box: Expected MJ2 Marker\n");
1166 if (0 != cio_read(1)) { /* Version = 0 */
1167 fprintf(stderr, "Error: Only Version 0 handled in MJP2 box\n");
1171 if (0 != cio_read(3)) { /* Flags = 0 */
1172 fprintf(stderr, "Error with flag in MJP2 box. Expected flag 0\n");
1178 cio_skip(2); /* Pre-defined */
1180 cio_skip(2); /* Reserved */
1182 cio_skip(4); /* Pre-defined */
1183 cio_skip(4); /* Pre-defined */
1184 cio_skip(4); /* Pre-defined */
1186 tk->w = cio_read(2); /* Width */
1187 tk->h = cio_read(2); /* Height */
1189 tk->horizresolution = cio_read(4); /* Horizontal resolution */
1190 tk->vertresolution = cio_read(4); /* Vertical resolution */
1192 cio_skip(4); /* Reserved */
1194 cio_skip(2); /* Pre-defined = 1 */
1196 tk->compressorname[0] = cio_read(4); /* Compressor Name */
1197 tk->compressorname[1] = cio_read(4);
1198 tk->compressorname[2] = cio_read(4);
1199 tk->compressorname[3] = cio_read(4);
1200 tk->compressorname[4] = cio_read(4);
1201 tk->compressorname[5] = cio_read(4);
1202 tk->compressorname[6] = cio_read(4);
1203 tk->compressorname[7] = cio_read(4);
1205 tk->depth = cio_read(2); /* Depth */
1207 /* Init std value */
1211 tk->or_fieldcount = 1;
1212 tk->or_fieldorder = 0;
1214 cio_skip(2); /* Pre-defined = -1 */
1216 if (jp2_read_jp2h(&tk->jp2_struct)) {
1217 fprintf(stderr, "Error with JP2H Box\n");
1221 tk->jp2_struct.comps = (jp2_comps_t *) malloc(tk->jp2_struct.numcomps * sizeof(jp2_comps_t));
1222 tk->jp2_struct.cl = (int *) malloc(sizeof(int));
1227 for (i = 0; cio_tell() - box.init_pos < box.length; i++) {
1228 mj2_read_boxhdr(&box2);
1229 cio_seek(box2.init_pos);
1230 switch (box2.type) {
1232 if (mj2_read_fiel(tk))
1237 if (mj2_read_jp2p(tk))
1242 if (mj2_read_jp2x(tk))
1247 if (mj2_read_jsub(tk))
1252 if (mj2_read_orfo(tk))
1257 fprintf(stderr, "Error with MJP2 Box size\n");
1268 * Write the STSD box
1270 * Sample Description
1273 void mj2_write_stsd(mj2_tk_t * tk)
1277 box.init_pos = cio_tell();
1279 cio_write(MJ2_STSD, 4); /* STSD */
1281 cio_write(0, 4); /* Version = 0, flags = 0 */
1283 cio_write(1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
1285 if (tk->track_type == 0) {
1287 } else if (tk->track_type == 1) {
1290 if (tk->track_type == 2) {
1295 box.length = cio_tell() - box.init_pos;
1296 cio_seek(box.init_pos);
1297 cio_write(box.length, 4); /* L */
1298 cio_seek(box.init_pos + box.length);
1304 * Sample Description
1307 int mj2_read_stsd(mj2_tk_t * tk, j2k_image_t * img)
1310 int entry_count, len_2skip;
1314 mj2_read_boxhdr(&box);
1316 if (MJ2_STSD != box.type) {
1317 fprintf(stderr, "Error: Expected STSD Marker\n");
1321 if (0 != cio_read(1)) { /* Version = 0 */
1322 fprintf(stderr, "Error: Only Version 0 handled in STSD box\n");
1326 if (0 != cio_read(3)) { /* Flags = 0 */
1327 fprintf(stderr, "Error with flag in STSD box. Expected flag 0\n");
1331 entry_count = cio_read(4);
1333 if (tk->track_type == 0) {
1334 for (i = 0; i < entry_count; i++) {
1335 if (mj2_read_smj2(img, tk))
1338 } else if (tk->track_type == 1) {
1339 len_2skip = cio_read(4); // Not implemented -> skipping box
1340 cio_skip(len_2skip - 4);
1341 } else if (tk->track_type == 2) {
1342 len_2skip = cio_read(4); // Not implemented -> skipping box
1343 cio_skip(len_2skip - 4);
1347 if (cio_tell() - box.init_pos != box.length) {
1348 fprintf(stderr, "Error with STSD Box size\n");
1355 * Write the STBL box
1357 * Sample table box box
1360 void mj2_write_stbl(mj2_tk_t * tk)
1364 box.init_pos = cio_tell();
1366 cio_write(MJ2_STBL, 4); /* STBL */
1374 box.length = cio_tell() - box.init_pos;
1375 cio_seek(box.init_pos);
1376 cio_write(box.length, 4); /* L */
1377 cio_seek(box.init_pos + box.length);
1383 * Sample table box box
1386 int mj2_read_stbl(mj2_tk_t * tk, j2k_image_t * img)
1390 mj2_read_boxhdr(&box);
1391 if (MJ2_STBL != box.type) {
1392 fprintf(stderr, "Error: Expected STBL Marker\n");
1396 if (mj2_read_stsd(tk, img))
1398 if (mj2_read_stts(tk))
1400 if (mj2_read_stsc(tk))
1402 if (mj2_read_stsz(tk))
1404 if (mj2_read_stco(tk))
1407 if (cio_tell() - box.init_pos != box.length) {
1408 fprintf(stderr, "Error with STBL Box size\n");
1420 void mj2_write_url(mj2_tk_t * tk, int url_num)
1424 box.init_pos = cio_tell();
1426 cio_write(MJ2_URL, 4); /* URL */
1429 cio_write(1, 4); /* Version = 0, flags = 1 because stored in same file */
1431 cio_write(0, 4); /* Version = 0, flags = 0 */
1432 cio_write(tk->url[url_num - 1].location[0], 4);
1433 cio_write(tk->url[url_num - 1].location[1], 4);
1434 cio_write(tk->url[url_num - 1].location[2], 4);
1435 cio_write(tk->url[url_num - 1].location[3], 4);
1438 box.length = cio_tell() - box.init_pos;
1439 cio_seek(box.init_pos);
1440 cio_write(box.length, 4); /* L */
1441 cio_seek(box.init_pos + box.length);
1450 int mj2_read_url(mj2_tk_t * tk, int urn_num)
1454 mj2_read_boxhdr(&box);
1455 if (MJ2_URL != box.type) {
1456 fprintf(stderr, "Error: Expected URL Marker\n");
1460 if (0 != cio_read(1)) { /* Version = 0 */
1461 fprintf(stderr, "Error: Only Version 0 handled in URL box\n");
1465 if (1 != cio_read(3)) { /* If flags = 1 --> media data in file */
1466 tk->url[urn_num].location[0] = cio_read(4);
1467 tk->url[urn_num].location[1] = cio_read(4);
1468 tk->url[urn_num].location[2] = cio_read(4);
1469 tk->url[urn_num].location[3] = cio_read(4);
1475 if (cio_tell() - box.init_pos != box.length) {
1476 fprintf(stderr, "Error with URL Box size\n");
1488 void mj2_write_urn(mj2_tk_t * tk, int urn_num)
1492 box.init_pos = cio_tell();
1494 cio_write(MJ2_URN, 4); /* URN */
1496 cio_write(0, 4); /* Version = 0, flags = 0 */
1498 cio_write(tk->urn[urn_num].name[0], 4);
1499 cio_write(tk->urn[urn_num].name[1], 4);
1500 cio_write(tk->urn[urn_num].name[2], 4);
1501 cio_write(tk->urn[urn_num].name[3], 4);
1502 cio_write(tk->urn[urn_num].location[0], 4);
1503 cio_write(tk->urn[urn_num].location[1], 4);
1504 cio_write(tk->urn[urn_num].location[2], 4);
1505 cio_write(tk->urn[urn_num].location[3], 4);
1507 box.length = cio_tell() - box.init_pos;
1508 cio_seek(box.init_pos);
1509 cio_write(box.length, 4); /* L */
1510 cio_seek(box.init_pos + box.length);
1519 int mj2_read_urn(mj2_tk_t * tk, int urn_num)
1524 mj2_read_boxhdr(&box);
1525 if (MJ2_URN != box.type) {
1526 fprintf(stderr, "Error: Expected URN Marker\n");
1530 if (0 != cio_read(1)) { /* Version = 0 */
1531 fprintf(stderr, "Error: Only Version 0 handled in URN box\n");
1535 if (1 != cio_read(3)) { /* If flags = 1 --> media data in file */
1536 tk->urn[urn_num].name[0] = cio_read(4);
1537 tk->urn[urn_num].name[1] = cio_read(4);
1538 tk->urn[urn_num].name[2] = cio_read(4);
1539 tk->urn[urn_num].name[3] = cio_read(4);
1540 tk->urn[urn_num].location[0] = cio_read(4);
1541 tk->urn[urn_num].location[1] = cio_read(4);
1542 tk->urn[urn_num].location[2] = cio_read(4);
1543 tk->urn[urn_num].location[3] = cio_read(4);
1547 if (cio_tell() - box.init_pos != box.length) {
1548 fprintf(stderr, "Error with URN Box size\n");
1556 * Write the DREF box
1558 * Data reference box
1561 void mj2_write_dref(mj2_tk_t * tk)
1566 box.init_pos = cio_tell();
1568 cio_write(MJ2_DREF, 4); /* DREF */
1570 cio_write(0, 4); /* Version = 0, flags = 0 */
1572 if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
1573 cio_write(1, 4); /* entry_count = 1 */
1574 mj2_write_url(tk, 0);
1576 cio_write(tk->num_url + tk->num_urn, 4); /* entry_count */
1578 for (i = 0; i < tk->num_url; i++)
1579 mj2_write_url(tk, i + 1);
1581 for (i = 0; i < tk->num_urn; i++)
1582 mj2_write_urn(tk, i);
1585 box.length = cio_tell() - box.init_pos;
1586 cio_seek(box.init_pos);
1587 cio_write(box.length, 4); /* L */
1588 cio_seek(box.init_pos + box.length);
1594 * Data reference box
1597 int mj2_read_dref(mj2_tk_t * tk)
1601 int entry_count, marker;
1604 mj2_read_boxhdr(&box);
1605 if (MJ2_DREF != box.type) {
1606 fprintf(stderr, "Error: Expected DREF Marker\n");
1610 if (0 != cio_read(1)) { /* Version = 0 */
1611 fprintf(stderr, "Error: Only Version 0 handled in DREF box\n");
1615 if (0 != cio_read(3)) { /* Flags = 0 */
1616 fprintf(stderr, "Error with flag in DREF box. Expected flag 0\n");
1620 entry_count = cio_read(4);
1624 for (i = 0; i < entry_count; i++) {
1626 marker = cio_read(4);
1627 if (marker == MJ2_URL) {
1630 if (mj2_read_url(tk, tk->num_url))
1632 } else if (marker == MJ2_URN) {
1635 if (mj2_read_urn(tk, tk->num_urn))
1638 fprintf(stderr, "Error with in DREF box. Expected URN or URL box\n");
1645 if (cio_tell() - box.init_pos != box.length) {
1646 fprintf(stderr, "Error with DREF Box size\n");
1653 * Write the DINF box
1655 * Data information box
1658 void mj2_write_dinf(mj2_tk_t * tk)
1662 box.init_pos = cio_tell();
1664 cio_write(MJ2_DINF, 4); /* DINF */
1668 box.length = cio_tell() - box.init_pos;
1669 cio_seek(box.init_pos);
1670 cio_write(box.length, 4); /* L */
1671 cio_seek(box.init_pos + box.length);
1677 * Data information box
1680 int mj2_read_dinf(mj2_tk_t * tk)
1684 mj2_read_boxhdr(&box);
1685 if (MJ2_DINF != box.type) {
1686 fprintf(stderr, "Error: Expected DINF Marker\n");
1690 if (mj2_read_dref(tk))
1693 if (cio_tell() - box.init_pos != box.length) {
1694 fprintf(stderr, "Error with DINF Box size\n");
1701 * Write the VMHD box
1703 * Video Media information box
1706 void mj2_write_vmhd(mj2_tk_t * tk)
1710 box.init_pos = cio_tell();
1712 cio_write(MJ2_VMHD, 4); /* VMHD */
1714 cio_write(1, 4); /* Version = 0, flags = 1 */
1716 cio_write(tk->graphicsmode, 2);
1717 cio_write(tk->opcolor[0], 2);
1718 cio_write(tk->opcolor[1], 2);
1719 cio_write(tk->opcolor[2], 2);
1721 box.length = cio_tell() - box.init_pos;
1722 cio_seek(box.init_pos);
1723 cio_write(box.length, 4); /* L */
1724 cio_seek(box.init_pos + box.length);
1730 * Video Media information box
1733 int mj2_read_vmhd(mj2_tk_t * tk)
1737 mj2_read_boxhdr(&box);
1738 if (MJ2_VMHD != box.type) {
1739 fprintf(stderr, "Error: Expected VMHD Marker\n");
1743 if (0 != cio_read(1)) { /* Version = 0 */
1744 fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
1748 if (1 != cio_read(3)) { /* Flags = 1 */
1749 fprintf(stderr, "Error with flag in VMHD box. Expected flag 1\n");
1754 tk->graphicsmode = cio_read(2);
1755 tk->opcolor[0] = cio_read(2);
1756 tk->opcolor[1] = cio_read(2);
1757 tk->opcolor[2] = cio_read(2);
1759 if (cio_tell() - box.init_pos != box.length) {
1760 fprintf(stderr, "Error with VMHD Box size\n");
1767 * Write the SMHD box
1769 * Sound Media information box
1772 void mj2_write_smhd(mj2_tk_t * tk)
1776 box.init_pos = cio_tell();
1778 cio_write(MJ2_SMHD, 4); /* SMHD */
1780 cio_write(0, 4); /* Version = 0, flags = 0 */
1782 cio_write(tk->balance << 8, 2);
1784 cio_write(0, 2); /* Reserved */
1786 box.length = cio_tell() - box.init_pos;
1787 cio_seek(box.init_pos);
1788 cio_write(box.length, 4); /* L */
1789 cio_seek(box.init_pos + box.length);
1795 * Sound Media information box
1798 int mj2_read_smhd(mj2_tk_t * tk)
1802 mj2_read_boxhdr(&box);
1803 if (MJ2_SMHD != box.type) {
1804 fprintf(stderr, "Error: Expected SMHD Marker\n");
1808 if (0 != cio_read(1)) { /* Version = 0 */
1809 fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
1813 if (0 != cio_read(3)) { /* Flags = 0 */
1814 fprintf(stderr, "Error with flag in VMHD box. Expected flag 0\n");
1819 tk->balance = cio_read(2) >> 8;
1821 cio_skip(2); /* Reserved */
1823 if (cio_tell() - box.init_pos != box.length) {
1824 fprintf(stderr, "Error with SMHD Box size\n");
1831 * Write the HMHD box
1833 * Hint Media information box
1836 void mj2_write_hmhd(mj2_tk_t * tk)
1840 box.init_pos = cio_tell();
1842 cio_write(MJ2_HMHD, 4); /* HMHD */
1844 cio_write(0, 4); /* Version = 0, flags = 0 */
1846 cio_write(tk->maxPDUsize, 2);
1847 cio_write(tk->avgPDUsize, 2);
1848 cio_write(tk->maxbitrate, 4);
1849 cio_write(tk->avgbitrate, 4);
1850 cio_write(tk->slidingavgbitrate, 4);
1852 box.length = cio_tell() - box.init_pos;
1853 cio_seek(box.init_pos);
1854 cio_write(box.length, 4); /* L */
1855 cio_seek(box.init_pos + box.length);
1861 * Hint Media information box
1864 int mj2_read_hmhd(mj2_tk_t * tk)
1868 mj2_read_boxhdr(&box);
1869 if (MJ2_HMHD != box.type) {
1870 fprintf(stderr, "Error: Expected HMHD Marker\n");
1874 if (0 != cio_read(1)) { /* Version = 0 */
1875 fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
1879 if (0 != cio_read(3)) { /* Flags = 0 */
1880 fprintf(stderr, "Error with flag in VMHD box. Expected flag 0\n");
1885 tk->maxPDUsize = cio_read(2);
1886 tk->avgPDUsize = cio_read(2);
1887 tk->maxbitrate = cio_read(4);
1888 tk->avgbitrate = cio_read(4);
1889 tk->slidingavgbitrate = cio_read(4);
1891 if (cio_tell() - box.init_pos != box.length) {
1892 fprintf(stderr, "Error with HMHD Box size\n");
1899 * Write the MINF box
1901 * Media information box
1904 void mj2_write_minf(mj2_tk_t * tk)
1908 box.init_pos = cio_tell();
1910 cio_write(MJ2_MINF, 4); /* MINF */
1912 if (tk->track_type == 0) {
1914 } else if (tk->track_type == 1) {
1916 } else if (tk->track_type == 2) {
1923 box.length = cio_tell() - box.init_pos;
1924 cio_seek(box.init_pos);
1925 cio_write(box.length, 4); /* L */
1926 cio_seek(box.init_pos + box.length);
1932 * Media information box
1935 int mj2_read_minf(mj2_tk_t * tk, j2k_image_t * img)
1938 unsigned int box_type;
1941 mj2_read_boxhdr(&box);
1942 if (MJ2_MINF != box.type) {
1943 fprintf(stderr, "Error: Expected MINF Marker\n");
1948 box_type = cio_read(4);
1951 if (box_type == MJ2_VMHD) {
1952 if (mj2_read_vmhd(tk))
1954 } else if (box_type == MJ2_SMHD) {
1955 if (mj2_read_smhd(tk))
1957 } else if (box_type == MJ2_HMHD) {
1958 if (mj2_read_hmhd(tk))
1961 fprintf(stderr, "Error in MINF box expected vmhd, smhd or hmhd\n");
1965 if (mj2_read_dinf(tk))
1968 if (mj2_read_stbl(tk, img))
1971 if (cio_tell() - box.init_pos != box.length) {
1972 fprintf(stderr, "Error with MINF Box size\n");
1979 * Write the HDLR box
1981 * Handler reference box
1984 void mj2_write_hdlr(mj2_tk_t * tk)
1988 box.init_pos = cio_tell();
1990 cio_write(MJ2_HDLR, 4); /* HDLR */
1992 cio_write(0, 4); /* Version = 0, flags = 0 */
1994 cio_write(0, 4); /* Predefine */
1996 tk->name = 0; /* The track name is immediately determined by the track type */
1998 if (tk->track_type == 0) {
1999 tk->handler_type = 0x76696465; /* Handler type: vide */
2000 cio_write(tk->handler_type, 4);
2004 cio_write(0, 4); /* Reserved */
2006 cio_write(0x76696465, 4);
2007 cio_write(0x6F206d65, 4);
2008 cio_write(0x64696120, 4);
2009 cio_write(0x74726163, 4);
2010 cio_write(0x6b00, 2); /* String: video media track */
2011 } else if (tk->track_type == 1) {
2012 tk->handler_type = 0x736F756E; /* Handler type: soun */
2013 cio_write(tk->handler_type, 4);
2017 cio_write(0, 4); /* Reserved */
2019 cio_write(0x536F756E, 4);
2020 cio_write(0x6400, 2); /* String: Sound */
2021 } else if (tk->track_type == 2) {
2022 tk->handler_type = 0x68696E74; /* Handler type: hint */
2023 cio_write(tk->handler_type, 4);
2027 cio_write(0, 4); /* Reserved */
2029 cio_write(0x48696E74, 4);
2030 cio_write(0, 2); /* String: Hint */
2033 box.length = cio_tell() - box.init_pos;
2034 cio_seek(box.init_pos);
2035 cio_write(box.length, 4); /* L */
2036 cio_seek(box.init_pos + box.length);
2042 * Handler reference box
2045 int mj2_read_hdlr(mj2_tk_t * tk)
2050 mj2_read_boxhdr(&box);
2051 if (MJ2_HDLR != box.type) {
2052 fprintf(stderr, "Error: Expected HDLR Marker\n");
2057 if (0 != cio_read(1)) { /* Version = 0 */
2058 fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
2062 if (0 != cio_read(3)) { /* Flags = 0 */
2063 fprintf(stderr, "Error with flag in VMHD box. Expected flag 0\n");
2067 cio_skip(4); /* Reserved */
2069 tk->handler_type = cio_read(4);
2070 cio_skip(12); /* Reserved */
2072 tk->name_size = box.length - 32;
2074 tk->name = (char *) malloc(tk->name_size * sizeof(char));
2075 for (i = 0; i < tk->name_size; i++) {
2076 tk->name[i] = cio_read(1); /* Name */
2079 if (cio_tell() - box.init_pos != box.length) {
2080 fprintf(stderr, "Error with HDLR Box size\n");
2087 * Write the MDHD box
2092 void mj2_write_mdhd(mj2_tk_t * tk)
2097 unsigned int modification_time;
2099 box.init_pos = cio_tell();
2101 cio_write(MJ2_MDHD, 4); /* MDHD */
2103 cio_write(0, 4); /* Version = 0, flags = 0 */
2105 cio_write(tk->creation_time, 4); /* Creation Time */
2107 time(<ime); /* Time since 1/1/70 */
2108 modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2110 cio_write(modification_time, 4); /* Modification Time */
2112 cio_write(tk->timescale, 4); /* Timescale */
2116 for (i = 0; i < tk->num_samples; i++)
2117 tk->duration += tk->sample[i].sample_delta;
2119 cio_write(tk->duration, 4); /* Duration */
2121 cio_write(tk->language, 2); /* Language */
2123 cio_write(0, 2); /* Predefined */
2125 box.length = cio_tell() - box.init_pos;
2126 cio_seek(box.init_pos);
2127 cio_write(box.length, 4); /* L */
2128 cio_seek(box.init_pos + box.length);
2137 int mj2_read_mdhd(mj2_tk_t * tk)
2141 mj2_read_boxhdr(&box);
2142 if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) { // Kakadu writes MHDR instead of MDHD
2143 fprintf(stderr, "Error: Expected MDHD Marker\n");
2147 if (0 != cio_read(1)) { /* Version = 0 */
2148 fprintf(stderr, "Error: Only Version 0 handled in MDHD box\n");
2152 if (0 != cio_read(3)) { /* Flags = 0 */
2153 fprintf(stderr, "Error with flag in MDHD box. Expected flag 0\n");
2158 tk->creation_time = cio_read(4); /* Creation Time */
2160 tk->modification_time = cio_read(4); /* Modification Time */
2162 tk->timescale = cio_read(4); /* Timescale */
2164 tk->duration = cio_read(4); /* Duration */
2166 tk->language = cio_read(2); /* Language */
2168 cio_skip(2); /* Predefined */
2170 if (cio_tell() - box.init_pos != box.length) {
2171 fprintf(stderr, "Error with MDHD Box size\n");
2178 * Write the MDIA box
2183 void mj2_write_mdia(mj2_tk_t * tk)
2187 box.init_pos = cio_tell();
2189 cio_write(MJ2_MDIA, 4); /* MDIA */
2195 box.length = cio_tell() - box.init_pos;
2196 cio_seek(box.init_pos);
2197 cio_write(box.length, 4); /* L */
2198 cio_seek(box.init_pos + box.length);
2207 int mj2_read_mdia(mj2_tk_t * tk, j2k_image_t * img)
2211 mj2_read_boxhdr(&box);
2212 if (MJ2_MDIA != box.type) {
2213 fprintf(stderr, "Error: Expected MDIA Marker\n");
2217 if (mj2_read_mdhd(tk))
2219 if (mj2_read_hdlr(tk))
2221 if (mj2_read_minf(tk, img))
2224 if (cio_tell() - box.init_pos != box.length) {
2225 fprintf(stderr, "Error with MDIA Box size\n");
2232 * Write the TKHD box
2237 void mj2_write_tkhd(mj2_tk_t * tk)
2243 box.init_pos = cio_tell();
2246 cio_write(MJ2_TKHD, 4); /* TKHD */
2248 cio_write(3, 4); /* Version=0, flags=3 */
2250 time(<ime); /* Time since 1/1/70 */
2251 tk->modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2253 cio_write(tk->creation_time, 4); /* Creation Time */
2255 cio_write(tk->modification_time, 4); /* Modification Time */
2257 cio_write(tk->track_ID, 4); /* Track ID */
2259 cio_write(0, 4); /* Reserved */
2263 for (i = 0; i < tk->num_samples; i++)
2264 tk->duration += tk->sample[i].sample_delta;
2266 cio_write(tk->duration, 4); /* Duration */
2268 cio_write(0, 4); /* Reserved */
2269 cio_write(0, 4); /* Reserved */
2271 cio_write(tk->layer, 2); /* Layer */
2273 cio_write(0, 2); /* Predefined */
2275 cio_write(tk->volume << 8, 2); /* Volume */
2277 cio_write(0, 2); /* Reserved */
2279 cio_write(tk->trans_matrix[0], 4); /* Transformation matrix for track */
2280 cio_write(tk->trans_matrix[1], 4);
2281 cio_write(tk->trans_matrix[2], 4);
2282 cio_write(tk->trans_matrix[3], 4);
2283 cio_write(tk->trans_matrix[4], 4);
2284 cio_write(tk->trans_matrix[5], 4);
2285 cio_write(tk->trans_matrix[6], 4);
2286 cio_write(tk->trans_matrix[7], 4);
2287 cio_write(tk->trans_matrix[8], 4);
2289 cio_write(tk->w << 16, 4); /* Video Width */
2291 cio_write(tk->h << 16, 4); /* Video Height */
2293 box.length = cio_tell() - box.init_pos;
2294 cio_seek(box.init_pos);
2295 cio_write(box.length, 4); /* L */
2296 cio_seek(box.init_pos + box.length);
2305 int mj2_read_tkhd(mj2_tk_t * tk)
2311 mj2_read_boxhdr(&box);
2313 if (MJ2_TKHD != box.type) {
2314 fprintf(stderr, "Error: Expected TKHD Marker\n");
2318 if (0 != cio_read(1)) { /* Version = 0 */
2319 fprintf(stderr, "Error: Only Version 0 handled in TKHD box\n");
2325 if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) { /* Flags = 1,2,3 or 4 */
2327 "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2331 tk->creation_time = cio_read(4); /* Creation Time */
2333 tk->modification_time = cio_read(4); /* Modification Time */
2335 tk->track_ID = cio_read(4); /* Track ID */
2337 cio_skip(4); /* Reserved */
2339 tk->duration = cio_read(4); /* Duration */
2341 cio_skip(8); /* Reserved */
2343 tk->layer = cio_read(2); /* Layer */
2345 cio_read(2); /* Predefined */
2347 tk->volume = cio_read(2) >> 8; /* Volume */
2349 cio_skip(2); /* Reserved */
2351 tk->trans_matrix[0] = cio_read(4); /* Transformation matrix for track */
2352 tk->trans_matrix[1] = cio_read(4);
2353 tk->trans_matrix[2] = cio_read(4);
2354 tk->trans_matrix[3] = cio_read(4);
2355 tk->trans_matrix[4] = cio_read(4);
2356 tk->trans_matrix[5] = cio_read(4);
2357 tk->trans_matrix[6] = cio_read(4);
2358 tk->trans_matrix[7] = cio_read(4);
2359 tk->trans_matrix[8] = cio_read(4);
2361 tk->w = cio_read(4) >> 16; /* Video Width */
2363 tk->h = cio_read(4) >> 16; /* Video Height */
2365 if (cio_tell() - box.init_pos != box.length) {
2366 fprintf(stderr, "Error with TKHD Box size\n");
2373 * Write the TRAK box
2378 void mj2_write_trak(mj2_tk_t * tk)
2382 box.init_pos = cio_tell();
2385 cio_write(MJ2_TRAK, 4); /* TRAK */
2390 box.length = cio_tell() - box.init_pos;
2391 cio_seek(box.init_pos);
2392 cio_write(box.length, 4); /* L */
2393 cio_seek(box.init_pos + box.length);
2402 int mj2_read_trak(mj2_tk_t * tk, j2k_image_t * img)
2406 mj2_read_boxhdr(&box);
2407 if (MJ2_TRAK != box.type) {
2408 fprintf(stderr, "Error: Expected TRAK Marker\n");
2411 if (mj2_read_tkhd(tk))
2413 if (mj2_read_mdia(tk, img))
2415 if (cio_tell() - box.init_pos != box.length) {
2416 fprintf(stderr, "Error with TRAK Box\n");
2423 * Write the MVHD box
2428 void mj2_write_mvhd(mj2_movie_t * movie)
2436 box.init_pos = cio_tell();
2438 cio_write(MJ2_MVHD, 4); /* MVHD */
2440 cio_write(0, 4); /* Version = 0, flags = 0 */
2442 time(<ime); /* Time since 1/1/70 */
2443 movie->modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2445 cio_write(movie->creation_time, 4); /* Creation Time */
2447 cio_write(movie->modification_time, 4); /* Modification Time */
2449 cio_write(movie->timescale, 4); /* Timescale */
2451 movie->duration = 0;
2453 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2454 mj2_tk_t *tk = &movie->tk[i];
2456 for (j = 0; j < tk->num_samples; j++) {
2457 movie->duration += tk->sample[j].sample_delta;
2461 cio_write(movie->duration, 4);
2463 cio_write(movie->rate << 16, 4); /* Rate to play presentation */
2465 cio_write(movie->volume << 8, 2); /* Volume */
2467 cio_write(0, 2); /* Reserved */
2468 cio_write(0, 4); /* Reserved */
2469 cio_write(0, 4); /* Reserved */
2471 cio_write(movie->trans_matrix[0], 4); /* Transformation matrix for video */
2472 cio_write(movie->trans_matrix[1], 4);
2473 cio_write(movie->trans_matrix[2], 4);
2474 cio_write(movie->trans_matrix[3], 4);
2475 cio_write(movie->trans_matrix[4], 4);
2476 cio_write(movie->trans_matrix[5], 4);
2477 cio_write(movie->trans_matrix[6], 4);
2478 cio_write(movie->trans_matrix[7], 4);
2479 cio_write(movie->trans_matrix[8], 4);
2481 cio_write(0, 4); /* Pre-defined */
2482 cio_write(0, 4); /* Pre-defined */
2483 cio_write(0, 4); /* Pre-defined */
2484 cio_write(0, 4); /* Pre-defined */
2485 cio_write(0, 4); /* Pre-defined */
2486 cio_write(0, 4); /* Pre-defined */
2489 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
2490 if (max_tk_num < movie->tk[i].track_ID)
2491 max_tk_num = movie->tk[i].track_ID;
2494 movie->next_tk_id = max_tk_num + 1;
2496 cio_write(movie->next_tk_id, 4); /* ID of Next track to be added */
2498 box.length = cio_tell() - box.init_pos;
2499 cio_seek(box.init_pos);
2500 cio_write(box.length, 4); /* L */
2501 cio_seek(box.init_pos + box.length);
2510 int mj2_read_mvhd(mj2_movie_t * movie)
2514 mj2_read_boxhdr(&box);
2515 if (MJ2_MVHD != box.type) {
2516 fprintf(stderr, "Error: Expected MVHD Marker\n");
2521 if (0 != cio_read(4)) { /* Version = 0, flags = 0 */
2522 fprintf(stderr, "Error: Only Version 0 handled\n");
2525 movie->creation_time = cio_read(4); /* Creation Time */
2527 movie->modification_time = cio_read(4); /* Modification Time */
2529 movie->timescale = cio_read(4); /* Timescale */
2531 movie->duration = cio_read(4); /* Duration */
2533 movie->rate = cio_read(4) >> 16; /* Rate to play presentation */
2535 movie->volume = cio_read(2) >> 8; /* Volume */
2537 cio_skip(10); /* Reserved */
2539 movie->trans_matrix[0] = cio_read(4); /* Transformation matrix for video */
2540 movie->trans_matrix[1] = cio_read(4);
2541 movie->trans_matrix[2] = cio_read(4);
2542 movie->trans_matrix[3] = cio_read(4);
2543 movie->trans_matrix[4] = cio_read(4);
2544 movie->trans_matrix[5] = cio_read(4);
2545 movie->trans_matrix[6] = cio_read(4);
2546 movie->trans_matrix[7] = cio_read(4);
2547 movie->trans_matrix[8] = cio_read(4);
2549 cio_skip(24); /* Pre-defined */
2551 movie->next_tk_id = cio_read(4); /* ID of Next track to be added */
2553 if (cio_tell() - box.init_pos != box.length) {
2554 fprintf(stderr, "Error with MVHD Box Size\n");
2562 * Write the MOOV box
2567 void mj2_write_moov(mj2_movie_t * movie)
2572 box.init_pos = cio_tell();
2574 cio_write(MJ2_MOOV, 4); /* MOOV */
2576 mj2_write_mvhd(movie);
2578 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2579 mj2_write_trak(&movie->tk[i]);
2582 box.length = cio_tell() - box.init_pos;
2583 cio_seek(box.init_pos);
2584 cio_write(box.length, 4); /* L */
2585 cio_seek(box.init_pos + box.length);
2595 int mj2_read_moov(mj2_movie_t * movie, j2k_image_t * img)
2601 mj2_read_boxhdr(&box);
2602 if (MJ2_MOOV != box.type) {
2603 fprintf(stderr, "Error: Expected MOOV Marker\n");
2609 if (mj2_read_mvhd(movie))
2614 (mj2_tk_t *) malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2616 for (i = 0; cio_tell() - box.init_pos < box.length; i++) {
2617 mj2_read_boxhdr(&box2);
2618 if (box2.type == MJ2_TRAK) {
2619 cio_seek(box2.init_pos);
2620 if (mj2_read_trak(&movie->tk[i], img))
2623 if (movie->tk[i].track_type == 0) {
2625 } else if (movie->tk[i].track_type == 1) {
2627 } else if (movie->tk[i].track_type == 2) {
2630 } else if (box2.type == MJ2_MVEX) {
2631 cio_seek(box2.init_pos);
2632 cio_skip(box2.length);
2635 fprintf(stderr, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2642 int mj2_read_struct(FILE *file, mj2_movie_t * movie) {
2653 src = (char*) malloc (300 * sizeof(char));
2654 fread(src,300,1, file); // Assuming that jp and ftyp markers size do
2655 // not exceed 300 bytes
2661 if (mj2_read_ftyp(movie))
2664 fsresult = fseek(file,cio_tell(),SEEK_SET);
2666 fprintf(stderr, "End of file reached while trying to read data after FTYP box\n" );
2670 foffset = cio_tell();
2674 fread(src,30,1,file);
2676 mj2_read_boxhdr(&box);
2678 while(box.type != MJ2_MOOV) {
2683 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2685 fprintf(stderr, "End of file reached while trying to read MDAT box\n" );
2688 foffset += box.length;
2692 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2694 fprintf(stderr, "End of file reached while trying to read MOOF box\n" );
2697 foffset += box.length;
2700 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2702 fprintf(stderr, "End of file reached while trying to read FREE box\n" );
2705 foffset += box.length;
2708 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2710 fprintf(stderr, "End of file reached while trying to read SKIP bo\nx" );
2713 foffset += box.length;
2716 fprintf(stderr, "Unknown box in MJ2 stream\n");
2717 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2719 fprintf(stderr, "End of file reached while trying to read %s box\n", box.type );
2722 foffset += box.length;
2725 fsresult = fread(src,8,1,file);
2726 if (fsresult != 1) {
2727 fprintf(stderr, "MOOV box not found in file\n");
2731 mj2_read_boxhdr(&box);
2734 fseek(file,foffset,SEEK_SET);
2735 src = realloc(src,box.length);
2736 fsresult = fread(src,box.length,1,file);
2737 if (fsresult != 1) {
2738 fprintf(stderr, "End of file reached while trying to read MOOV box\n");
2742 cio_init(src, box.length);
2744 if (mj2_read_moov(movie, &img))