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