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