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->track_type == 0) {// Video track
95 if (tk->jp2_struct.comps != 0)
96 free(tk->jp2_struct.comps);
97 if (tk->jp2_struct.cl != 0)
98 free(tk->jp2_struct.cl);
99 if (tk->num_jp2x != 0)
103 if (tk->num_url != 0)
105 if (tk->num_urn != 0)
109 if (tk->num_tts != 0)
111 if (tk->num_chunks != 0)
113 if (tk->num_samplestochunk != 0)
114 free(tk->sampletochunk);
115 if (tk->num_samples != 0)
128 int mj2_read_boxhdr(mj2_box_t * box)
130 box->init_pos = cio_tell();
131 box->length = cio_read(4);
132 box->type = cio_read(4);
133 if (box->length == 1) {
134 if (cio_read(4) != 0) {
135 fprintf(stderr, "Error: Cannot handle box sizes higher than 2^32\n");
138 box->length = cio_read(4);
139 if (box->length == 0)
140 box->length = cio_numbytesleft() + 12;
142 else if (box->length == 0) {
143 box->length = cio_numbytesleft() + 8;
150 * Initialisation of a Standard Movie, given a simple movie structure defined by the user
151 * The movie will have one sample per chunk
153 * Arguments: mj2_movie_t * movie
154 * Several variables of "movie" must be defined in order to enable a correct execution of
156 * - The number of tracks of each type (movie->num_vtk, movie->num_stk, movie->num_htk)
157 * - The memory for each must be allocated (movie->tk)
159 * The track type (tk->track_type)
160 * The number of sample (tk->num_samples)
161 * The sample rate (tk->sample_rate)
165 int mj2_init_stdmovie(mj2_movie_t * movie)
171 movie->brand = MJ2_MJ2;
172 movie->minversion = 0;
175 (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
177 movie->cl[0] = MJ2_MJ2;
178 movie->cl[1] = MJ2_MJ2S;
179 time(<ime); /* Time since 1/1/70 */
180 movie->creation_time = (unsigned int) ltime + 2082844800; /* Seconds between 1/1/04 and 1/1/70 */
181 movie->timescale = 1000;
183 movie->rate = 1 << 16; /* Rate to play presentation (default = 0x00010000) */
184 movie->volume = 1 << 8; /* Movie volume (default = 0x0100) */
185 movie->trans_matrix[0] = 0x00010000; /* Transformation matrix for video */
186 movie->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
187 movie->trans_matrix[2] = 0;
188 movie->trans_matrix[3] = 0;
189 movie->trans_matrix[4] = 0x00010000;
190 movie->trans_matrix[5] = 0;
191 movie->trans_matrix[6] = 0;
192 movie->trans_matrix[7] = 0;
193 movie->trans_matrix[8] = 0x40000000;
194 movie->next_tk_id = 1;
196 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
197 mj2_tk_t *tk = &movie->tk[i];
199 tk->jp2_struct.comps = NULL;
200 tk->jp2_struct.cl = NULL;
202 if (tk->track_type == 0) {
203 if (tk->num_samples == 0)
209 tk->timescale = 1000; /* Timescale = 1 ms */
211 tk->chunk[0].num_samples = 1;
212 tk->chunk[0].sample_descr_idx = 1;
214 tk->same_sample_size = 0;
216 tk->num_samplestochunk = 1; /* One sample per chunk */
218 (mj2_sampletochunk_t *) malloc(tk->num_samplestochunk *
219 sizeof(mj2_sampletochunk_t));
220 tk->sampletochunk[0].first_chunk = 1;
221 tk->sampletochunk[0].samples_per_chunk = 1;
222 tk->sampletochunk[0].sample_descr_idx = 1;
224 if (tk->sample_rate == 0) {
225 fprintf(stderr,"Error while initializing MJ2 movie: Sample rate of track %d must be different from zero\n",tk->track_ID);
229 for (j = 0; j < tk->num_samples; j++) {
230 tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
234 tk->tts = (mj2_tts_t *) malloc(tk->num_tts * sizeof(mj2_tts_t));
235 tk->tts[0].sample_count = tk->num_samples;
236 tk->tts[0].sample_delta = tk->timescale / tk->sample_rate;
238 tk->horizresolution = 0x00480000; /* Horizontal resolution (typically 72) */
239 tk->vertresolution = 0x00480000; /* Vertical resolution (typically 72) */
240 tk->compressorname[0] = 0x0f4d6f74; /* Compressor Name[]: Motion JPEG2000 */
241 tk->compressorname[1] = 0x696f6e20;
242 tk->compressorname[2] = 0x4a504547;
243 tk->compressorname[3] = 0x32303030;
244 tk->compressorname[4] = 0x00120000;
245 tk->compressorname[5] = 0;
246 tk->compressorname[6] = 0x00000042;
247 tk->compressorname[7] = 0x000000DC;
248 tk->num_url = 0; /* Number of URL */
249 tk->num_urn = 0; /* Number of URN */
250 tk->graphicsmode = 0; /* Graphicsmode */
251 tk->opcolor[0] = 0; /* OpColor */
252 tk->opcolor[1] = 0; /* OpColor */
253 tk->opcolor[2] = 0; /* OpColor */
254 tk->creation_time = movie->creation_time; /* Seconds between 1/1/04 and 1/1/70 */
255 tk->language = 0; /* Language (undefined) */
257 tk->volume = 1 << 8; /* Movie volume (default = 0x0100) */
258 tk->trans_matrix[0] = 0x00010000; /* Transformation matrix for track */
259 tk->trans_matrix[1] = 0; /* Unity is { 0x00010000,0,0,0,0x00010000,0,0,0,0x40000000 } */
260 tk->trans_matrix[2] = 0;
261 tk->trans_matrix[3] = 0;
262 tk->trans_matrix[4] = 0x00010000;
263 tk->trans_matrix[5] = 0;
264 tk->trans_matrix[6] = 0;
265 tk->trans_matrix[7] = 0;
266 tk->trans_matrix[8] = 0x40000000;
269 tk->or_fieldcount = 1;
270 tk->or_fieldorder = 0;
272 tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
274 tk->br[1] = MJ2_J2P0;
276 tk->hsub = 2; /* 4:2:0 */
277 tk->vsub = 2; /* 4:2:0 */
280 tk->visual_w = tk->w << 16;
281 tk->visual_h = tk->h << 16;
292 * Time To Sample box Decompact
295 void mj2_tts_decompact(mj2_tk_t * tk)
299 for (i = 0; i < tk->num_tts; i++) {
300 tk->num_samples += tk->tts[i].sample_count;
304 (mj2_sample_t *) malloc(tk->num_samples * sizeof(mj2_sample_t));
306 for (i = 0; i < tk->num_tts; i++) {
307 for (j = 0; j < tk->tts[i].sample_count; j++) {
308 tk->sample[j].sample_delta = tk->tts[i].sample_delta;
314 * Sample To Chunk box Decompact
317 void mj2_stsc_decompact(mj2_tk_t * tk)
323 if (tk->num_samplestochunk == 1) {
325 (unsigned int) ceil((double) tk->num_samples /
326 (double) tk->sampletochunk[0].samples_per_chunk);
328 (mj2_chunk_t *) malloc(tk->num_chunks * sizeof(mj2_chunk_t));
329 for (k = 0; k < tk->num_chunks; k++) {
330 tk->chunk[k].num_samples = tk->sampletochunk[0].samples_per_chunk;
335 (mj2_chunk_t *) malloc(tk->num_samples * sizeof(mj2_chunk_t));
337 for (i = 0; i < tk->num_samplestochunk -1 ; i++) {
338 for (j = tk->sampletochunk[i].first_chunk - 1;
339 j < tk->sampletochunk[i + 1].first_chunk - 1; j++) {
340 tk->chunk[j].num_samples = tk->sampletochunk[i].samples_per_chunk;
342 sampleno += tk->chunk[j].num_samples;
345 tk->num_chunks += (int)(tk->num_samples - sampleno) / tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
346 for (k = tk->sampletochunk[tk->num_samplestochunk - 1].first_chunk - 1;
347 k < tk->num_chunks; k++) {
348 tk->chunk[k].num_samples =
349 tk->sampletochunk[tk->num_samplestochunk - 1].samples_per_chunk;
351 tk->chunk = realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
358 * Chunk offset box Decompact
361 void mj2_stco_decompact(mj2_tk_t * tk)
366 int intra_chunk_offset;
368 for (i = 0; i < tk->num_chunks; i++) {
369 intra_chunk_offset = 0;
370 for (j = 0; j < tk->chunk[i].num_samples; j++) {
371 tk->sample[k].offset = intra_chunk_offset + tk->chunk[i].offset;
372 intra_chunk_offset += tk->sample[k].sample_size;
387 box.init_pos = cio_tell();
390 cio_write(MJ2_JP, 4); /* JP */
391 cio_write(0x0d0a870a, 4); /* 0x0d0a870a required in a JP box */
393 box.length = cio_tell() - box.init_pos;
394 cio_seek(box.init_pos);
395 cio_write(box.length, 4);
396 cio_seek(box.init_pos + box.length);
402 * JPEG 2000 signature
409 mj2_read_boxhdr(&box);
410 if (MJ2_JP != box.type) { /* Check Marker */
411 fprintf(stderr, "Error: Expected JP Marker\n");
414 if (0x0d0a870a != cio_read(4)) { /* read the 0x0d0a870a required in a JP box */
415 fprintf(stderr, "Error with JP Marker\n");
418 if (cio_tell() - box.init_pos != box.length) { /* Check box length */
419 fprintf(stderr, "Error with JP Box size \n");
432 void mj2_write_ftyp(mj2_movie_t * movie)
436 box.init_pos = cio_tell();
439 cio_write(MJ2_FTYP, 4); /* FTYP */
440 cio_write(movie->brand, 4); /* BR */
441 cio_write(movie->minversion, 4); /* MinV */
443 for (i = 0; i < movie->num_cl; i++)
444 cio_write(movie->cl[i], 4); /* CL */
446 box.length = cio_tell() - box.init_pos;
447 cio_seek(box.init_pos);
448 cio_write(box.length, 4); /* Length */
449 cio_seek(box.init_pos + box.length);
458 int mj2_read_ftyp(mj2_movie_t * movie)
463 mj2_read_boxhdr(&box); /* Box Size */
464 if (MJ2_FTYP != box.type) {
465 fprintf(stderr, "Error: Expected FTYP Marker\n");
469 movie->brand = cio_read(4); /* BR */
470 movie->minversion = cio_read(4); /* MinV */
471 movie->num_cl = (box.length - 16) / 4;
473 (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
475 for (i = movie->num_cl - 1; i > -1; i--)
476 movie->cl[i] = cio_read(4); /* CLi */
478 if (cio_tell() - box.init_pos != box.length) {
479 fprintf(stderr, "Error with FTYP Box\n");
492 void mj2_write_stco(mj2_tk_t * tk)
497 box.init_pos = cio_tell();
499 cio_write(MJ2_STCO, 4); /* STCO */
501 cio_write(0, 4); /* Version = 0, flags = 0 */
503 cio_write(tk->num_chunks, 4); /* Entry Count */
505 for (i = 0; i < tk->num_chunks; i++) {
506 cio_write(tk->chunk[i].offset, 4); /* Entry offset */
509 box.length = cio_tell() - box.init_pos;
510 cio_seek(box.init_pos);
511 cio_write(box.length, 4); /* L */
512 cio_seek(box.init_pos + box.length);
521 int mj2_read_stco(mj2_tk_t * tk)
526 mj2_read_boxhdr(&box); /* Box Size */
527 if (MJ2_STCO != box.type) {
528 fprintf(stderr, "Error: Expected STCO Marker\n");
532 if (0 != cio_read(1)) { /* Version = 0 */
533 fprintf(stderr, "Error: Only Version 0 handled in STCO box\n");
537 if (0 != cio_read(3)) { /* Flags = 0 */
538 fprintf(stderr, "Error with flag in STCO box. Expected flag 0\n");
543 if (cio_read(4) != tk->num_chunks) {
545 "Error in STCO box: expecting same amount of entry-count as chunks \n");
547 for (i = 0; i < tk->num_chunks; i++) {
548 tk->chunk[i].offset = cio_read(4); /* Entry offset */
552 mj2_stco_decompact(tk);
555 if (cio_tell() - box.init_pos != box.length) {
556 fprintf(stderr, "Error with STCO Box size\n");
568 void mj2_write_stsz(mj2_tk_t * tk)
573 box.init_pos = cio_tell();
575 cio_write(MJ2_STSZ, 4); /* STSZ */
577 cio_write(0, 4); /* Version = 0, flags = 0 */
579 if (tk->same_sample_size == 1) { /* If they all have the same size */
580 cio_write(tk->sample[0].sample_size, 4); /* Size */
582 cio_write(1, 4); /* Entry count = 1 */
586 cio_write(0, 4); /* Sample Size = 0 becase they all have different sizes */
588 cio_write(tk->num_samples, 4); /* Sample Count */
590 for (i = 0; i < tk->num_samples; i++) {
591 cio_write(tk->sample[i].sample_size, 4);
595 box.length = cio_tell() - box.init_pos;
596 cio_seek(box.init_pos);
597 cio_write(box.length, 4); /* L */
598 cio_seek(box.init_pos + box.length);
607 int mj2_read_stsz(mj2_tk_t * tk)
613 mj2_read_boxhdr(&box); /* Box Size */
614 if (MJ2_STSZ != box.type) {
615 fprintf(stderr, "Error: Expected STSZ Marker\n");
620 if (0 != cio_read(1)) { /* Version = 0 */
621 fprintf(stderr, "Error: Only Version 0 handled in STSZ box\n");
625 if (0 != cio_read(3)) { /* Flags = 0 */
626 fprintf(stderr, "Error with flag in STSZ box. Expected flag 0\n");
630 sample_size = cio_read(4);
632 if (sample_size != 0) { /* Samples do have the same size */
633 tk->same_sample_size = 1;
634 for (i = 0; i < tk->num_samples; i++) {
635 tk->sample[i].sample_size = sample_size;
637 cio_skip(4); /* Sample count = 1 */
639 tk->same_sample_size = 0;
640 if (tk->num_samples != cio_read(4)) { /* Sample count */
642 "Error in STSZ box. Expected that sample-count is number of samples in track\n");
645 for (i = 0; i < tk->num_samples; i++) {
646 tk->sample[i].sample_size = cio_read(4); /* Sample Size */
649 if (cio_tell() - box.init_pos != box.length) {
650 fprintf(stderr, "Error with STSZ Box size\n");
664 void mj2_write_stsc(mj2_tk_t * tk)
669 box.init_pos = cio_tell();
671 cio_write(MJ2_STSC, 4); /* STSC */
673 cio_write(0, 4); /* Version = 0, flags = 0 */
675 cio_write(tk->num_samplestochunk, 4); /* Entry Count */
677 for (i = 0; i < tk->num_samplestochunk; i++) {
678 cio_write(tk->sampletochunk[i].first_chunk, 4); /* First Chunk */
679 cio_write(tk->sampletochunk[i].samples_per_chunk, 4); /* Samples per chunk */
680 cio_write(tk->sampletochunk[i].sample_descr_idx, 4); /* Samples description index */
684 box.length = cio_tell() - box.init_pos;
685 cio_seek(box.init_pos);
686 cio_write(box.length, 4); /* L */
687 cio_seek(box.init_pos + box.length);
696 int mj2_read_stsc(mj2_tk_t * tk)
701 mj2_read_boxhdr(&box); /* Box Size */
702 if (MJ2_STSC != box.type) {
703 fprintf(stderr, "Error: Expected STSC Marker\n");
708 if (0 != cio_read(1)) { /* Version = 0 */
709 fprintf(stderr, "Error: Only Version 0 handled in STSC box\n");
713 if (0 != cio_read(3)) { /* Flags = 0 */
714 fprintf(stderr, "Error with flag in STSC box. Expected flag 0\n");
718 tk->num_samplestochunk = cio_read(4);
721 (mj2_sampletochunk_t *) malloc(tk->num_samplestochunk *
722 sizeof(mj2_sampletochunk_t));
725 for (i = 0; i < tk->num_samplestochunk; i++) {
726 tk->sampletochunk[i].first_chunk = cio_read(4);
727 tk->sampletochunk[i].samples_per_chunk = cio_read(4);
728 tk->sampletochunk[i].sample_descr_idx = cio_read(4);
731 mj2_stsc_decompact(tk); /* decompact sample to chunk box */
734 if (cio_tell() - box.init_pos != box.length) {
735 fprintf(stderr, "Error with STSC Box size\n");
747 void mj2_write_stts(mj2_tk_t * tk)
753 box.init_pos = cio_tell();
755 cio_write(MJ2_STTS, 4); /* STTS */
757 cio_write(0, 4); /* Version = 0, flags = 0 */
759 cio_write(tk->num_tts, 4); /* entry_count */
760 for (i = 0; i < tk->num_tts; i++) {
761 cio_write(tk->tts[i].sample_count, 4); /* Sample-count */
762 cio_write(tk->tts[i].sample_delta, 4); /* Sample-Delta */
765 box.length = cio_tell() - box.init_pos;
766 cio_seek(box.init_pos);
767 cio_write(box.length, 4); /* L */
768 cio_seek(box.init_pos + box.length);
777 int mj2_read_stts(mj2_tk_t * tk)
783 mj2_read_boxhdr(&box);
784 if (MJ2_STTS != box.type) {
785 fprintf(stderr, "Error: Expected STTS Marker\n");
790 if (0 != cio_read(1)) { /* Version = 0 */
791 fprintf(stderr, "Error: Only Version 0 handled in STTS box\n");
795 if (0 != cio_read(3)) { /* Flags = 0 */
796 fprintf(stderr, "Error with flag in STTS box. Expected flag 0\n");
800 tk->num_tts = cio_read(4);
802 tk->tts = (mj2_tts_t *) malloc(tk->num_tts * sizeof(mj2_tts_t));
804 for (i = 0; i < tk->num_tts; i++) {
805 tk->tts[i].sample_count = cio_read(4);
806 tk->tts[i].sample_delta = cio_read(4);
809 mj2_tts_decompact(tk);
811 if (cio_tell() - box.init_pos != box.length) {
812 fprintf(stderr, "Error with STTS Box size\n");
824 void mj2_write_fiel(mj2_tk_t * tk)
829 box.init_pos = cio_tell();
831 cio_write(MJ2_FIEL, 4); /* STTS */
833 cio_write(tk->fieldcount, 1); /* Field count */
834 cio_write(tk->fieldorder, 1); /* Field order */
837 box.length = cio_tell() - box.init_pos;
838 cio_seek(box.init_pos);
839 cio_write(box.length, 4); /* L */
840 cio_seek(box.init_pos + box.length);
849 int mj2_read_fiel(mj2_tk_t * tk)
854 mj2_read_boxhdr(&box);
855 if (MJ2_FIEL != box.type) {
856 fprintf(stderr, "Error: Expected FIEL Marker\n");
861 tk->fieldcount = cio_read(1);
862 tk->fieldorder = cio_read(1);
864 if (cio_tell() - box.init_pos != box.length) {
865 fprintf(stderr, "Error with FIEL Box size\n");
874 * Original Format Box
877 void mj2_write_orfo(mj2_tk_t * tk)
881 box.init_pos = cio_tell();
883 cio_write(MJ2_ORFO, 4);
885 cio_write(tk->or_fieldcount, 1); /* Original Field count */
886 cio_write(tk->or_fieldorder, 1); /* Original Field order */
889 box.length = cio_tell() - box.init_pos;
890 cio_seek(box.init_pos);
891 cio_write(box.length, 4); /* L */
892 cio_seek(box.init_pos + box.length);
898 * Original Format Box
901 int mj2_read_orfo(mj2_tk_t * tk)
906 mj2_read_boxhdr(&box);
907 if (MJ2_ORFO != box.type) {
908 fprintf(stderr, "Error: Expected ORFO Marker\n");
913 tk->or_fieldcount = cio_read(1);
914 tk->or_fieldorder = cio_read(1);
916 if (cio_tell() - box.init_pos != box.length) {
917 fprintf(stderr, "Error with ORFO Box size\n");
929 void mj2_write_jp2p(mj2_tk_t * tk)
935 box.init_pos = cio_tell();
937 cio_write(MJ2_JP2P, 4);
939 cio_write(0, 4); /* Version 0, flags =0 */
941 for (i = 0; i < tk->num_br; i++) {
942 cio_write(tk->br[i], 4);
945 box.length = cio_tell() - box.init_pos;
946 cio_seek(box.init_pos);
947 cio_write(box.length, 4); /* L */
948 cio_seek(box.init_pos + box.length);
957 int mj2_read_jp2p(mj2_tk_t * tk)
963 mj2_read_boxhdr(&box);
964 if (MJ2_JP2P != box.type) {
965 fprintf(stderr, "Error: Expected JP2P Marker\n");
969 if (0 != cio_read(1)) { /* Version = 0 */
970 fprintf(stderr, "Error: Only Version 0 handled in JP2P box\n");
974 if (0 != cio_read(3)) { /* Flags = 0 */
975 fprintf(stderr, "Error with flag in JP2P box. Expected flag 0\n");
980 tk->num_br = (box.length - 12) / 4;
981 tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
983 for (i = 0; i < tk->num_br; i++) {
984 tk->br[i] = cio_read(4);
987 if (cio_tell() - box.init_pos != box.length) {
988 fprintf(stderr, "Error with JP2P Box size\n");
1000 void mj2_write_jp2x(mj2_tk_t * tk)
1006 box.init_pos = cio_tell();
1008 cio_write(MJ2_JP2X, 4);
1010 for (i = 0; i < tk->num_jp2x; i++) {
1011 cio_write(tk->jp2xdata[i], 1);
1014 box.length = cio_tell() - box.init_pos;
1015 cio_seek(box.init_pos);
1016 cio_write(box.length, 4); /* L */
1017 cio_seek(box.init_pos + box.length);
1026 int mj2_read_jp2x(mj2_tk_t * tk)
1032 mj2_read_boxhdr(&box);
1033 if (MJ2_JP2X != box.type) {
1034 fprintf(stderr, "Error: Expected JP2X Marker\n");
1039 tk->num_jp2x = (box.length - 8);
1041 (unsigned char *) malloc(tk->num_jp2x * sizeof(unsigned char));
1043 for (i = 0; i < tk->num_jp2x; i++) {
1044 tk->jp2xdata[i] = cio_read(1);
1047 if (cio_tell() - box.init_pos != box.length) {
1048 fprintf(stderr, "Error with JP2X Box size\n");
1055 * Write the JSUB box
1057 * MJP2 Subsampling Box
1060 void mj2_write_jsub(mj2_tk_t * tk)
1065 box.init_pos = cio_tell();
1067 cio_write(MJ2_JSUB, 4);
1069 cio_write(tk->hsub, 1);
1070 cio_write(tk->vsub, 1);
1071 cio_write(tk->hoff, 1);
1072 cio_write(tk->voff, 1);
1074 box.length = cio_tell() - box.init_pos;
1075 cio_seek(box.init_pos);
1076 cio_write(box.length, 4); /* L */
1077 cio_seek(box.init_pos + box.length);
1083 * MJP2 Subsampling Box
1086 int mj2_read_jsub(mj2_tk_t * tk)
1090 mj2_read_boxhdr(&box);
1091 if (MJ2_JSUB != box.type) {
1092 fprintf(stderr, "Error: Expected JSUB Marker\n");
1096 tk->hsub = cio_read(1);
1097 tk->vsub = cio_read(1);
1098 tk->hoff = cio_read(1);;
1099 tk->voff = cio_read(1);
1101 if (cio_tell() - box.init_pos != box.length) {
1102 fprintf(stderr, "Error with JSUB Box size\n");
1109 * Write the SMJ2 box
1111 * Visual Sample Entry Description
1114 void mj2_write_smj2(mj2_tk_t * tk)
1118 box.init_pos = cio_tell();
1120 cio_write(MJ2_MJ2, 4); /* MJ2 */
1122 cio_write(0, 4); /* Version = 0, flags = 0 */
1126 cio_write(0, 2); /* Pre-defined */
1128 cio_write(0, 2); /* Reserved */
1130 cio_write(0, 4); /* Pre-defined */
1131 cio_write(0, 4); /* Pre-defined */
1132 cio_write(0, 4); /* Pre-defined */
1134 cio_write(tk->w, 2); /* Width */
1135 cio_write(tk->h, 2); /* Height */
1137 cio_write(tk->horizresolution, 4); /* Horizontal resolution */
1138 cio_write(tk->vertresolution, 4); /* Vertical resolution */
1140 cio_write(0, 4); /* Reserved */
1142 cio_write(1, 2); /* Pre-defined = 1 */
1144 cio_write(tk->compressorname[0], 4); /* Compressor Name */
1145 cio_write(tk->compressorname[1], 4);
1146 cio_write(tk->compressorname[2], 4);
1147 cio_write(tk->compressorname[3], 4);
1148 cio_write(tk->compressorname[4], 4);
1149 cio_write(tk->compressorname[5], 4);
1150 cio_write(tk->compressorname[6], 4);
1151 cio_write(tk->compressorname[7], 4);
1153 cio_write(tk->depth, 2); /* Depth */
1155 cio_write(0xffff, 2); /* Pre-defined = -1 */
1157 jp2_write_jp2h(&tk->jp2_struct);
1161 if (tk->num_br != 0)
1163 if (tk->num_jp2x != 0)
1169 box.length = cio_tell() - box.init_pos;
1170 cio_seek(box.init_pos);
1171 cio_write(box.length, 4); /* L */
1172 cio_seek(box.init_pos + box.length);
1178 * Visual Sample Entry Description
1181 int mj2_read_smj2(j2k_image_t * img, mj2_tk_t * tk)
1187 mj2_read_boxhdr(&box);
1189 if (MJ2_MJ2 != box.type) {
1190 fprintf(stderr, "Error in SMJ2 box: Expected MJ2 Marker\n");
1194 if (0 != cio_read(1)) { /* Version = 0 */
1195 fprintf(stderr, "Error: Only Version 0 handled in MJP2 box\n");
1199 if (0 != cio_read(3)) { /* Flags = 0 */
1200 fprintf(stderr, "Error with flag in MJP2 box. Expected flag 0\n");
1206 cio_skip(2); /* Pre-defined */
1208 cio_skip(2); /* Reserved */
1210 cio_skip(4); /* Pre-defined */
1211 cio_skip(4); /* Pre-defined */
1212 cio_skip(4); /* Pre-defined */
1214 tk->w = cio_read(2); /* Width */
1215 tk->h = cio_read(2); /* Height */
1217 tk->horizresolution = cio_read(4); /* Horizontal resolution */
1218 tk->vertresolution = cio_read(4); /* Vertical resolution */
1220 cio_skip(4); /* Reserved */
1222 cio_skip(2); /* Pre-defined = 1 */
1224 tk->compressorname[0] = cio_read(4); /* Compressor Name */
1225 tk->compressorname[1] = cio_read(4);
1226 tk->compressorname[2] = cio_read(4);
1227 tk->compressorname[3] = cio_read(4);
1228 tk->compressorname[4] = cio_read(4);
1229 tk->compressorname[5] = cio_read(4);
1230 tk->compressorname[6] = cio_read(4);
1231 tk->compressorname[7] = cio_read(4);
1233 tk->depth = cio_read(2); /* Depth */
1235 /* Init std value */
1239 tk->or_fieldcount = 1;
1240 tk->or_fieldorder = 0;
1242 cio_skip(2); /* Pre-defined = -1 */
1244 if (jp2_read_jp2h(&tk->jp2_struct)) {
1245 fprintf(stderr, "Error with JP2H Box\n");
1249 tk->jp2_struct.comps = (jp2_comps_t *) malloc(tk->jp2_struct.numcomps * sizeof(jp2_comps_t));
1250 tk->jp2_struct.cl = (int *) malloc(sizeof(int));
1255 for (i = 0; cio_tell() - box.init_pos < box.length; i++) {
1256 mj2_read_boxhdr(&box2);
1257 cio_seek(box2.init_pos);
1258 switch (box2.type) {
1260 if (mj2_read_fiel(tk))
1265 if (mj2_read_jp2p(tk))
1270 if (mj2_read_jp2x(tk))
1275 if (mj2_read_jsub(tk))
1280 if (mj2_read_orfo(tk))
1285 fprintf(stderr, "Error with MJP2 Box size\n");
1296 * Write the STSD box
1298 * Sample Description
1301 void mj2_write_stsd(mj2_tk_t * tk)
1305 box.init_pos = cio_tell();
1307 cio_write(MJ2_STSD, 4); /* STSD */
1309 cio_write(0, 4); /* Version = 0, flags = 0 */
1311 cio_write(1, 4); /* entry_count = 1 (considering same JP2 headerboxes) */
1313 if (tk->track_type == 0) {
1315 } else if (tk->track_type == 1) {
1318 if (tk->track_type == 2) {
1323 box.length = cio_tell() - box.init_pos;
1324 cio_seek(box.init_pos);
1325 cio_write(box.length, 4); /* L */
1326 cio_seek(box.init_pos + box.length);
1332 * Sample Description
1335 int mj2_read_stsd(mj2_tk_t * tk, j2k_image_t * img)
1338 int entry_count, len_2skip;
1342 mj2_read_boxhdr(&box);
1344 if (MJ2_STSD != box.type) {
1345 fprintf(stderr, "Error: Expected STSD Marker\n");
1349 if (0 != cio_read(1)) { /* Version = 0 */
1350 fprintf(stderr, "Error: Only Version 0 handled in STSD box\n");
1354 if (0 != cio_read(3)) { /* Flags = 0 */
1355 fprintf(stderr, "Error with flag in STSD box. Expected flag 0\n");
1359 entry_count = cio_read(4);
1361 if (tk->track_type == 0) {
1362 for (i = 0; i < entry_count; i++) {
1363 if (mj2_read_smj2(img, tk))
1366 } else if (tk->track_type == 1) {
1367 len_2skip = cio_read(4); // Not implemented -> skipping box
1368 cio_skip(len_2skip - 4);
1369 } else if (tk->track_type == 2) {
1370 len_2skip = cio_read(4); // Not implemented -> skipping box
1371 cio_skip(len_2skip - 4);
1375 if (cio_tell() - box.init_pos != box.length) {
1376 fprintf(stderr, "Error with STSD Box size\n");
1383 * Write the STBL box
1385 * Sample table box box
1388 void mj2_write_stbl(mj2_tk_t * tk)
1392 box.init_pos = cio_tell();
1394 cio_write(MJ2_STBL, 4); /* STBL */
1402 box.length = cio_tell() - box.init_pos;
1403 cio_seek(box.init_pos);
1404 cio_write(box.length, 4); /* L */
1405 cio_seek(box.init_pos + box.length);
1411 * Sample table box box
1414 int mj2_read_stbl(mj2_tk_t * tk, j2k_image_t * img)
1418 mj2_read_boxhdr(&box);
1419 if (MJ2_STBL != box.type) {
1420 fprintf(stderr, "Error: Expected STBL Marker\n");
1424 if (mj2_read_stsd(tk, img))
1426 if (mj2_read_stts(tk))
1428 if (mj2_read_stsc(tk))
1430 if (mj2_read_stsz(tk))
1432 if (mj2_read_stco(tk))
1435 if (cio_tell() - box.init_pos != box.length) {
1436 fprintf(stderr, "Error with STBL Box size\n");
1448 void mj2_write_url(mj2_tk_t * tk, int url_num)
1452 box.init_pos = cio_tell();
1454 cio_write(MJ2_URL, 4); /* URL */
1457 cio_write(1, 4); /* Version = 0, flags = 1 because stored in same file */
1459 cio_write(0, 4); /* Version = 0, flags = 0 */
1460 cio_write(tk->url[url_num - 1].location[0], 4);
1461 cio_write(tk->url[url_num - 1].location[1], 4);
1462 cio_write(tk->url[url_num - 1].location[2], 4);
1463 cio_write(tk->url[url_num - 1].location[3], 4);
1466 box.length = cio_tell() - box.init_pos;
1467 cio_seek(box.init_pos);
1468 cio_write(box.length, 4); /* L */
1469 cio_seek(box.init_pos + box.length);
1478 int mj2_read_url(mj2_tk_t * tk, int urn_num)
1482 mj2_read_boxhdr(&box);
1483 if (MJ2_URL != box.type) {
1484 fprintf(stderr, "Error: Expected URL Marker\n");
1488 if (0 != cio_read(1)) { /* Version = 0 */
1489 fprintf(stderr, "Error: Only Version 0 handled in URL box\n");
1493 if (1 != cio_read(3)) { /* If flags = 1 --> media data in file */
1494 tk->url[urn_num].location[0] = cio_read(4);
1495 tk->url[urn_num].location[1] = cio_read(4);
1496 tk->url[urn_num].location[2] = cio_read(4);
1497 tk->url[urn_num].location[3] = cio_read(4);
1503 if (cio_tell() - box.init_pos != box.length) {
1504 fprintf(stderr, "Error with URL Box size\n");
1516 void mj2_write_urn(mj2_tk_t * tk, int urn_num)
1520 box.init_pos = cio_tell();
1522 cio_write(MJ2_URN, 4); /* URN */
1524 cio_write(0, 4); /* Version = 0, flags = 0 */
1526 cio_write(tk->urn[urn_num].name[0], 4);
1527 cio_write(tk->urn[urn_num].name[1], 4);
1528 cio_write(tk->urn[urn_num].name[2], 4);
1529 cio_write(tk->urn[urn_num].name[3], 4);
1530 cio_write(tk->urn[urn_num].location[0], 4);
1531 cio_write(tk->urn[urn_num].location[1], 4);
1532 cio_write(tk->urn[urn_num].location[2], 4);
1533 cio_write(tk->urn[urn_num].location[3], 4);
1535 box.length = cio_tell() - box.init_pos;
1536 cio_seek(box.init_pos);
1537 cio_write(box.length, 4); /* L */
1538 cio_seek(box.init_pos + box.length);
1547 int mj2_read_urn(mj2_tk_t * tk, int urn_num)
1552 mj2_read_boxhdr(&box);
1553 if (MJ2_URN != box.type) {
1554 fprintf(stderr, "Error: Expected URN Marker\n");
1558 if (0 != cio_read(1)) { /* Version = 0 */
1559 fprintf(stderr, "Error: Only Version 0 handled in URN box\n");
1563 if (1 != cio_read(3)) { /* If flags = 1 --> media data in file */
1564 tk->urn[urn_num].name[0] = cio_read(4);
1565 tk->urn[urn_num].name[1] = cio_read(4);
1566 tk->urn[urn_num].name[2] = cio_read(4);
1567 tk->urn[urn_num].name[3] = cio_read(4);
1568 tk->urn[urn_num].location[0] = cio_read(4);
1569 tk->urn[urn_num].location[1] = cio_read(4);
1570 tk->urn[urn_num].location[2] = cio_read(4);
1571 tk->urn[urn_num].location[3] = cio_read(4);
1575 if (cio_tell() - box.init_pos != box.length) {
1576 fprintf(stderr, "Error with URN Box size\n");
1584 * Write the DREF box
1586 * Data reference box
1589 void mj2_write_dref(mj2_tk_t * tk)
1594 box.init_pos = cio_tell();
1596 cio_write(MJ2_DREF, 4); /* DREF */
1598 cio_write(0, 4); /* Version = 0, flags = 0 */
1600 if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
1601 cio_write(1, 4); /* entry_count = 1 */
1602 mj2_write_url(tk, 0);
1604 cio_write(tk->num_url + tk->num_urn, 4); /* entry_count */
1606 for (i = 0; i < tk->num_url; i++)
1607 mj2_write_url(tk, i + 1);
1609 for (i = 0; i < tk->num_urn; i++)
1610 mj2_write_urn(tk, i);
1613 box.length = cio_tell() - box.init_pos;
1614 cio_seek(box.init_pos);
1615 cio_write(box.length, 4); /* L */
1616 cio_seek(box.init_pos + box.length);
1622 * Data reference box
1625 int mj2_read_dref(mj2_tk_t * tk)
1629 int entry_count, marker;
1632 mj2_read_boxhdr(&box);
1633 if (MJ2_DREF != box.type) {
1634 fprintf(stderr, "Error: Expected DREF Marker\n");
1638 if (0 != cio_read(1)) { /* Version = 0 */
1639 fprintf(stderr, "Error: Only Version 0 handled in DREF box\n");
1643 if (0 != cio_read(3)) { /* Flags = 0 */
1644 fprintf(stderr, "Error with flag in DREF box. Expected flag 0\n");
1648 entry_count = cio_read(4);
1652 for (i = 0; i < entry_count; i++) {
1654 marker = cio_read(4);
1655 if (marker == MJ2_URL) {
1658 if (mj2_read_url(tk, tk->num_url))
1660 } else if (marker == MJ2_URN) {
1663 if (mj2_read_urn(tk, tk->num_urn))
1666 fprintf(stderr, "Error with in DREF box. Expected URN or URL box\n");
1673 if (cio_tell() - box.init_pos != box.length) {
1674 fprintf(stderr, "Error with DREF Box size\n");
1681 * Write the DINF box
1683 * Data information box
1686 void mj2_write_dinf(mj2_tk_t * tk)
1690 box.init_pos = cio_tell();
1692 cio_write(MJ2_DINF, 4); /* DINF */
1696 box.length = cio_tell() - box.init_pos;
1697 cio_seek(box.init_pos);
1698 cio_write(box.length, 4); /* L */
1699 cio_seek(box.init_pos + box.length);
1705 * Data information box
1708 int mj2_read_dinf(mj2_tk_t * tk)
1712 mj2_read_boxhdr(&box);
1713 if (MJ2_DINF != box.type) {
1714 fprintf(stderr, "Error: Expected DINF Marker\n");
1718 if (mj2_read_dref(tk))
1721 if (cio_tell() - box.init_pos != box.length) {
1722 fprintf(stderr, "Error with DINF Box size\n");
1729 * Write the VMHD box
1731 * Video Media information box
1734 void mj2_write_vmhd(mj2_tk_t * tk)
1738 box.init_pos = cio_tell();
1740 cio_write(MJ2_VMHD, 4); /* VMHD */
1742 cio_write(1, 4); /* Version = 0, flags = 1 */
1744 cio_write(tk->graphicsmode, 2);
1745 cio_write(tk->opcolor[0], 2);
1746 cio_write(tk->opcolor[1], 2);
1747 cio_write(tk->opcolor[2], 2);
1749 box.length = cio_tell() - box.init_pos;
1750 cio_seek(box.init_pos);
1751 cio_write(box.length, 4); /* L */
1752 cio_seek(box.init_pos + box.length);
1758 * Video Media information box
1761 int mj2_read_vmhd(mj2_tk_t * tk)
1765 mj2_read_boxhdr(&box);
1766 if (MJ2_VMHD != box.type) {
1767 fprintf(stderr, "Error: Expected VMHD Marker\n");
1771 if (0 != cio_read(1)) { /* Version = 0 */
1772 fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
1776 if (1 != cio_read(3)) { /* Flags = 1 */
1777 fprintf(stderr, "Error with flag in VMHD box. Expected flag 1\n");
1782 tk->graphicsmode = cio_read(2);
1783 tk->opcolor[0] = cio_read(2);
1784 tk->opcolor[1] = cio_read(2);
1785 tk->opcolor[2] = cio_read(2);
1787 if (cio_tell() - box.init_pos != box.length) {
1788 fprintf(stderr, "Error with VMHD Box size\n");
1795 * Write the SMHD box
1797 * Sound Media information box
1800 void mj2_write_smhd(mj2_tk_t * tk)
1804 box.init_pos = cio_tell();
1806 cio_write(MJ2_SMHD, 4); /* SMHD */
1808 cio_write(0, 4); /* Version = 0, flags = 0 */
1810 cio_write(tk->balance, 2);
1812 cio_write(0, 2); /* Reserved */
1814 box.length = cio_tell() - box.init_pos;
1815 cio_seek(box.init_pos);
1816 cio_write(box.length, 4); /* L */
1817 cio_seek(box.init_pos + box.length);
1823 * Sound Media information box
1826 int mj2_read_smhd(mj2_tk_t * tk)
1830 mj2_read_boxhdr(&box);
1831 if (MJ2_SMHD != box.type) {
1832 fprintf(stderr, "Error: Expected SMHD Marker\n");
1836 if (0 != cio_read(1)) { /* Version = 0 */
1837 fprintf(stderr, "Error: Only Version 0 handled in SMHD box\n");
1841 if (0 != cio_read(3)) { /* Flags = 0 */
1842 fprintf(stderr, "Error with flag in SMHD box. Expected flag 0\n");
1847 tk->balance = cio_read(2);
1849 /* Init variables to zero to avoid problems when freeeing memory
1850 The values will possibly be overidded when decoding the track structure */
1856 tk->num_samplestochunk = 0;
1857 tk->num_samples = 0;
1859 cio_skip(2); /* Reserved */
1861 if (cio_tell() - box.init_pos != box.length) {
1862 fprintf(stderr, "Error with SMHD Box size\n");
1869 * Write the HMHD box
1871 * Hint Media information box
1874 void mj2_write_hmhd(mj2_tk_t * tk)
1878 box.init_pos = cio_tell();
1880 cio_write(MJ2_HMHD, 4); /* HMHD */
1882 cio_write(0, 4); /* Version = 0, flags = 0 */
1884 cio_write(tk->maxPDUsize, 2);
1885 cio_write(tk->avgPDUsize, 2);
1886 cio_write(tk->maxbitrate, 4);
1887 cio_write(tk->avgbitrate, 4);
1888 cio_write(tk->slidingavgbitrate, 4);
1890 box.length = cio_tell() - box.init_pos;
1891 cio_seek(box.init_pos);
1892 cio_write(box.length, 4); /* L */
1893 cio_seek(box.init_pos + box.length);
1899 * Hint Media information box
1902 int mj2_read_hmhd(mj2_tk_t * tk)
1906 mj2_read_boxhdr(&box);
1907 if (MJ2_HMHD != box.type) {
1908 fprintf(stderr, "Error: Expected HMHD Marker\n");
1912 if (0 != cio_read(1)) { /* Version = 0 */
1913 fprintf(stderr, "Error: Only Version 0 handled in HMHD box\n");
1917 if (0 != cio_read(3)) { /* Flags = 0 */
1918 fprintf(stderr, "Error with flag in HMHD box. Expected flag 0\n");
1923 tk->maxPDUsize = cio_read(2);
1924 tk->avgPDUsize = cio_read(2);
1925 tk->maxbitrate = cio_read(4);
1926 tk->avgbitrate = cio_read(4);
1927 tk->slidingavgbitrate = cio_read(4);
1929 /* Init variables to zero to avoid problems when freeeing memory
1930 The values will possibly be overidded when decoding the track structure */
1936 tk->num_samplestochunk = 0;
1937 tk->num_samples = 0;
1940 if (cio_tell() - box.init_pos != box.length) {
1941 fprintf(stderr, "Error with HMHD Box size\n");
1948 * Write the MINF box
1950 * Media information box
1953 void mj2_write_minf(mj2_tk_t * tk)
1957 box.init_pos = cio_tell();
1959 cio_write(MJ2_MINF, 4); /* MINF */
1961 if (tk->track_type == 0) {
1963 } else if (tk->track_type == 1) {
1965 } else if (tk->track_type == 2) {
1972 box.length = cio_tell() - box.init_pos;
1973 cio_seek(box.init_pos);
1974 cio_write(box.length, 4); /* L */
1975 cio_seek(box.init_pos + box.length);
1981 * Media information box
1984 int mj2_read_minf(mj2_tk_t * tk, j2k_image_t * img)
1987 unsigned int box_type;
1990 mj2_read_boxhdr(&box);
1991 if (MJ2_MINF != box.type) {
1992 fprintf(stderr, "Error: Expected MINF Marker\n");
1997 box_type = cio_read(4);
2000 if (box_type == MJ2_VMHD) {
2001 if (mj2_read_vmhd(tk))
2003 } else if (box_type == MJ2_SMHD) {
2004 if (mj2_read_smhd(tk))
2006 } else if (box_type == MJ2_HMHD) {
2007 if (mj2_read_hmhd(tk))
2010 fprintf(stderr, "Error in MINF box expected vmhd, smhd or hmhd\n");
2014 if (mj2_read_dinf(tk))
2017 if (mj2_read_stbl(tk, img))
2020 if (cio_tell() - box.init_pos != box.length) {
2021 fprintf(stderr, "Error with MINF Box size\n");
2028 * Write the HDLR box
2030 * Handler reference box
2033 void mj2_write_hdlr(mj2_tk_t * tk)
2037 box.init_pos = cio_tell();
2039 cio_write(MJ2_HDLR, 4); /* HDLR */
2041 cio_write(0, 4); /* Version = 0, flags = 0 */
2043 cio_write(0, 4); /* Predefine */
2045 tk->name = 0; /* The track name is immediately determined by the track type */
2047 if (tk->track_type == 0) {
2048 tk->handler_type = 0x76696465; /* Handler type: vide */
2049 cio_write(tk->handler_type, 4);
2053 cio_write(0, 4); /* Reserved */
2055 cio_write(0x76696465, 4);
2056 cio_write(0x6F206d65, 4);
2057 cio_write(0x64696120, 4);
2058 cio_write(0x74726163, 4);
2059 cio_write(0x6b00, 2); /* String: video media track */
2060 } else if (tk->track_type == 1) {
2061 tk->handler_type = 0x736F756E; /* Handler type: soun */
2062 cio_write(tk->handler_type, 4);
2066 cio_write(0, 4); /* Reserved */
2068 cio_write(0x536F756E, 4);
2069 cio_write(0x6400, 2); /* String: Sound */
2070 } else if (tk->track_type == 2) {
2071 tk->handler_type = 0x68696E74; /* Handler type: hint */
2072 cio_write(tk->handler_type, 4);
2076 cio_write(0, 4); /* Reserved */
2078 cio_write(0x48696E74, 4);
2079 cio_write(0, 2); /* String: Hint */
2082 box.length = cio_tell() - box.init_pos;
2083 cio_seek(box.init_pos);
2084 cio_write(box.length, 4); /* L */
2085 cio_seek(box.init_pos + box.length);
2091 * Handler reference box
2094 int mj2_read_hdlr(mj2_tk_t * tk)
2099 mj2_read_boxhdr(&box);
2100 if (MJ2_HDLR != box.type) {
2101 fprintf(stderr, "Error: Expected HDLR Marker\n");
2106 if (0 != cio_read(1)) { /* Version = 0 */
2107 fprintf(stderr, "Error: Only Version 0 handled in HDLR box\n");
2111 if (0 != cio_read(3)) { /* Flags = 0 */
2112 fprintf(stderr, "Error with flag in HDLR box. Expected flag 0\n");
2116 cio_skip(4); /* Reserved */
2118 tk->handler_type = cio_read(4);
2119 cio_skip(12); /* Reserved */
2121 tk->name_size = box.length - 32;
2123 tk->name = (char *) malloc(tk->name_size * sizeof(char));
2124 for (i = 0; i < tk->name_size; i++) {
2125 tk->name[i] = cio_read(1); /* Name */
2128 if (cio_tell() - box.init_pos != box.length) {
2129 fprintf(stderr, "Error with HDLR Box size\n");
2136 * Write the MDHD box
2141 void mj2_write_mdhd(mj2_tk_t * tk)
2146 unsigned int modification_time;
2148 box.init_pos = cio_tell();
2150 cio_write(MJ2_MDHD, 4); /* MDHD */
2152 cio_write(0, 4); /* Version = 0, flags = 0 */
2154 cio_write(tk->creation_time, 4); /* Creation Time */
2156 time(<ime); /* Time since 1/1/70 */
2157 modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2159 cio_write(modification_time, 4); /* Modification Time */
2161 cio_write(tk->timescale, 4); /* Timescale */
2165 for (i = 0; i < tk->num_samples; i++)
2166 tk->duration += tk->sample[i].sample_delta;
2168 cio_write(tk->duration, 4); /* Duration */
2170 cio_write(tk->language, 2); /* Language */
2172 cio_write(0, 2); /* Predefined */
2174 box.length = cio_tell() - box.init_pos;
2175 cio_seek(box.init_pos);
2176 cio_write(box.length, 4); /* L */
2177 cio_seek(box.init_pos + box.length);
2186 int mj2_read_mdhd(mj2_tk_t * tk)
2190 mj2_read_boxhdr(&box);
2191 if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) { // Kakadu writes MHDR instead of MDHD
2192 fprintf(stderr, "Error: Expected MDHD Marker\n");
2196 if (0 != cio_read(1)) { /* Version = 0 */
2197 fprintf(stderr, "Error: Only Version 0 handled in MDHD box\n");
2201 if (0 != cio_read(3)) { /* Flags = 0 */
2202 fprintf(stderr, "Error with flag in MDHD box. Expected flag 0\n");
2207 tk->creation_time = cio_read(4); /* Creation Time */
2209 tk->modification_time = cio_read(4); /* Modification Time */
2211 tk->timescale = cio_read(4); /* Timescale */
2213 tk->duration = cio_read(4); /* Duration */
2215 tk->language = cio_read(2); /* Language */
2217 cio_skip(2); /* Predefined */
2219 if (cio_tell() - box.init_pos != box.length) {
2220 fprintf(stderr, "Error with MDHD Box size\n");
2227 * Write the MDIA box
2232 void mj2_write_mdia(mj2_tk_t * tk)
2236 box.init_pos = cio_tell();
2238 cio_write(MJ2_MDIA, 4); /* MDIA */
2244 box.length = cio_tell() - box.init_pos;
2245 cio_seek(box.init_pos);
2246 cio_write(box.length, 4); /* L */
2247 cio_seek(box.init_pos + box.length);
2256 int mj2_read_mdia(mj2_tk_t * tk, j2k_image_t * img)
2260 mj2_read_boxhdr(&box);
2261 if (MJ2_MDIA != box.type) {
2262 fprintf(stderr, "Error: Expected MDIA Marker\n");
2266 if (mj2_read_mdhd(tk))
2268 if (mj2_read_hdlr(tk))
2270 if (mj2_read_minf(tk, img))
2273 if (cio_tell() - box.init_pos != box.length) {
2274 fprintf(stderr, "Error with MDIA Box size\n");
2281 * Write the TKHD box
2286 void mj2_write_tkhd(mj2_tk_t * tk)
2292 box.init_pos = cio_tell();
2295 cio_write(MJ2_TKHD, 4); /* TKHD */
2297 cio_write(3, 4); /* Version=0, flags=3 */
2299 time(<ime); /* Time since 1/1/70 */
2300 tk->modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2302 cio_write(tk->creation_time, 4); /* Creation Time */
2304 cio_write(tk->modification_time, 4); /* Modification Time */
2306 cio_write(tk->track_ID, 4); /* Track ID */
2308 cio_write(0, 4); /* Reserved */
2312 for (i = 0; i < tk->num_samples; i++)
2313 tk->duration += tk->sample[i].sample_delta;
2315 cio_write(tk->duration, 4); /* Duration */
2317 cio_write(0, 4); /* Reserved */
2318 cio_write(0, 4); /* Reserved */
2320 cio_write(tk->layer, 2); /* Layer */
2322 cio_write(0, 2); /* Predefined */
2324 cio_write(tk->volume, 2); /* Volume */
2326 cio_write(0, 2); /* Reserved */
2328 cio_write(tk->trans_matrix[0], 4); /* Transformation matrix for track */
2329 cio_write(tk->trans_matrix[1], 4);
2330 cio_write(tk->trans_matrix[2], 4);
2331 cio_write(tk->trans_matrix[3], 4);
2332 cio_write(tk->trans_matrix[4], 4);
2333 cio_write(tk->trans_matrix[5], 4);
2334 cio_write(tk->trans_matrix[6], 4);
2335 cio_write(tk->trans_matrix[7], 4);
2336 cio_write(tk->trans_matrix[8], 4);
2338 cio_write(tk->visual_w, 4); /* Video Visual Width */
2340 cio_write(tk->visual_h, 4); /* Video Visual Height */
2342 box.length = cio_tell() - box.init_pos;
2343 cio_seek(box.init_pos);
2344 cio_write(box.length, 4); /* L */
2345 cio_seek(box.init_pos + box.length);
2354 int mj2_read_tkhd(mj2_tk_t * tk)
2360 mj2_read_boxhdr(&box);
2362 if (MJ2_TKHD != box.type) {
2363 fprintf(stderr, "Error: Expected TKHD Marker\n");
2367 if (0 != cio_read(1)) { /* Version = 0 */
2368 fprintf(stderr, "Error: Only Version 0 handled in TKHD box\n");
2374 if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) { /* Flags = 1,2,3 or 4 */
2376 "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2380 tk->creation_time = cio_read(4); /* Creation Time */
2382 tk->modification_time = cio_read(4); /* Modification Time */
2384 tk->track_ID = cio_read(4); /* Track ID */
2386 cio_skip(4); /* Reserved */
2388 tk->duration = cio_read(4); /* Duration */
2390 cio_skip(8); /* Reserved */
2392 tk->layer = cio_read(2); /* Layer */
2394 cio_read(2); /* Predefined */
2396 tk->volume = cio_read(2); /* Volume */
2398 cio_skip(2); /* Reserved */
2400 tk->trans_matrix[0] = cio_read(4); /* Transformation matrix for track */
2401 tk->trans_matrix[1] = cio_read(4);
2402 tk->trans_matrix[2] = cio_read(4);
2403 tk->trans_matrix[3] = cio_read(4);
2404 tk->trans_matrix[4] = cio_read(4);
2405 tk->trans_matrix[5] = cio_read(4);
2406 tk->trans_matrix[6] = cio_read(4);
2407 tk->trans_matrix[7] = cio_read(4);
2408 tk->trans_matrix[8] = cio_read(4);
2410 tk->visual_w = cio_read(4); /* Video Visual Width */
2412 tk->visual_h = cio_read(4); /* Video Visual Height */
2414 if (cio_tell() - box.init_pos != box.length) {
2415 fprintf(stderr, "Error with TKHD Box size\n");
2422 * Write the TRAK box
2427 void mj2_write_trak(mj2_tk_t * tk)
2431 box.init_pos = cio_tell();
2434 cio_write(MJ2_TRAK, 4); /* TRAK */
2439 box.length = cio_tell() - box.init_pos;
2440 cio_seek(box.init_pos);
2441 cio_write(box.length, 4); /* L */
2442 cio_seek(box.init_pos + box.length);
2451 int mj2_read_trak(mj2_tk_t * tk, j2k_image_t * img)
2455 mj2_read_boxhdr(&box);
2456 if (MJ2_TRAK != box.type) {
2457 fprintf(stderr, "Error: Expected TRAK Marker\n");
2460 if (mj2_read_tkhd(tk))
2462 if (mj2_read_mdia(tk, img))
2464 if (cio_tell() - box.init_pos != box.length) {
2465 fprintf(stderr, "Error with TRAK Box\n");
2472 * Write the MVHD box
2477 void mj2_write_mvhd(mj2_movie_t * movie)
2485 box.init_pos = cio_tell();
2487 cio_write(MJ2_MVHD, 4); /* MVHD */
2489 cio_write(0, 4); /* Version = 0, flags = 0 */
2491 time(<ime); /* Time since 1/1/70 */
2492 movie->modification_time = ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2494 cio_write(movie->creation_time, 4); /* Creation Time */
2496 cio_write(movie->modification_time, 4); /* Modification Time */
2498 cio_write(movie->timescale, 4); /* Timescale */
2500 movie->duration = 0;
2502 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2503 mj2_tk_t *tk = &movie->tk[i];
2505 for (j = 0; j < tk->num_samples; j++) {
2506 movie->duration += tk->sample[j].sample_delta;
2510 cio_write(movie->duration, 4);
2512 cio_write(movie->rate, 4); /* Rate to play presentation */
2514 cio_write(movie->volume, 2); /* Volume */
2516 cio_write(0, 2); /* Reserved */
2517 cio_write(0, 4); /* Reserved */
2518 cio_write(0, 4); /* Reserved */
2520 cio_write(movie->trans_matrix[0], 4); /* Transformation matrix for video */
2521 cio_write(movie->trans_matrix[1], 4);
2522 cio_write(movie->trans_matrix[2], 4);
2523 cio_write(movie->trans_matrix[3], 4);
2524 cio_write(movie->trans_matrix[4], 4);
2525 cio_write(movie->trans_matrix[5], 4);
2526 cio_write(movie->trans_matrix[6], 4);
2527 cio_write(movie->trans_matrix[7], 4);
2528 cio_write(movie->trans_matrix[8], 4);
2530 cio_write(0, 4); /* Pre-defined */
2531 cio_write(0, 4); /* Pre-defined */
2532 cio_write(0, 4); /* Pre-defined */
2533 cio_write(0, 4); /* Pre-defined */
2534 cio_write(0, 4); /* Pre-defined */
2535 cio_write(0, 4); /* Pre-defined */
2538 for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
2539 if (max_tk_num < movie->tk[i].track_ID)
2540 max_tk_num = movie->tk[i].track_ID;
2543 movie->next_tk_id = max_tk_num + 1;
2545 cio_write(movie->next_tk_id, 4); /* ID of Next track to be added */
2547 box.length = cio_tell() - box.init_pos;
2548 cio_seek(box.init_pos);
2549 cio_write(box.length, 4); /* L */
2550 cio_seek(box.init_pos + box.length);
2559 int mj2_read_mvhd(mj2_movie_t * movie)
2563 mj2_read_boxhdr(&box);
2564 if (MJ2_MVHD != box.type) {
2565 fprintf(stderr, "Error: Expected MVHD Marker\n");
2570 if (0 != cio_read(4)) { /* Version = 0, flags = 0 */
2571 fprintf(stderr, "Error: Only Version 0 handled in MVHD box\n");
2574 movie->creation_time = cio_read(4); /* Creation Time */
2576 movie->modification_time = cio_read(4); /* Modification Time */
2578 movie->timescale = cio_read(4); /* Timescale */
2580 movie->duration = cio_read(4); /* Duration */
2582 movie->rate = cio_read(4); /* Rate to play presentation */
2584 movie->volume = cio_read(2); /* Volume */
2586 cio_skip(10); /* Reserved */
2588 movie->trans_matrix[0] = cio_read(4); /* Transformation matrix for video */
2589 movie->trans_matrix[1] = cio_read(4);
2590 movie->trans_matrix[2] = cio_read(4);
2591 movie->trans_matrix[3] = cio_read(4);
2592 movie->trans_matrix[4] = cio_read(4);
2593 movie->trans_matrix[5] = cio_read(4);
2594 movie->trans_matrix[6] = cio_read(4);
2595 movie->trans_matrix[7] = cio_read(4);
2596 movie->trans_matrix[8] = cio_read(4);
2598 cio_skip(24); /* Pre-defined */
2600 movie->next_tk_id = cio_read(4); /* ID of Next track to be added */
2602 if (cio_tell() - box.init_pos != box.length) {
2603 fprintf(stderr, "Error with MVHD Box Size\n");
2611 * Write the MOOV box
2616 void mj2_write_moov(mj2_movie_t * movie)
2621 box.init_pos = cio_tell();
2623 cio_write(MJ2_MOOV, 4); /* MOOV */
2625 mj2_write_mvhd(movie);
2627 for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2628 mj2_write_trak(&movie->tk[i]);
2631 box.length = cio_tell() - box.init_pos;
2632 cio_seek(box.init_pos);
2633 cio_write(box.length, 4); /* L */
2634 cio_seek(box.init_pos + box.length);
2644 int mj2_read_moov(mj2_movie_t * movie, j2k_image_t * img)
2650 mj2_read_boxhdr(&box);
2651 if (MJ2_MOOV != box.type) {
2652 fprintf(stderr, "Error: Expected MOOV Marker\n");
2658 if (mj2_read_mvhd(movie))
2663 (mj2_tk_t *) malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2665 for (i = 0; cio_tell() - box.init_pos < box.length; i++) {
2666 mj2_read_boxhdr(&box2);
2667 if (box2.type == MJ2_TRAK) {
2668 cio_seek(box2.init_pos);
2669 if (mj2_read_trak(&movie->tk[i], img))
2672 if (movie->tk[i].track_type == 0) {
2674 } else if (movie->tk[i].track_type == 1) {
2676 } else if (movie->tk[i].track_type == 2) {
2679 } else if (box2.type == MJ2_MVEX) {
2680 cio_seek(box2.init_pos);
2681 cio_skip(box2.length);
2684 fprintf(stderr, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2691 int mj2_read_struct(FILE *file, mj2_movie_t * movie) {
2702 src = (char*) malloc (300 * sizeof(char));
2703 fread(src,300,1, file); // Assuming that jp and ftyp markers size do
2704 // not exceed 300 bytes
2710 if (mj2_read_ftyp(movie))
2713 fsresult = fseek(file,cio_tell(),SEEK_SET);
2715 fprintf(stderr, "End of file reached while trying to read data after FTYP box\n" );
2719 foffset = cio_tell();
2723 fread(src,30,1,file);
2725 mj2_read_boxhdr(&box);
2727 while(box.type != MJ2_MOOV) {
2732 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2734 fprintf(stderr, "End of file reached while trying to read MDAT box\n" );
2737 foffset += box.length;
2741 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2743 fprintf(stderr, "End of file reached while trying to read MOOF box\n" );
2746 foffset += box.length;
2749 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2751 fprintf(stderr, "End of file reached while trying to read FREE box\n" );
2754 foffset += box.length;
2757 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2759 fprintf(stderr, "End of file reached while trying to read SKIP box\n" );
2762 foffset += box.length;
2765 fprintf(stderr, "Unknown box in MJ2 stream\n");
2766 fsresult = fseek(file,foffset+box.length,SEEK_SET);
2768 fprintf(stderr, "End of file reached while trying to read end of unknown box\n");
2771 foffset += box.length;
2774 fsresult = fread(src,8,1,file);
2775 if (fsresult != 1) {
2776 fprintf(stderr, "MOOV box not found in file\n");
2780 mj2_read_boxhdr(&box);
2783 fseek(file,foffset,SEEK_SET);
2784 src = realloc(src,box.length);
2785 fsresult = fread(src,box.length,1,file);
2786 if (fsresult != 1) {
2787 fprintf(stderr, "End of file reached while trying to read MOOV box\n");
2791 cio_init(src, box.length);
2793 if (mj2_read_moov(movie, &img))