2014cf257012c5b8251db01336599fdd21232bda
[openjpeg.git] / mj2 / mj2.c
1 /*
2 * Copyright (c) 2003-2004, Fran�ois-Olivier Devaux
3 * Copyright (c) 2003-2004,  Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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.
26 */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 #include <math.h>
33
34 #include "mj2.h"
35 #include <cio.h>
36
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
76
77 /*
78
79 * Free movie structure memory
80 *
81 */
82 void mj2_memory_free(mj2_movie_t * movie)
83 {
84   int i;
85   mj2_tk_t *tk=NULL;
86
87   if (movie->num_cl != 0)
88     free(movie->cl);
89
90   for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
91     tk = &movie->tk[i];
92     if (tk->name_size != 0)
93       free(tk->name);
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);
98     if (tk->num_url != 0)
99       free(tk->url);
100     if (tk->num_urn != 0)
101       free(tk->urn);
102     if (tk->num_br != 0)
103       free(tk->br);
104     if (tk->num_jp2x != 0)
105       free(tk->jp2xdata);
106     if (tk->num_tts != 0)
107       free(tk->tts);
108     if (tk->num_chunks != 0)
109       free(tk->chunk);
110     if (tk->num_samplestochunk != 0)
111       free(tk->sampletochunk);
112     if (tk->num_samples != 0)
113       free(tk->sample);
114   }
115
116   free(movie->tk);
117 }
118
119 /*
120
121 * Read box headers
122 *
123 */
124
125 int mj2_read_boxhdr(mj2_box_t * box)
126 {
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");
133       return 1;
134     };
135     box->length = cio_read(4);
136     if (box->length == 0) 
137       box->length = cio_numbytesleft() + 12;
138   }
139   else if (box->length == 0) {
140     box->length = cio_numbytesleft() + 8;
141   }
142   return 0;
143 }
144
145 /*
146
147 * Initialisation of a Standard Video Track
148 * with one sample per chunk
149 */
150
151 int mj2_init_stdmovie(mj2_movie_t * movie)
152 {
153   int i;
154   unsigned int j;
155   time_t ltime;
156   movie->brand = MJ2_MJ2;
157   movie->minversion = 0;
158   if (!((movie->num_cl<100) && (movie->num_cl>-1))) {
159     movie->num_cl = 2;
160     movie->cl =
161       (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
162   }
163
164   movie->cl[0] = MJ2_MJ2;
165   movie->cl[1] = MJ2_MJ2S;
166   time(&ltime);                 /* 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;
169
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;
182
183   for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
184     mj2_tk_t *tk = &movie->tk[i];
185     movie->next_tk_id++;
186     if (tk->track_type == 0) {
187       if (tk->num_samples == 0)
188         return 1;
189
190       tk->Dim[0] = 0;
191       tk->Dim[1] = 0;
192
193       tk->timescale = 1000;     /* Timescale = 1 ms                                          */
194
195       tk->chunk[0].num_samples = 1;
196       tk->chunk[0].sample_descr_idx = 1;
197
198       tk->same_sample_size = 0;
199
200       tk->num_samplestochunk = 1;       /* One sample per chunk                                      */
201       tk->sampletochunk =
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;
207
208       for (j = 0; j < tk->num_samples; j++)
209         tk->sample[j].sample_delta = tk->timescale / tk->sample_rate;
210
211       tk->num_tts = 1;
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;
215
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)                                       */
234       tk->layer = 0;
235       tk->volume = 1;
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;
245       tk->fieldcount = 1;
246       tk->fieldorder = 0;
247       tk->or_fieldcount = 1;
248       tk->or_fieldorder = 0;
249       tk->num_br = 2;
250       tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
251       tk->br[0] = MJ2_JP2;
252       tk->br[1] = MJ2_J2P0;
253       tk->num_jp2x = 0;
254       tk->hsub = 2;             /* 4:2:0                                                      */
255       tk->vsub = 2;             /* 4:2:0                                                      */
256       tk->hoff = 0;
257       tk->voff = 0;
258     }
259   }
260   return 0;
261 }
262
263 /*
264 * Time To Sample box Decompact
265 *
266 */
267 void mj2_tts_decompact(mj2_tk_t * tk)
268 {
269   int i, j;
270   tk->num_samples = 0;
271   for (i = 0; i < tk->num_tts; i++) {
272     tk->num_samples += tk->tts[i].sample_count;
273   }
274
275   tk->sample =
276     (mj2_sample_t *) malloc(tk->num_samples * sizeof(mj2_sample_t));
277
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;
281     }
282   }
283 }
284
285 /*
286 * Sample To Chunk box Decompact
287 *
288 */
289 void mj2_stsc_decompact(mj2_tk_t * tk)
290 {
291   int j, i;
292   unsigned int k;
293   int sampleno=0;
294   
295   if (tk->num_samplestochunk == 1) {
296     tk->num_chunks =
297       (unsigned int) ceil((double) tk->num_samples /
298       (double) tk->sampletochunk[0].samples_per_chunk);
299     tk->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;
303     }
304     
305   } else {
306     tk->chunk =
307       (mj2_chunk_t *) malloc(tk->num_samples * sizeof(mj2_chunk_t));
308     tk->num_chunks = 0;
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;
313         tk->num_chunks++;
314         sampleno += tk->chunk[j].num_samples;
315       }
316     }
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;
322     }
323     tk->chunk = realloc(tk->chunk, tk->num_chunks * sizeof(mj2_chunk_t));
324   }
325   
326 }
327
328
329 /*
330 * Chunk offset box Decompact
331 *
332 */
333 void mj2_stco_decompact(mj2_tk_t * tk)
334 {
335   int j;
336   unsigned int i;
337   int k = 0;
338   int intra_chunk_offset;
339
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;
345       k++;
346     }
347   }
348 }
349
350 /*
351 * Write the JP box
352 *
353 * JP Signature box
354 *
355 */
356 void mj2_write_jp()
357 {
358   mj2_box_t box;
359   box.init_pos = cio_tell();
360   cio_skip(4);
361
362   cio_write(MJ2_JP, 4);         /* JP */
363   cio_write(0x0d0a870a, 4);     /* 0x0d0a870a required in a JP box */
364
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);
369 }
370
371 /*
372 * Read the JP box
373 *
374 * JPEG 2000 signature
375 *
376 */
377 int mj2_read_jp()
378 {
379   mj2_box_t box;
380
381   mj2_read_boxhdr(&box);
382   if (MJ2_JP != box.type) {     /* Check Marker */
383     fprintf(stderr, "Error: Expected JP Marker\n");
384     return 1;
385   }
386   if (0x0d0a870a != cio_read(4)) {      /* read the 0x0d0a870a required in a JP box */
387     fprintf(stderr, "Error with JP Marker\n");
388     return 1;
389   }
390   if (cio_tell() - box.init_pos != box.length) {        /* Check box length */
391     fprintf(stderr, "Error with JP Box size \n");
392     return 1;
393   }
394   return 0;
395
396 }
397
398 /*
399 * Write the FTYP box
400 *
401 * File type box
402 *
403 */
404 void mj2_write_ftyp(mj2_movie_t * movie)
405 {
406   int i;
407   mj2_box_t box;
408   box.init_pos = cio_tell();
409   cio_skip(4);
410
411   cio_write(MJ2_FTYP, 4);       /* FTYP       */
412   cio_write(movie->brand, 4);   /* BR         */
413   cio_write(movie->minversion, 4);      /* MinV       */
414
415   for (i = 0; i < movie->num_cl; i++)
416     cio_write(movie->cl[i], 4); /* CL         */
417
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);
422 }
423
424 /*
425 * Read the FTYP box
426 *
427 * File type box
428 *
429 */
430 int mj2_read_ftyp(mj2_movie_t * movie)
431 {
432   int i;
433   mj2_box_t box;
434
435   mj2_read_boxhdr(&box);        /* Box Size */
436   if (MJ2_FTYP != box.type) {
437     fprintf(stderr, "Error: Expected FTYP Marker\n");
438     return 1;
439   }
440
441   movie->brand = cio_read(4);   /* BR              */
442   movie->minversion = cio_read(4);      /* MinV            */
443   movie->num_cl = (box.length - 16) / 4;
444   movie->cl =
445     (unsigned int *) malloc(movie->num_cl * sizeof(unsigned int));
446
447   for (i = movie->num_cl - 1; i > -1; i--)
448     movie->cl[i] = cio_read(4); /* CLi */
449
450   if (cio_tell() - box.init_pos != box.length) {
451     fprintf(stderr, "Error with FTYP Box\n");
452     return 1;
453   }
454   return 0;
455 }
456
457
458 /*
459 * Write the STCO box
460 *
461 * Chunk Offset Box
462 *
463 */
464 void mj2_write_stco(mj2_tk_t * tk)
465 {
466   mj2_box_t box;
467   unsigned int i;
468
469   box.init_pos = cio_tell();
470   cio_skip(4);
471   cio_write(MJ2_STCO, 4);       /* STCO       */
472
473   cio_write(0, 4);              /* Version = 0, flags = 0 */
474
475   cio_write(tk->num_chunks, 4); /* Entry Count */
476
477   for (i = 0; i < tk->num_chunks; i++) {
478     cio_write(tk->chunk[i].offset, 4);  /* Entry offset */
479   }
480
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);
485 }
486
487 /*
488 * Read the STCO box
489 *
490 * Chunk Offset Box
491 *
492 */
493 int mj2_read_stco(mj2_tk_t * tk)
494 {
495   unsigned int i;
496   mj2_box_t box;
497
498   mj2_read_boxhdr(&box);        /* Box Size */
499   if (MJ2_STCO != box.type) {
500     fprintf(stderr, "Error: Expected STCO Marker\n");
501     return 1;
502   }
503
504   if (0 != cio_read(1)) {       /* Version = 0 */
505     fprintf(stderr, "Error: Only Version 0 handled in STCO box\n");
506     return 1;
507   }
508
509   if (0 != cio_read(3)) {       /* Flags = 0  */
510     fprintf(stderr, "Error with flag in STCO box. Expected flag 0\n");
511     return 1;
512   }
513
514
515   if (cio_read(4) != tk->num_chunks) {
516     fprintf(stderr,
517             "Error in STCO box: expecting same amount of entry-count as chunks \n");
518   } else {
519     for (i = 0; i < tk->num_chunks; i++) {
520       tk->chunk[i].offset = cio_read(4);        /* Entry offset */
521     }
522   }
523
524   mj2_stco_decompact(tk);
525
526
527   if (cio_tell() - box.init_pos != box.length) {
528     fprintf(stderr, "Error with STCO Box size\n");
529     return 1;
530   }
531   return 0;
532 }
533
534 /*
535 * Write the STSZ box
536 *
537 * Sample size box
538 *
539 */
540 void mj2_write_stsz(mj2_tk_t * tk)
541 {
542   mj2_box_t box;
543   unsigned int i;
544
545   box.init_pos = cio_tell();
546   cio_skip(4);
547   cio_write(MJ2_STSZ, 4);       /* STSZ       */
548
549   cio_write(0, 4);              /* Version = 0, flags = 0 */
550
551   if (tk->same_sample_size == 1) {      /* If they all have the same size */
552     cio_write(tk->sample[0].sample_size, 4);    /* Size */
553
554     cio_write(1, 4);            /* Entry count = 1 */
555   }
556
557   else {
558     cio_write(0, 4);            /* Sample Size = 0 becase they all have different sizes */
559
560     cio_write(tk->num_samples, 4);      /* Sample Count */
561
562     for (i = 0; i < tk->num_samples; i++) {
563       cio_write(tk->sample[i].sample_size, 4);
564     }
565   }
566
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);
571 }
572
573 /*
574 * Read the STSZ box
575 *
576 * Sample size box
577 *
578 */
579 int mj2_read_stsz(mj2_tk_t * tk)
580 {
581   int sample_size;
582   unsigned int i;
583   mj2_box_t box;
584
585   mj2_read_boxhdr(&box);        /* Box Size */
586   if (MJ2_STSZ != box.type) {
587     fprintf(stderr, "Error: Expected STSZ Marker\n");
588     return 1;
589   }
590
591
592   if (0 != cio_read(1)) {       /* Version = 0 */
593     fprintf(stderr, "Error: Only Version 0 handled in STSZ box\n");
594     return 1;
595   }
596
597   if (0 != cio_read(3)) {       /* Flags = 0  */
598     fprintf(stderr, "Error with flag in STSZ box. Expected flag 0\n");
599     return 1;
600   }
601
602   sample_size = cio_read(4);
603
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;
608     }
609     cio_skip(4);                /* Sample count = 1 */
610   } else {
611     tk->same_sample_size = 0;
612     if (tk->num_samples != cio_read(4)) {       /* Sample count */
613       fprintf(stderr,
614               "Error in STSZ box. Expected that sample-count is number of samples in track\n");
615       return 1;
616     }
617     for (i = 0; i < tk->num_samples; i++) {
618       tk->sample[i].sample_size = cio_read(4);  /* Sample Size */
619     }
620
621     if (cio_tell() - box.init_pos != box.length) {
622       fprintf(stderr, "Error with STSZ Box size\n");
623       return 1;
624     }
625   }
626   return 0;
627
628 }
629
630 /*
631 * Write the STSC box
632 *
633 * Sample to Chunk
634 *
635 */
636 void mj2_write_stsc(mj2_tk_t * tk)
637 {
638   int i;
639   mj2_box_t box;
640
641   box.init_pos = cio_tell();
642   cio_skip(4);
643   cio_write(MJ2_STSC, 4);       /* STSC       */
644
645   cio_write(0, 4);              /* Version = 0, flags = 0 */
646
647   cio_write(tk->num_samplestochunk, 4); /* Entry Count */
648
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 */
653   }
654
655
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);
660 }
661
662 /*
663 * Read the STSC box
664 *
665 * Sample to Chunk
666 *
667 */
668 int mj2_read_stsc(mj2_tk_t * tk)
669 {
670   int i;
671   mj2_box_t box;
672
673   mj2_read_boxhdr(&box);        /* Box Size */
674   if (MJ2_STSC != box.type) {
675     fprintf(stderr, "Error: Expected STSC Marker\n");
676     return 1;
677   }
678
679
680   if (0 != cio_read(1)) {       /* Version = 0 */
681     fprintf(stderr, "Error: Only Version 0 handled in STSC box\n");
682     return 1;
683   }
684
685   if (0 != cio_read(3)) {       /* Flags = 0  */
686     fprintf(stderr, "Error with flag in STSC box. Expected flag 0\n");
687     return 1;
688   }
689
690   tk->num_samplestochunk = cio_read(4);
691
692   tk->sampletochunk =
693     (mj2_sampletochunk_t *) malloc(tk->num_samplestochunk *
694                                    sizeof(mj2_sampletochunk_t));
695
696
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);
701   }
702
703   mj2_stsc_decompact(tk);       /* decompact sample to chunk box */
704
705
706   if (cio_tell() - box.init_pos != box.length) {
707     fprintf(stderr, "Error with STSC Box size\n");
708     return 1;
709   }
710   return 0;
711 }
712
713 /*
714 * Write the STTS box
715 *
716 * Time to Sample Box
717 *
718 */
719 void mj2_write_stts(mj2_tk_t * tk)
720 {
721
722   int i;
723   mj2_box_t box;
724
725   box.init_pos = cio_tell();
726   cio_skip(4);
727   cio_write(MJ2_STTS, 4);       /* STTS       */
728
729   cio_write(0, 4);              /* Version = 0, flags = 0 */
730
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 */
735   }
736
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);
741 }
742
743 /*
744 * Read the STTS box
745 *
746
747 *
748 */
749 int mj2_read_stts(mj2_tk_t * tk)
750 {
751   int i;
752
753   mj2_box_t box;
754
755   mj2_read_boxhdr(&box);
756   if (MJ2_STTS != box.type) {
757     fprintf(stderr, "Error: Expected STTS Marker\n");
758     return 1;
759   }
760
761
762   if (0 != cio_read(1)) {       /* Version = 0 */
763     fprintf(stderr, "Error: Only Version 0 handled in STTS box\n");
764     return 1;
765   }
766
767   if (0 != cio_read(3)) {       /* Flags = 0  */
768     fprintf(stderr, "Error with flag in STTS box. Expected flag 0\n");
769     return 1;
770   }
771
772   tk->num_tts = cio_read(4);
773
774   tk->tts = (mj2_tts_t *) malloc(tk->num_tts * sizeof(mj2_tts_t));
775
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);
779   }
780
781   mj2_tts_decompact(tk);
782
783   if (cio_tell() - box.init_pos != box.length) {
784     fprintf(stderr, "Error with STTS Box size\n");
785     return 1;
786   }
787   return 0;
788 }
789
790 /*
791 * Write the FIEL box
792 *
793 * Field coding Box
794 *
795 */
796 void mj2_write_fiel(mj2_tk_t * tk)
797 {
798
799   mj2_box_t box;
800
801   box.init_pos = cio_tell();
802   cio_skip(4);
803   cio_write(MJ2_FIEL, 4);       /* STTS       */
804
805   cio_write(tk->fieldcount, 1); /* Field count */
806   cio_write(tk->fieldorder, 1); /* Field order */
807
808
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);
813 }
814
815 /*
816 * Read the FIEL box
817 *
818 * Field coding Box
819 *
820 */
821 int mj2_read_fiel(mj2_tk_t * tk)
822 {
823
824   mj2_box_t box;
825
826   mj2_read_boxhdr(&box);
827   if (MJ2_FIEL != box.type) {
828     fprintf(stderr, "Error: Expected FIEL Marker\n");
829     return 1;
830   }
831
832
833   tk->fieldcount = cio_read(1);
834   tk->fieldorder = cio_read(1);
835
836   if (cio_tell() - box.init_pos != box.length) {
837     fprintf(stderr, "Error with FIEL Box size\n");
838     return 1;
839   }
840   return 0;
841 }
842
843 /*
844 * Write the ORFO box
845 *
846 * Original Format Box
847 *
848 */
849 void mj2_write_orfo(mj2_tk_t * tk)
850 {
851   mj2_box_t box;
852
853   box.init_pos = cio_tell();
854   cio_skip(4);
855   cio_write(MJ2_ORFO, 4);
856
857   cio_write(tk->or_fieldcount, 1);      /* Original Field count */
858   cio_write(tk->or_fieldorder, 1);      /* Original Field order */
859
860
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);
865 }
866
867 /*
868 * Read the ORFO box
869 *
870 * Original Format Box
871 *
872 */
873 int mj2_read_orfo(mj2_tk_t * tk)
874 {
875
876   mj2_box_t box;
877
878   mj2_read_boxhdr(&box);
879   if (MJ2_ORFO != box.type) {
880     fprintf(stderr, "Error: Expected ORFO Marker\n");
881     return 1;
882   }
883
884
885   tk->or_fieldcount = cio_read(1);
886   tk->or_fieldorder = cio_read(1);
887
888   if (cio_tell() - box.init_pos != box.length) {
889     fprintf(stderr, "Error with ORFO Box size\n");
890     return 1;
891   }
892   return 0;
893 }
894
895 /*
896 * Write the JP2P box
897 *
898 * MJP2 Profile Box
899 *
900 */
901 void mj2_write_jp2p(mj2_tk_t * tk)
902 {
903
904   int i;
905   mj2_box_t box;
906
907   box.init_pos = cio_tell();
908   cio_skip(4);
909   cio_write(MJ2_JP2P, 4);
910
911   cio_write(0, 4);              /* Version 0, flags =0 */
912
913   for (i = 0; i < tk->num_br; i++) {
914     cio_write(tk->br[i], 4);
915   }
916
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);
921 }
922
923 /*
924 * Read the JP2P box
925 *
926 * MJP2 Profile Box
927 *
928 */
929 int mj2_read_jp2p(mj2_tk_t * tk)
930 {
931   int i;
932
933   mj2_box_t box;
934
935   mj2_read_boxhdr(&box);
936   if (MJ2_JP2P != box.type) {
937     fprintf(stderr, "Error: Expected JP2P Marker\n");
938     return 1;
939   }
940
941   if (0 != cio_read(1)) {       /* Version = 0 */
942     fprintf(stderr, "Error: Only Version 0 handled in JP2P box\n");
943     return 1;
944   }
945
946   if (0 != cio_read(3)) {       /* Flags = 0  */
947     fprintf(stderr, "Error with flag in JP2P box. Expected flag 0\n");
948     return 1;
949   }
950
951
952   tk->num_br = (box.length - 12) / 4;
953   tk->br = (unsigned int *) malloc(tk->num_br * sizeof(unsigned int));
954
955   for (i = 0; i < tk->num_br; i++) {
956     tk->br[i] = cio_read(4);
957   }
958
959   if (cio_tell() - box.init_pos != box.length) {
960     fprintf(stderr, "Error with JP2P Box size\n");
961     return 1;
962   }
963   return 0;
964 }
965
966 /*
967 * Write the JP2X box
968 *
969 * MJP2 Prefix Box
970 *
971 */
972 void mj2_write_jp2x(mj2_tk_t * tk)
973 {
974
975   int i;
976   mj2_box_t box;
977
978   box.init_pos = cio_tell();
979   cio_skip(4);
980   cio_write(MJ2_JP2X, 4);
981
982   for (i = 0; i < tk->num_jp2x; i++) {
983     cio_write(tk->jp2xdata[i], 1);
984   }
985
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);
990 }
991
992 /*
993 * Read the JP2X box
994 *
995 * MJP2 Prefix Box
996 *
997 */
998 int mj2_read_jp2x(mj2_tk_t * tk)
999 {
1000   unsigned int i;
1001
1002   mj2_box_t box;
1003
1004   mj2_read_boxhdr(&box);
1005   if (MJ2_JP2X != box.type) {
1006     fprintf(stderr, "Error: Expected JP2X Marker\n");
1007     return 1;
1008   }
1009
1010
1011   tk->num_jp2x = (box.length - 8);
1012   tk->jp2xdata =
1013     (unsigned char *) malloc(tk->num_jp2x * sizeof(unsigned char));
1014
1015   for (i = 0; i < tk->num_jp2x; i++) {
1016     tk->jp2xdata[i] = cio_read(1);
1017   }
1018
1019   if (cio_tell() - box.init_pos != box.length) {
1020     fprintf(stderr, "Error with JP2X Box size\n");
1021     return 1;
1022   }
1023   return 0;
1024 }
1025
1026 /*
1027 * Write the JSUB box
1028 *
1029 * MJP2 Subsampling Box
1030 *
1031 */
1032 void mj2_write_jsub(mj2_tk_t * tk)
1033 {
1034
1035   mj2_box_t box;
1036
1037   box.init_pos = cio_tell();
1038   cio_skip(4);
1039   cio_write(MJ2_JSUB, 4);
1040
1041   cio_write(tk->hsub, 1);
1042   cio_write(tk->vsub, 1);
1043   cio_write(tk->hoff, 1);
1044   cio_write(tk->voff, 1);
1045
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);
1050 }
1051
1052 /*
1053 * Read the JSUB box
1054 *
1055 * MJP2 Subsampling Box
1056 *
1057 */
1058 int mj2_read_jsub(mj2_tk_t * tk)
1059 {
1060   mj2_box_t box;
1061
1062   mj2_read_boxhdr(&box);
1063   if (MJ2_JSUB != box.type) {
1064     fprintf(stderr, "Error: Expected JSUB Marker\n");
1065     return 1;
1066   }
1067
1068   tk->hsub = cio_read(1);
1069   tk->vsub = cio_read(1);
1070   tk->hoff = cio_read(1);;
1071   tk->voff = cio_read(1);
1072
1073   if (cio_tell() - box.init_pos != box.length) {
1074     fprintf(stderr, "Error with JSUB Box size\n");
1075     return 1;
1076   }
1077   return 0;
1078 }
1079
1080 /*
1081 * Write the SMJ2 box
1082 *
1083 * Visual Sample Entry Description
1084 *
1085 */
1086 void mj2_write_smj2(mj2_tk_t * tk)
1087 {
1088   mj2_box_t box;
1089
1090   box.init_pos = cio_tell();
1091   cio_skip(4);
1092   cio_write(MJ2_MJ2, 4);        /* MJ2       */
1093
1094   cio_write(0, 4);              /* Version = 0, flags = 0 */
1095
1096   cio_write(1, 4);
1097
1098   cio_write(0, 2);              /* Pre-defined */
1099
1100   cio_write(0, 2);              /* Reserved */
1101
1102   cio_write(0, 4);              /* Pre-defined */
1103   cio_write(0, 4);              /* Pre-defined */
1104   cio_write(0, 4);              /* Pre-defined */
1105
1106   cio_write(tk->w, 2);          /* Width  */
1107   cio_write(tk->h, 2);          /* Height */
1108
1109   cio_write(tk->horizresolution, 4);    /* Horizontal resolution */
1110   cio_write(tk->vertresolution, 4);     /* Vertical resolution   */
1111
1112   cio_write(0, 4);              /* Reserved */
1113
1114   cio_write(1, 2);              /* Pre-defined = 1 */
1115
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);
1124
1125   cio_write(tk->depth, 2);      /* Depth */
1126
1127   cio_write(0xffff, 2);         /* Pre-defined = -1 */
1128
1129   jp2_write_jp2h(&tk->jp2_struct);
1130
1131   mj2_write_fiel(tk);
1132
1133   if (tk->num_br != 0)
1134     mj2_write_jp2p(tk);
1135   if (tk->num_jp2x != 0)
1136     mj2_write_jp2x(tk);
1137
1138   mj2_write_jsub(tk);
1139   mj2_write_orfo(tk);
1140
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);
1145 }
1146
1147 /*
1148 * Read the SMJ2 box
1149 *
1150 * Visual Sample Entry Description
1151 *
1152 */
1153 int mj2_read_smj2(j2k_image_t * img, mj2_tk_t * tk)
1154 {
1155   mj2_box_t box;
1156   mj2_box_t box2;
1157   int i;
1158
1159   mj2_read_boxhdr(&box);
1160
1161   if (MJ2_MJ2 != box.type) {
1162     fprintf(stderr, "Error in SMJ2 box: Expected MJ2 Marker\n");
1163     return 1;
1164   }
1165
1166   if (0 != cio_read(1)) {       /* Version = 0 */
1167     fprintf(stderr, "Error: Only Version 0 handled in MJP2 box\n");
1168     return 1;
1169   }
1170
1171   if (0 != cio_read(3)) {       /* Flags = 0  */
1172     fprintf(stderr, "Error with flag in MJP2 box. Expected flag 0\n");
1173     return 1;
1174   }
1175
1176   cio_skip(4);
1177
1178   cio_skip(2);                  /* Pre-defined */
1179
1180   cio_skip(2);                  /* Reserved */
1181
1182   cio_skip(4);                  /* Pre-defined */
1183   cio_skip(4);                  /* Pre-defined */
1184   cio_skip(4);                  /* Pre-defined */
1185
1186   tk->w = cio_read(2);          /* Width  */
1187   tk->h = cio_read(2);          /* Height */
1188
1189   tk->horizresolution = cio_read(4);    /* Horizontal resolution */
1190   tk->vertresolution = cio_read(4);     /* Vertical resolution   */
1191
1192   cio_skip(4);                  /* Reserved */
1193
1194   cio_skip(2);                  /* Pre-defined = 1 */
1195
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);
1204
1205   tk->depth = cio_read(2);      /* Depth */
1206
1207   /* Init std value */
1208   tk->num_jp2x = 0;
1209   tk->fieldcount = 1;
1210   tk->fieldorder = 0;
1211   tk->or_fieldcount = 1;
1212   tk->or_fieldorder = 0;
1213
1214   cio_skip(2);                  /* Pre-defined = -1 */
1215
1216   if (jp2_read_jp2h(&tk->jp2_struct)) {
1217     fprintf(stderr, "Error with JP2H Box\n");
1218     return 1;
1219   }
1220   
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));
1223
1224   tk->num_br = 0;
1225   tk->num_jp2x = 0;
1226
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) {
1231     case MJ2_FIEL:
1232       if (mj2_read_fiel(tk))
1233         return 1;
1234       break;
1235
1236     case MJ2_JP2P:
1237       if (mj2_read_jp2p(tk))
1238         return 1;
1239       break;
1240
1241     case MJ2_JP2X:
1242       if (mj2_read_jp2x(tk))
1243         return 1;
1244       break;
1245
1246     case MJ2_JSUB:
1247       if (mj2_read_jsub(tk))
1248         return 1;
1249       break;
1250
1251     case MJ2_ORFO:
1252       if (mj2_read_orfo(tk))
1253         return 1;
1254       break;
1255
1256     default:
1257       fprintf(stderr, "Error with MJP2 Box size\n");
1258       return 1;
1259       break;
1260
1261     }
1262   }
1263   return 0;
1264 }
1265
1266
1267 /*
1268 * Write the STSD box
1269 *
1270 * Sample Description
1271 *
1272 */
1273 void mj2_write_stsd(mj2_tk_t * tk)
1274 {
1275   mj2_box_t box;
1276
1277   box.init_pos = cio_tell();
1278   cio_skip(4);
1279   cio_write(MJ2_STSD, 4);       /* STSD       */
1280
1281   cio_write(0, 4);              /* Version = 0, flags = 0 */
1282
1283   cio_write(1, 4);              /* entry_count = 1 (considering same JP2 headerboxes) */
1284
1285   if (tk->track_type == 0) {
1286     mj2_write_smj2(tk);
1287   } else if (tk->track_type == 1) {
1288     // Not implemented
1289   }
1290   if (tk->track_type == 2) {
1291     // Not implemented
1292   }
1293
1294
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);
1299 }
1300
1301 /*
1302 * Read the STSD box
1303 *
1304 * Sample Description
1305 *
1306 */
1307 int mj2_read_stsd(mj2_tk_t * tk, j2k_image_t * img)
1308 {
1309   int i;
1310   int entry_count, len_2skip;
1311
1312   mj2_box_t box;
1313
1314   mj2_read_boxhdr(&box);
1315
1316   if (MJ2_STSD != box.type) {
1317     fprintf(stderr, "Error: Expected STSD Marker\n");
1318     return 1;
1319   }
1320
1321   if (0 != cio_read(1)) {       /* Version = 0 */
1322     fprintf(stderr, "Error: Only Version 0 handled in STSD box\n");
1323     return 1;
1324   }
1325
1326   if (0 != cio_read(3)) {       /* Flags = 0  */
1327     fprintf(stderr, "Error with flag in STSD box. Expected flag 0\n");
1328     return 1;
1329   }
1330
1331   entry_count = cio_read(4);
1332
1333   if (tk->track_type == 0) {
1334     for (i = 0; i < entry_count; i++) {
1335       if (mj2_read_smj2(img, tk))
1336         return 1;
1337     }
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);
1344   }
1345
1346
1347   if (cio_tell() - box.init_pos != box.length) {
1348     fprintf(stderr, "Error with STSD Box size\n");
1349     return 1;
1350   }
1351   return 0;
1352 }
1353
1354 /*
1355 * Write the STBL box
1356 *
1357 * Sample table box box
1358 *
1359 */
1360 void mj2_write_stbl(mj2_tk_t * tk)
1361 {
1362   mj2_box_t box;
1363
1364   box.init_pos = cio_tell();
1365   cio_skip(4);
1366   cio_write(MJ2_STBL, 4);       /* STBL       */
1367
1368   mj2_write_stsd(tk);
1369   mj2_write_stts(tk);
1370   mj2_write_stsc(tk);
1371   mj2_write_stsz(tk);
1372   mj2_write_stco(tk);
1373
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);
1378 }
1379
1380 /*
1381 * Read the STBL box
1382 *
1383 * Sample table box box
1384 *
1385 */
1386 int mj2_read_stbl(mj2_tk_t * tk, j2k_image_t * img)
1387 {
1388   mj2_box_t box;
1389
1390   mj2_read_boxhdr(&box);
1391   if (MJ2_STBL != box.type) {
1392     fprintf(stderr, "Error: Expected STBL Marker\n");
1393     return 1;
1394   }
1395
1396   if (mj2_read_stsd(tk, img))
1397     return 1;
1398   if (mj2_read_stts(tk))
1399     return 1;
1400   if (mj2_read_stsc(tk))
1401     return 1;
1402   if (mj2_read_stsz(tk))
1403     return 1;
1404   if (mj2_read_stco(tk))
1405     return 1;
1406
1407   if (cio_tell() - box.init_pos != box.length) {
1408     fprintf(stderr, "Error with STBL Box size\n");
1409     return 1;
1410   }
1411   return 0;
1412 }
1413
1414 /*
1415 * Write the URL box
1416 *
1417 * URL box
1418 *
1419 */
1420 void mj2_write_url(mj2_tk_t * tk, int url_num)
1421 {
1422   mj2_box_t box;
1423
1424   box.init_pos = cio_tell();
1425   cio_skip(4);
1426   cio_write(MJ2_URL, 4);        /* URL       */
1427
1428   if (url_num == 0)
1429     cio_write(1, 4);            /* Version = 0, flags = 1 because stored in same file */
1430   else {
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);
1436   }
1437
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);
1442 }
1443
1444 /*
1445 * Read the URL box
1446 *
1447 * URL box
1448 *
1449 */
1450 int mj2_read_url(mj2_tk_t * tk, int urn_num)
1451 {
1452   mj2_box_t box;
1453
1454   mj2_read_boxhdr(&box);
1455   if (MJ2_URL != box.type) {
1456     fprintf(stderr, "Error: Expected URL Marker\n");
1457     return 1;
1458   }
1459
1460   if (0 != cio_read(1)) {       /* Version = 0 */
1461     fprintf(stderr, "Error: Only Version 0 handled in URL box\n");
1462     return 1;
1463   }
1464
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);
1470   } else {
1471     tk->num_url--;
1472   }
1473
1474
1475   if (cio_tell() - box.init_pos != box.length) {
1476     fprintf(stderr, "Error with URL Box size\n");
1477     return 1;
1478   }
1479   return 0;
1480 }
1481
1482 /*
1483 * Write the URN box
1484 *
1485 * URN box
1486 *
1487 */
1488 void mj2_write_urn(mj2_tk_t * tk, int urn_num)
1489 {
1490   mj2_box_t box;
1491
1492   box.init_pos = cio_tell();
1493   cio_skip(4);
1494   cio_write(MJ2_URN, 4);        /* URN       */
1495
1496   cio_write(0, 4);              /* Version = 0, flags =  0 */
1497
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);
1506
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);
1511 }
1512
1513 /*
1514 * Read the URN box
1515 *
1516 * URN box
1517 *
1518 */
1519 int mj2_read_urn(mj2_tk_t * tk, int urn_num)
1520 {
1521
1522   mj2_box_t box;
1523
1524   mj2_read_boxhdr(&box);
1525   if (MJ2_URN != box.type) {
1526     fprintf(stderr, "Error: Expected URN Marker\n");
1527     return 1;
1528   }
1529
1530   if (0 != cio_read(1)) {       /* Version = 0 */
1531     fprintf(stderr, "Error: Only Version 0 handled in URN box\n");
1532     return 1;
1533   }
1534
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);
1544   }
1545
1546
1547   if (cio_tell() - box.init_pos != box.length) {
1548     fprintf(stderr, "Error with URN Box size\n");
1549     return 1;
1550   }
1551   return 0;
1552 }
1553
1554
1555 /*
1556 * Write the DREF box
1557 *
1558 * Data reference box
1559 *
1560 */
1561 void mj2_write_dref(mj2_tk_t * tk)
1562 {
1563   int i;
1564   mj2_box_t box;
1565
1566   box.init_pos = cio_tell();
1567   cio_skip(4);
1568   cio_write(MJ2_DREF, 4);       /* DREF       */
1569
1570   cio_write(0, 4);              /* Version = 0, flags = 0 */
1571
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);
1575   } else {
1576     cio_write(tk->num_url + tk->num_urn, 4);    /* entry_count */
1577
1578     for (i = 0; i < tk->num_url; i++)
1579       mj2_write_url(tk, i + 1);
1580
1581     for (i = 0; i < tk->num_urn; i++)
1582       mj2_write_urn(tk, i);
1583   }
1584
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);
1589 }
1590
1591 /*
1592 * Read the DREF box
1593 *
1594 * Data reference box
1595 *
1596 */
1597 int mj2_read_dref(mj2_tk_t * tk)
1598 {
1599
1600   int i;
1601   int entry_count, marker;
1602   mj2_box_t box;
1603
1604   mj2_read_boxhdr(&box);
1605   if (MJ2_DREF != box.type) {
1606     fprintf(stderr, "Error: Expected DREF Marker\n");
1607     return 1;
1608   }
1609
1610   if (0 != cio_read(1)) {       /* Version = 0 */
1611     fprintf(stderr, "Error: Only Version 0 handled in DREF box\n");
1612     return 1;
1613   }
1614
1615   if (0 != cio_read(3)) {       /* Flags = 0  */
1616     fprintf(stderr, "Error with flag in DREF box. Expected flag 0\n");
1617     return 1;
1618   }
1619
1620   entry_count = cio_read(4);
1621   tk->num_url = 0;
1622   tk->num_urn = 0;
1623
1624   for (i = 0; i < entry_count; i++) {
1625     cio_skip(4);
1626     marker = cio_read(4);
1627     if (marker == MJ2_URL) {
1628       cio_skip(-8);
1629       tk->num_url++;
1630       if (mj2_read_url(tk, tk->num_url))
1631         return 1;
1632     } else if (marker == MJ2_URN) {
1633       cio_skip(-8);
1634       tk->num_urn++;
1635       if (mj2_read_urn(tk, tk->num_urn))
1636         return 1;
1637     } else {
1638       fprintf(stderr, "Error with in DREF box. Expected URN or URL box\n");
1639       return 1;
1640     }
1641
1642   }
1643
1644
1645   if (cio_tell() - box.init_pos != box.length) {
1646     fprintf(stderr, "Error with DREF Box size\n");
1647     return 1;
1648   }
1649   return 0;
1650 }
1651
1652 /*
1653 * Write the DINF box
1654 *
1655 * Data information box
1656 *
1657 */
1658 void mj2_write_dinf(mj2_tk_t * tk)
1659 {
1660   mj2_box_t box;
1661
1662   box.init_pos = cio_tell();
1663   cio_skip(4);
1664   cio_write(MJ2_DINF, 4);       /* DINF       */
1665
1666   mj2_write_dref(tk);
1667
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);
1672 }
1673
1674 /*
1675 * Read the DINF box
1676 *
1677 * Data information box
1678 *
1679 */
1680 int mj2_read_dinf(mj2_tk_t * tk)
1681 {
1682   mj2_box_t box;
1683
1684   mj2_read_boxhdr(&box);
1685   if (MJ2_DINF != box.type) {
1686     fprintf(stderr, "Error: Expected DINF Marker\n");
1687     return 1;
1688   }
1689
1690   if (mj2_read_dref(tk))
1691     return 1;
1692
1693   if (cio_tell() - box.init_pos != box.length) {
1694     fprintf(stderr, "Error with DINF Box size\n");
1695     return 1;
1696   }
1697   return 0;
1698 }
1699
1700 /*
1701 * Write the VMHD box
1702 *
1703 * Video Media information box
1704 *
1705 */
1706 void mj2_write_vmhd(mj2_tk_t * tk)
1707 {
1708   mj2_box_t box;
1709
1710   box.init_pos = cio_tell();
1711   cio_skip(4);
1712   cio_write(MJ2_VMHD, 4);       /* VMHD       */
1713
1714   cio_write(1, 4);              /* Version = 0, flags = 1 */
1715
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);
1720
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);
1725 }
1726
1727 /*
1728 * Read the VMHD box
1729 *
1730 * Video Media information box
1731 *
1732 */
1733 int mj2_read_vmhd(mj2_tk_t * tk)
1734 {
1735   mj2_box_t box;
1736
1737   mj2_read_boxhdr(&box);
1738   if (MJ2_VMHD != box.type) {
1739     fprintf(stderr, "Error: Expected VMHD Marker\n");
1740     return 1;
1741   }
1742
1743   if (0 != cio_read(1)) {       /* Version = 0 */
1744     fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
1745     return 1;
1746   }
1747
1748   if (1 != cio_read(3)) {       /* Flags = 1  */
1749     fprintf(stderr, "Error with flag in VMHD box. Expected flag 1\n");
1750     return 1;
1751   }
1752
1753   tk->track_type = 0;
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);
1758
1759   if (cio_tell() - box.init_pos != box.length) {
1760     fprintf(stderr, "Error with VMHD Box size\n");
1761     return 1;
1762   }
1763   return 0;
1764 }
1765
1766 /*
1767 * Write the SMHD box
1768 *
1769 * Sound Media information box
1770 *
1771 */
1772 void mj2_write_smhd(mj2_tk_t * tk)
1773 {
1774   mj2_box_t box;
1775
1776   box.init_pos = cio_tell();
1777   cio_skip(4);
1778   cio_write(MJ2_SMHD, 4);       /* SMHD       */
1779
1780   cio_write(0, 4);              /* Version = 0, flags = 0 */
1781
1782   cio_write(tk->balance << 8, 2);
1783
1784   cio_write(0, 2);              /* Reserved */
1785
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);
1790 }
1791
1792 /*
1793 * Read the SMHD box
1794 *
1795 * Sound Media information box
1796 *
1797 */
1798 int mj2_read_smhd(mj2_tk_t * tk)
1799 {
1800   mj2_box_t box;
1801
1802   mj2_read_boxhdr(&box);
1803   if (MJ2_SMHD != box.type) {
1804     fprintf(stderr, "Error: Expected SMHD Marker\n");
1805     return 1;
1806   }
1807
1808   if (0 != cio_read(1)) {       /* Version = 0 */
1809     fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
1810     return 1;
1811   }
1812
1813   if (0 != cio_read(3)) {       /* Flags = 0  */
1814     fprintf(stderr, "Error with flag in VMHD box. Expected flag 0\n");
1815     return 1;
1816   }
1817
1818   tk->track_type = 1;
1819   tk->balance = cio_read(2) >> 8;
1820
1821   cio_skip(2);                  /* Reserved */
1822
1823   if (cio_tell() - box.init_pos != box.length) {
1824     fprintf(stderr, "Error with SMHD Box size\n");
1825     return 1;
1826   }
1827   return 0;
1828 }
1829
1830 /*
1831 * Write the HMHD box
1832 *
1833 * Hint Media information box
1834 *
1835 */
1836 void mj2_write_hmhd(mj2_tk_t * tk)
1837 {
1838   mj2_box_t box;
1839
1840   box.init_pos = cio_tell();
1841   cio_skip(4);
1842   cio_write(MJ2_HMHD, 4);       /* HMHD       */
1843
1844   cio_write(0, 4);              /* Version = 0, flags = 0 */
1845
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);
1851
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);
1856 }
1857
1858 /*
1859 * Read the HMHD box
1860 *
1861 * Hint Media information box
1862 *
1863 */
1864 int mj2_read_hmhd(mj2_tk_t * tk)
1865 {
1866   mj2_box_t box;
1867
1868   mj2_read_boxhdr(&box);
1869   if (MJ2_HMHD != box.type) {
1870     fprintf(stderr, "Error: Expected HMHD Marker\n");
1871     return 1;
1872   }
1873
1874   if (0 != cio_read(1)) {       /* Version = 0 */
1875     fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
1876     return 1;
1877   }
1878
1879   if (0 != cio_read(3)) {       /* Flags = 0  */
1880     fprintf(stderr, "Error with flag in VMHD box. Expected flag 0\n");
1881     return 1;
1882   }
1883
1884   tk->track_type = 2;
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);
1890
1891   if (cio_tell() - box.init_pos != box.length) {
1892     fprintf(stderr, "Error with HMHD Box size\n");
1893     return 1;
1894   }
1895   return 0;
1896 }
1897
1898 /*
1899 * Write the MINF box
1900 *
1901 * Media information box
1902 *
1903 */
1904 void mj2_write_minf(mj2_tk_t * tk)
1905 {
1906   mj2_box_t box;
1907
1908   box.init_pos = cio_tell();
1909   cio_skip(4);
1910   cio_write(MJ2_MINF, 4);       /* MINF       */
1911
1912   if (tk->track_type == 0) {
1913     mj2_write_vmhd(tk);
1914   } else if (tk->track_type == 1) {
1915     mj2_write_smhd(tk);
1916   } else if (tk->track_type == 2) {
1917     mj2_write_hmhd(tk);
1918   }
1919
1920   mj2_write_dinf(tk);
1921   mj2_write_stbl(tk);
1922
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);
1927 }
1928
1929 /*
1930 * Read the MINF box
1931 *
1932 * Media information box
1933 *
1934 */
1935 int mj2_read_minf(mj2_tk_t * tk, j2k_image_t * img)
1936 {
1937
1938   unsigned int box_type;
1939   mj2_box_t box;
1940
1941   mj2_read_boxhdr(&box);
1942   if (MJ2_MINF != box.type) {
1943     fprintf(stderr, "Error: Expected MINF Marker\n");
1944     return 1;
1945   }
1946
1947   cio_skip(4);
1948   box_type = cio_read(4);
1949   cio_skip(-8);
1950
1951   if (box_type == MJ2_VMHD) {
1952     if (mj2_read_vmhd(tk))
1953       return 1;
1954   } else if (box_type == MJ2_SMHD) {
1955     if (mj2_read_smhd(tk))
1956       return 1;
1957   } else if (box_type == MJ2_HMHD) {
1958     if (mj2_read_hmhd(tk))
1959       return 1;
1960   } else {
1961     fprintf(stderr, "Error in MINF box expected vmhd, smhd or hmhd\n");
1962     return 1;
1963   }
1964
1965   if (mj2_read_dinf(tk))
1966     return 1;
1967
1968   if (mj2_read_stbl(tk, img))
1969     return 1;
1970
1971   if (cio_tell() - box.init_pos != box.length) {
1972     fprintf(stderr, "Error with MINF Box size\n");
1973     return 1;
1974   }
1975   return 0;
1976 }
1977
1978 /*
1979 * Write the HDLR box
1980 *
1981 * Handler reference box
1982 *
1983 */
1984 void mj2_write_hdlr(mj2_tk_t * tk)
1985 {
1986   mj2_box_t box;
1987
1988   box.init_pos = cio_tell();
1989   cio_skip(4);
1990   cio_write(MJ2_HDLR, 4);       /* HDLR       */
1991
1992   cio_write(0, 4);              /* Version = 0, flags = 0 */
1993
1994   cio_write(0, 4);              /* Predefine */
1995
1996   tk->name = 0;                 /* The track name is immediately determined by the track type */
1997
1998   if (tk->track_type == 0) {
1999     tk->handler_type = 0x76696465;      /* Handler type: vide */
2000     cio_write(tk->handler_type, 4);
2001
2002     cio_write(0, 4);
2003     cio_write(0, 4);
2004     cio_write(0, 4);            /* Reserved */
2005
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);
2014
2015     cio_write(0, 4);
2016     cio_write(0, 4);
2017     cio_write(0, 4);            /* Reserved */
2018
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);
2024
2025     cio_write(0, 4);
2026     cio_write(0, 4);
2027     cio_write(0, 4);            /* Reserved */
2028
2029     cio_write(0x48696E74, 4);
2030     cio_write(0, 2);            /* String: Hint */
2031   }
2032
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);
2037 }
2038
2039 /*
2040 * Read the HDLR box
2041 *
2042 * Handler reference box
2043 *
2044 */
2045 int mj2_read_hdlr(mj2_tk_t * tk)
2046 {
2047   int i;
2048   mj2_box_t box;
2049
2050   mj2_read_boxhdr(&box);
2051   if (MJ2_HDLR != box.type) {
2052     fprintf(stderr, "Error: Expected HDLR Marker\n");
2053     return 1;
2054   }
2055
2056
2057   if (0 != cio_read(1)) {       /* Version = 0 */
2058     fprintf(stderr, "Error: Only Version 0 handled in VMHD box\n");
2059     return 1;
2060   }
2061
2062   if (0 != cio_read(3)) {       /* Flags = 0  */
2063     fprintf(stderr, "Error with flag in VMHD box. Expected flag 0\n");
2064     return 1;
2065   }
2066
2067   cio_skip(4);                  /* Reserved */
2068
2069   tk->handler_type = cio_read(4);
2070   cio_skip(12);                 /* Reserved */
2071
2072   tk->name_size = box.length - 32;
2073
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 */
2077   }
2078
2079   if (cio_tell() - box.init_pos != box.length) {
2080     fprintf(stderr, "Error with HDLR Box size\n");
2081     return 1;
2082   }
2083   return 0;
2084 }
2085
2086 /*
2087 * Write the MDHD box
2088 *
2089 * Media Header Box
2090 *
2091 */
2092 void mj2_write_mdhd(mj2_tk_t * tk)
2093 {
2094   mj2_box_t box;
2095   unsigned int i;
2096   time_t ltime;
2097   unsigned int modification_time;
2098
2099   box.init_pos = cio_tell();
2100   cio_skip(4);
2101   cio_write(MJ2_MDHD, 4);       /* MDHD       */
2102
2103   cio_write(0, 4);              /* Version = 0, flags = 0 */
2104
2105   cio_write(tk->creation_time, 4);      /* Creation Time */
2106
2107   time(&ltime);                 /* Time since 1/1/70 */
2108   modification_time = ltime + 2082844800;       /* Seoonds between 1/1/04 and 1/1/70 */
2109
2110   cio_write(modification_time, 4);      /* Modification Time */
2111
2112   cio_write(tk->timescale, 4);  /* Timescale */
2113
2114   tk->duration = 0;
2115
2116   for (i = 0; i < tk->num_samples; i++)
2117     tk->duration += tk->sample[i].sample_delta;
2118
2119   cio_write(tk->duration, 4);   /* Duration */
2120
2121   cio_write(tk->language, 2);   /* Language */
2122
2123   cio_write(0, 2);              /* Predefined */
2124
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);
2129 }
2130
2131 /*
2132 * Read the MDHD box
2133 *
2134 * Media Header Box
2135 *
2136 */
2137 int mj2_read_mdhd(mj2_tk_t * tk)
2138 {
2139   mj2_box_t box;
2140
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");
2144     return 1;
2145   }
2146
2147   if (0 != cio_read(1)) {       /* Version = 0 */
2148     fprintf(stderr, "Error: Only Version 0 handled in MDHD box\n");
2149     return 1;
2150   }
2151
2152   if (0 != cio_read(3)) {       /* Flags = 0 */
2153     fprintf(stderr, "Error with flag in MDHD box. Expected flag 0\n");
2154     return 1;
2155   }
2156
2157
2158   tk->creation_time = cio_read(4);      /* Creation Time */
2159
2160   tk->modification_time = cio_read(4);  /* Modification Time */
2161
2162   tk->timescale = cio_read(4);  /* Timescale */
2163
2164   tk->duration = cio_read(4);   /* Duration */
2165
2166   tk->language = cio_read(2);   /* Language */
2167
2168   cio_skip(2);                  /* Predefined */
2169
2170   if (cio_tell() - box.init_pos != box.length) {
2171     fprintf(stderr, "Error with MDHD Box size\n");
2172     return 1;
2173   }
2174   return 0;
2175 }
2176
2177 /*
2178 * Write the MDIA box
2179 *
2180 * Media box
2181 *
2182 */
2183 void mj2_write_mdia(mj2_tk_t * tk)
2184 {
2185   mj2_box_t box;
2186
2187   box.init_pos = cio_tell();
2188   cio_skip(4);
2189   cio_write(MJ2_MDIA, 4);       /* MDIA       */
2190
2191   mj2_write_mdhd(tk);
2192   mj2_write_hdlr(tk);
2193   mj2_write_minf(tk);
2194
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);
2199 }
2200
2201 /*
2202 * Read the MDIA box
2203 *
2204 * Media box
2205 *
2206 */
2207 int mj2_read_mdia(mj2_tk_t * tk, j2k_image_t * img)
2208 {
2209   mj2_box_t box;
2210
2211   mj2_read_boxhdr(&box);
2212   if (MJ2_MDIA != box.type) {
2213     fprintf(stderr, "Error: Expected MDIA Marker\n");
2214     return 1;
2215   }
2216
2217   if (mj2_read_mdhd(tk))
2218     return 1;
2219   if (mj2_read_hdlr(tk))
2220     return 1;
2221   if (mj2_read_minf(tk, img))
2222     return 1;
2223
2224   if (cio_tell() - box.init_pos != box.length) {
2225     fprintf(stderr, "Error with MDIA Box size\n");
2226     return 1;
2227   }
2228   return 0;
2229 }
2230
2231 /*
2232 * Write the TKHD box
2233 *
2234 * Track Header box
2235 *
2236 */
2237 void mj2_write_tkhd(mj2_tk_t * tk)
2238 {
2239   mj2_box_t box;
2240   unsigned int i;
2241   time_t ltime;
2242
2243   box.init_pos = cio_tell();
2244   cio_skip(4);
2245
2246   cio_write(MJ2_TKHD, 4);       /* TKHD       */
2247
2248   cio_write(3, 4);              /* Version=0, flags=3 */
2249
2250   time(&ltime);                 /* Time since 1/1/70 */
2251   tk->modification_time = ltime + 2082844800;   /* Seoonds between 1/1/04 and 1/1/70 */
2252
2253   cio_write(tk->creation_time, 4);      /* Creation Time */
2254
2255   cio_write(tk->modification_time, 4);  /* Modification Time */
2256
2257   cio_write(tk->track_ID, 4);   /* Track ID */
2258
2259   cio_write(0, 4);              /* Reserved */
2260
2261   tk->duration = 0;
2262
2263   for (i = 0; i < tk->num_samples; i++)
2264     tk->duration += tk->sample[i].sample_delta;
2265
2266   cio_write(tk->duration, 4);   /* Duration */
2267
2268   cio_write(0, 4);              /* Reserved */
2269   cio_write(0, 4);              /* Reserved */
2270
2271   cio_write(tk->layer, 2);      /* Layer    */
2272
2273   cio_write(0, 2);              /* Predefined */
2274
2275   cio_write(tk->volume << 8, 2);        /* Volume       */
2276
2277   cio_write(0, 2);              /* Reserved */
2278
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);
2288
2289   cio_write(tk->w << 16, 4);    /* Video Width  */
2290
2291   cio_write(tk->h << 16, 4);    /* Video Height */
2292
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);
2297 }
2298
2299 /*
2300 * Read the TKHD box
2301 *
2302 * Track Header box
2303 *
2304 */
2305 int mj2_read_tkhd(mj2_tk_t * tk)
2306 {
2307   int flag;
2308
2309   mj2_box_t box;
2310
2311   mj2_read_boxhdr(&box);
2312
2313   if (MJ2_TKHD != box.type) {
2314     fprintf(stderr, "Error: Expected TKHD Marker\n");
2315     return 1;
2316   }
2317
2318   if (0 != cio_read(1)) {       /* Version = 0 */
2319     fprintf(stderr, "Error: Only Version 0 handled in TKHD box\n");
2320     return 1;
2321   }
2322
2323   flag = cio_read(3);
2324
2325   if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) {    /* Flags = 1,2,3 or 4 */
2326     fprintf(stderr,
2327             "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2328     return 1;
2329   }
2330
2331   tk->creation_time = cio_read(4);      /* Creation Time */
2332
2333   tk->modification_time = cio_read(4);  /* Modification Time */
2334
2335   tk->track_ID = cio_read(4);   /* Track ID */
2336
2337   cio_skip(4);                  /* Reserved */
2338
2339   tk->duration = cio_read(4);   /* Duration */
2340
2341   cio_skip(8);                  /* Reserved */
2342
2343   tk->layer = cio_read(2);      /* Layer    */
2344
2345   cio_read(2);                  /* Predefined */
2346
2347   tk->volume = cio_read(2) >> 8;        /* Volume       */
2348
2349   cio_skip(2);                  /* Reserved */
2350
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);
2360
2361   tk->w = cio_read(4) >> 16;    /* Video Width  */
2362
2363   tk->h = cio_read(4) >> 16;    /* Video Height */
2364
2365   if (cio_tell() - box.init_pos != box.length) {
2366     fprintf(stderr, "Error with TKHD Box size\n");
2367     return 1;
2368   }
2369   return 0;
2370 }
2371
2372 /*
2373 * Write the TRAK box
2374 *
2375 * Track box
2376 *
2377 */
2378 void mj2_write_trak(mj2_tk_t * tk)
2379 {
2380   mj2_box_t box;
2381
2382   box.init_pos = cio_tell();
2383   cio_skip(4);
2384
2385   cio_write(MJ2_TRAK, 4);       /* TRAK       */
2386
2387   mj2_write_tkhd(tk);
2388   mj2_write_mdia(tk);
2389
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);
2394 }
2395
2396 /*
2397 * Read the TRAK box
2398 *
2399 * Track box
2400 *
2401 */
2402 int mj2_read_trak(mj2_tk_t * tk, j2k_image_t * img)
2403 {
2404   mj2_box_t box;
2405
2406   mj2_read_boxhdr(&box);
2407   if (MJ2_TRAK != box.type) {
2408     fprintf(stderr, "Error: Expected TRAK Marker\n");
2409     return 1;
2410   }
2411   if (mj2_read_tkhd(tk))
2412     return 1;
2413   if (mj2_read_mdia(tk, img))
2414     return 1;
2415   if (cio_tell() - box.init_pos != box.length) {
2416     fprintf(stderr, "Error with TRAK Box\n");
2417     return 1;
2418   }
2419   return 0;
2420 }
2421
2422 /*
2423 * Write the MVHD box
2424 *
2425 * Movie header Box
2426 *
2427 */
2428 void mj2_write_mvhd(mj2_movie_t * movie)
2429 {
2430   int i;
2431   mj2_box_t box;
2432   unsigned j;
2433   time_t ltime;
2434   int max_tk_num = 0;
2435
2436   box.init_pos = cio_tell();
2437   cio_skip(4);
2438   cio_write(MJ2_MVHD, 4);       /* MVHD       */
2439
2440   cio_write(0, 4);              /* Version = 0, flags = 0 */
2441
2442   time(&ltime);                 /* Time since 1/1/70 */
2443   movie->modification_time = ltime + 2082844800;        /* Seoonds between 1/1/04 and 1/1/70 */
2444
2445   cio_write(movie->creation_time, 4);   /* Creation Time */
2446
2447   cio_write(movie->modification_time, 4);       /* Modification Time */
2448
2449   cio_write(movie->timescale, 4);       /* Timescale */
2450
2451   movie->duration = 0;
2452
2453   for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2454     mj2_tk_t *tk = &movie->tk[i];
2455
2456     for (j = 0; j < tk->num_samples; j++) {
2457       movie->duration += tk->sample[j].sample_delta;
2458     }
2459   }
2460
2461   cio_write(movie->duration, 4);
2462
2463   cio_write(movie->rate << 16, 4);      /* Rate to play presentation    */
2464
2465   cio_write(movie->volume << 8, 2);     /* Volume       */
2466
2467   cio_write(0, 2);              /* Reserved */
2468   cio_write(0, 4);              /* Reserved */
2469   cio_write(0, 4);              /* Reserved */
2470
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);
2480
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 */
2487
2488
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;
2492   }
2493
2494   movie->next_tk_id = max_tk_num + 1;
2495
2496   cio_write(movie->next_tk_id, 4);      /* ID of Next track to be added */
2497
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);
2502 }
2503
2504 /*
2505 * Read the MVHD box
2506 *
2507 * Movie header Box
2508 *
2509 */
2510 int mj2_read_mvhd(mj2_movie_t * movie)
2511 {
2512   mj2_box_t box;
2513
2514   mj2_read_boxhdr(&box);
2515   if (MJ2_MVHD != box.type) {
2516     fprintf(stderr, "Error: Expected MVHD Marker\n");
2517     return 1;
2518   }
2519
2520
2521   if (0 != cio_read(4)) {       /* Version = 0, flags = 0 */
2522     fprintf(stderr, "Error: Only Version 0 handled\n");
2523   }
2524
2525   movie->creation_time = cio_read(4);   /* Creation Time */
2526
2527   movie->modification_time = cio_read(4);       /* Modification Time */
2528
2529   movie->timescale = cio_read(4);       /* Timescale */
2530
2531   movie->duration = cio_read(4);        /* Duration */
2532
2533   movie->rate = cio_read(4) >> 16;      /* Rate to play presentation    */
2534
2535   movie->volume = cio_read(2) >> 8;     /* Volume       */
2536
2537   cio_skip(10);                 /* Reserved */
2538
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);
2548
2549   cio_skip(24);                 /* Pre-defined */
2550
2551   movie->next_tk_id = cio_read(4);      /* ID of Next track to be added */
2552
2553   if (cio_tell() - box.init_pos != box.length) {
2554     fprintf(stderr, "Error with MVHD Box Size\n");
2555     return 1;
2556   }
2557   return 0;
2558 }
2559
2560
2561 /*
2562 * Write the MOOV box
2563 *
2564 * Movie Box
2565 *
2566 */
2567 void mj2_write_moov(mj2_movie_t * movie)
2568 {
2569   int i;
2570   mj2_box_t box;
2571
2572   box.init_pos = cio_tell();
2573   cio_skip(4);
2574   cio_write(MJ2_MOOV, 4);       /* MOOV       */
2575
2576   mj2_write_mvhd(movie);
2577
2578   for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2579     mj2_write_trak(&movie->tk[i]);
2580   }
2581
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);
2586
2587 }
2588
2589 /*
2590 * Read the MOOV box
2591 *
2592 * Movie Box
2593 *
2594 */
2595 int mj2_read_moov(mj2_movie_t * movie, j2k_image_t * img)
2596 {
2597   unsigned int i;
2598   mj2_box_t box;
2599   mj2_box_t box2;
2600
2601   mj2_read_boxhdr(&box);
2602   if (MJ2_MOOV != box.type) {
2603     fprintf(stderr, "Error: Expected MOOV Marker\n");
2604     return 1;
2605   }
2606
2607
2608
2609   if (mj2_read_mvhd(movie))
2610     return 1;
2611
2612
2613   movie->tk =
2614     (mj2_tk_t *) malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2615
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))
2621         return 1;
2622
2623       if (movie->tk[i].track_type == 0) {
2624         movie->num_vtk++;
2625       } else if (movie->tk[i].track_type == 1) {
2626         movie->num_stk++;
2627       } else if (movie->tk[i].track_type == 2) {
2628         movie->num_htk++;
2629       }
2630     } else if (box2.type == MJ2_MVEX) {
2631       cio_seek(box2.init_pos);
2632       cio_skip(box2.length);
2633       i--;
2634     } else {
2635       fprintf(stderr, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2636       return 1;
2637     }
2638   }
2639   return 0;
2640 }
2641
2642 int mj2_read_struct(FILE *file, mj2_movie_t * movie) {
2643   mj2_box_t box;
2644   j2k_image_t img;
2645   char * src;
2646   int fsresult;
2647   int foffset;
2648
2649   movie->num_vtk=0;
2650   movie->num_stk=0;
2651   movie->num_htk=0;
2652     
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
2656   
2657   cio_init(src, 300);
2658   
2659   if (mj2_read_jp())
2660     return 1;
2661   if (mj2_read_ftyp(movie))
2662     return 1;
2663
2664   fsresult = fseek(file,cio_tell(),SEEK_SET);
2665   if( fsresult ) {
2666     fprintf(stderr, "End of file reached while trying to read data after FTYP box\n" );
2667     return 1;
2668   }
2669
2670   foffset = cio_tell();
2671   
2672   box.type = 0;
2673   
2674   fread(src,30,1,file);
2675   cio_init(src, 30);
2676   mj2_read_boxhdr(&box);
2677   
2678   while(box.type != MJ2_MOOV) {
2679     
2680     switch(box.type)
2681     {
2682     case MJ2_MDAT:
2683       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2684       if( fsresult ) {
2685         fprintf(stderr, "End of file reached while trying to read MDAT box\n" );
2686         return 1;
2687       }
2688       foffset += box.length;
2689       break;
2690       
2691     case MJ2_MOOF:
2692       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2693       if( fsresult ) {
2694         fprintf(stderr, "End of file reached while trying to read MOOF box\n" );
2695         return 1;
2696       }
2697       foffset += box.length;
2698       break;      
2699     case MJ2_FREE:
2700       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2701       if( fsresult ) {
2702         fprintf(stderr, "End of file reached while trying to read FREE box\n" );
2703         return 1;
2704       }
2705       foffset += box.length;
2706       break;      
2707     case MJ2_SKIP:
2708       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2709       if( fsresult ) {
2710         fprintf(stderr, "End of file reached while trying to read SKIP bo\nx" );
2711         return 1;
2712       }
2713       foffset += box.length;
2714       break;      
2715     default:
2716       fprintf(stderr, "Unknown box in MJ2 stream\n");
2717       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2718       if( fsresult ) {
2719         fprintf(stderr, "End of file reached while trying to read %s box\n", box.type ); 
2720         return 1;
2721       }      
2722       foffset += box.length;
2723       break;
2724     }
2725     fsresult = fread(src,8,1,file);
2726     if (fsresult != 1) {
2727       fprintf(stderr, "MOOV box not found in file\n"); 
2728       return 1;
2729     }
2730     cio_init(src, 8);
2731     mj2_read_boxhdr(&box);
2732   }
2733
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"); 
2739     return 1;
2740   }
2741
2742   cio_init(src, box.length);
2743   
2744   if (mj2_read_moov(movie, &img))
2745     return 1;
2746   
2747   free(src);
2748   return 0;
2749 }