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