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