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