[trunk] FolderReorgProposal task: cleanup doxygen
[openjpeg.git] / src / lib / openmj2 / 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   opj_jp2_color_t color;
1100   int i;
1101   opj_bool ok;
1102
1103   mj2_read_boxhdr(&box, cio);
1104         
1105   if (MJ2_MJ2 != box.type) {
1106     opj_event_msg(cio->cinfo, EVT_ERROR, "Error in SMJ2 box: Expected MJ2 Marker\n");
1107     return 1;
1108   }
1109         
1110   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1111     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MJP2 box\n");
1112     return 1;
1113   }
1114         
1115   if (0 != cio_read(cio, 3)) {  /* Flags = 0  */
1116     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MJP2 box. Expected flag 0\n");
1117     return 1;
1118   }
1119         
1120   cio_skip(cio,4);
1121         
1122   cio_skip(cio,2);                      /* Pre-defined */
1123         
1124   cio_skip(cio,2);                      /* Reserved */
1125         
1126   cio_skip(cio,4);                      /* Pre-defined */
1127   cio_skip(cio,4);                      /* Pre-defined */
1128   cio_skip(cio,4);                      /* Pre-defined */
1129         
1130   tk->w = cio_read(cio, 2);             /* Width  */
1131   tk->h = cio_read(cio, 2);             /* Height */
1132         
1133   tk->horizresolution = cio_read(cio, 4);       /* Horizontal resolution */
1134   tk->vertresolution = cio_read(cio, 4);        /* Vertical resolution   */
1135         
1136   cio_skip(cio,4);                      /* Reserved */
1137         
1138   cio_skip(cio,2);                      /* Pre-defined = 1 */
1139         
1140   tk->compressorname[0] = cio_read(cio, 4);     /* Compressor Name */
1141   tk->compressorname[1] = cio_read(cio, 4);
1142   tk->compressorname[2] = cio_read(cio, 4);
1143   tk->compressorname[3] = cio_read(cio, 4);
1144   tk->compressorname[4] = cio_read(cio, 4);
1145   tk->compressorname[5] = cio_read(cio, 4);
1146   tk->compressorname[6] = cio_read(cio, 4);
1147   tk->compressorname[7] = cio_read(cio, 4);
1148         
1149   tk->depth = cio_read(cio, 2); /* Depth */
1150         
1151   /* Init std value */
1152   tk->num_jp2x = 0;
1153   tk->fieldcount = 1;
1154   tk->fieldorder = 0;
1155   tk->or_fieldcount = 1;
1156   tk->or_fieldorder = 0;
1157         
1158   cio_skip(cio,2);                      /* Pre-defined = -1 */
1159   memset(&color, 0, sizeof(opj_jp2_color_t));
1160   tk->jp2_struct.cinfo = tk->cinfo;
1161
1162   ok = jp2_read_jp2h(&tk->jp2_struct, cio, &color);
1163
1164   tk->jp2_struct.cinfo = NULL;
1165
1166   if(ok == OPJ_FALSE)
1167  {
1168         opj_event_msg(tk->cinfo, EVT_ERROR, "Error reading JP2H Box\n");
1169     return 1;
1170  }
1171
1172   tk->jp2_struct.comps = (opj_jp2_comps_t*) opj_malloc(tk->jp2_struct.numcomps * sizeof(opj_jp2_comps_t));
1173   tk->jp2_struct.cl = (unsigned int*) opj_malloc(sizeof(unsigned int));
1174
1175   tk->num_br = 0;
1176   tk->num_jp2x = 0;
1177         
1178   for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
1179     mj2_read_boxhdr(&box2, cio);
1180     cio_seek(cio, box2.init_pos);
1181     switch (box2.type) {
1182     case MJ2_FIEL:
1183       if (mj2_read_fiel(tk, cio))
1184                                 return 1;
1185       break;
1186                         
1187     case MJ2_JP2P:
1188       if (mj2_read_jp2p(tk, cio))
1189                                 return 1;
1190       break;
1191                         
1192     case MJ2_JP2X:
1193       if (mj2_read_jp2x(tk, cio))
1194                                 return 1;
1195       break;
1196                         
1197     case MJ2_JSUB:
1198       if (mj2_read_jsub(tk, cio))
1199                                 return 1;
1200       break;
1201                         
1202     case MJ2_ORFO:
1203       if (mj2_read_orfo(tk, cio))
1204                                 return 1;
1205       break;
1206                         
1207     default:
1208       opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MJP2 Box size\n");
1209       return 1;
1210       break;
1211                         
1212     }
1213   }
1214   return 0;
1215 }
1216
1217
1218 /*
1219 * Write the STSD box
1220 *
1221 * Sample Description
1222 *
1223 */
1224 void mj2_write_stsd(mj2_tk_t * tk, opj_cio_t *cio)
1225 {
1226   mj2_box_t box;
1227         
1228   box.init_pos = cio_tell(cio);
1229   cio_skip(cio,4);
1230   cio_write(cio, MJ2_STSD, 4);  /* STSD       */
1231         
1232   cio_write(cio, 0, 4);         /* Version = 0, flags = 0 */
1233         
1234   cio_write(cio, 1, 4);         /* entry_count = 1 (considering same JP2 headerboxes) */
1235         
1236   if (tk->track_type == 0) {
1237     mj2_write_smj2(tk, cio);
1238   } else if (tk->track_type == 1) {
1239     /* Not implemented*/
1240   }
1241   if (tk->track_type == 2) {
1242     /* Not implemented*/
1243   }
1244         
1245         
1246   box.length = cio_tell(cio) - box.init_pos;
1247   cio_seek(cio, box.init_pos);
1248   cio_write(cio, box.length, 4);        /* L          */
1249   cio_seek(cio, box.init_pos + box.length);
1250 }
1251
1252 /*
1253 * Read the STSD box
1254 *
1255 * Sample Description
1256 *
1257 */
1258 int mj2_read_stsd(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1259 {
1260   int i;
1261   int entry_count, len_2skip;
1262         
1263   mj2_box_t box;
1264         
1265   mj2_read_boxhdr(&box, cio);
1266         
1267   if (MJ2_STSD != box.type) {
1268     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STSD Marker\n");
1269     return 1;
1270   }
1271         
1272   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1273     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in STSD box\n");
1274     return 1;
1275   }
1276         
1277   if (0 != cio_read(cio, 3)) {  /* Flags = 0  */
1278     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in STSD box. Expected flag 0\n");
1279     return 1;
1280   }
1281         
1282   entry_count = cio_read(cio, 4);
1283         
1284   if (tk->track_type == 0) {
1285     for (i = 0; i < entry_count; i++) {
1286       if (mj2_read_smj2(img, tk, cio))
1287                                 return 1;
1288     }
1289   } else if (tk->track_type == 1) {
1290     len_2skip = cio_read(cio, 4);       /* Not implemented -> skipping box*/
1291     cio_skip(cio,len_2skip - 4);
1292   } else if (tk->track_type == 2) {
1293     len_2skip = cio_read(cio, 4);       /* Not implemented -> skipping box*/
1294     cio_skip(cio,len_2skip - 4);
1295   }
1296         
1297         
1298   if (cio_tell(cio) - box.init_pos != box.length) {
1299     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STSD Box size\n");
1300     return 1;
1301   }
1302   return 0;
1303 }
1304
1305 /*
1306 * Write the STBL box
1307 *
1308 * Sample table box box
1309 *
1310 */
1311 void mj2_write_stbl(mj2_tk_t * tk, opj_cio_t *cio)
1312 {
1313   mj2_box_t box;
1314         
1315   box.init_pos = cio_tell(cio);
1316   cio_skip(cio,4);
1317   cio_write(cio, MJ2_STBL, 4);  /* STBL       */
1318         
1319   mj2_write_stsd(tk, cio);
1320   mj2_write_stts(tk, cio);
1321   mj2_write_stsc(tk, cio);
1322   mj2_write_stsz(tk, cio);
1323   mj2_write_stco(tk, cio);
1324         
1325   box.length = cio_tell(cio) - box.init_pos;
1326   cio_seek(cio, box.init_pos);
1327   cio_write(cio, box.length, 4);        /* L          */
1328   cio_seek(cio, box.init_pos + box.length);
1329 }
1330
1331 /*
1332 * Read the STBL box
1333 *
1334 * Sample table box box
1335 *
1336 */
1337 int mj2_read_stbl(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1338 {
1339   mj2_box_t box;
1340         
1341   mj2_read_boxhdr(&box, cio);
1342   if (MJ2_STBL != box.type) {
1343     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected STBL Marker\n");
1344     return 1;
1345   }
1346         
1347   if (mj2_read_stsd(tk, img, cio))
1348     return 1;
1349   if (mj2_read_stts(tk, cio))
1350     return 1;
1351   if (mj2_read_stsc(tk, cio))
1352     return 1;
1353   if (mj2_read_stsz(tk, cio))
1354     return 1;
1355   if (mj2_read_stco(tk, cio))
1356     return 1;
1357         
1358   if (cio_tell(cio) - box.init_pos != box.length) {
1359     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with STBL Box size\n");
1360     return 1;
1361   }
1362   return 0;
1363 }
1364
1365 /*
1366 * Write the URL box
1367 *
1368 * URL box
1369 *
1370 */
1371 void mj2_write_url(mj2_tk_t * tk, int url_num, opj_cio_t *cio)
1372 {
1373   mj2_box_t box;
1374         
1375   box.init_pos = cio_tell(cio);
1376   cio_skip(cio,4);
1377   cio_write(cio, MJ2_URL, 4);   /* URL       */
1378         
1379   if (url_num == 0)
1380     cio_write(cio, 1, 4);               /* Version = 0, flags = 1 because stored in same file */
1381   else {
1382     cio_write(cio, 0, 4);               /* Version = 0, flags =  0 */
1383     cio_write(cio, tk->url[url_num - 1].location[0], 4);
1384     cio_write(cio, tk->url[url_num - 1].location[1], 4);
1385     cio_write(cio, tk->url[url_num - 1].location[2], 4);
1386     cio_write(cio, tk->url[url_num - 1].location[3], 4);
1387   }
1388         
1389   box.length = cio_tell(cio) - box.init_pos;
1390   cio_seek(cio, box.init_pos);
1391   cio_write(cio, box.length, 4);        /* L          */
1392   cio_seek(cio, box.init_pos + box.length);
1393 }
1394
1395 /*
1396 * Read the URL box
1397 *
1398 * URL box
1399 *
1400 */
1401 int mj2_read_url(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1402 {
1403   mj2_box_t box;
1404         
1405   mj2_read_boxhdr(&box, cio);
1406   if (MJ2_URL != box.type) {
1407     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URL Marker\n");
1408     return 1;
1409   }
1410         
1411   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1412     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URL box\n");
1413     return 1;
1414   }
1415         
1416   if (1 != cio_read(cio, 3)) {  /* If flags = 1 --> media data in file */
1417     tk->url[urn_num].location[0] = cio_read(cio, 4);
1418     tk->url[urn_num].location[1] = cio_read(cio, 4);
1419     tk->url[urn_num].location[2] = cio_read(cio, 4);
1420     tk->url[urn_num].location[3] = cio_read(cio, 4);
1421   } else {
1422     tk->num_url--;
1423   }
1424         
1425         
1426   if (cio_tell(cio) - box.init_pos != box.length) {
1427     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URL Box size\n");
1428     return 1;
1429   }
1430   return 0;
1431 }
1432
1433 /*
1434 * Write the URN box
1435 *
1436 * URN box
1437 *
1438 */
1439 void mj2_write_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1440 {
1441   mj2_box_t box;
1442         
1443   box.init_pos = cio_tell(cio);
1444   cio_skip(cio,4);
1445   cio_write(cio, MJ2_URN, 4);   /* URN       */
1446         
1447   cio_write(cio, 0, 4);         /* Version = 0, flags =  0 */
1448         
1449   cio_write(cio, tk->urn[urn_num].name[0], 4);
1450   cio_write(cio, tk->urn[urn_num].name[1], 4);
1451   cio_write(cio, tk->urn[urn_num].name[2], 4);
1452   cio_write(cio, tk->urn[urn_num].name[3], 4);
1453   cio_write(cio, tk->urn[urn_num].location[0], 4);
1454   cio_write(cio, tk->urn[urn_num].location[1], 4);
1455   cio_write(cio, tk->urn[urn_num].location[2], 4);
1456   cio_write(cio, tk->urn[urn_num].location[3], 4);
1457         
1458   box.length = cio_tell(cio) - box.init_pos;
1459   cio_seek(cio, box.init_pos);
1460   cio_write(cio, box.length, 4);        /* L          */
1461   cio_seek(cio, box.init_pos + box.length);
1462 }
1463
1464 /*
1465 * Read the URN box
1466 *
1467 * URN box
1468 *
1469 */
1470 int mj2_read_urn(mj2_tk_t * tk, int urn_num, opj_cio_t *cio)
1471 {
1472         
1473   mj2_box_t box;
1474         
1475   mj2_read_boxhdr(&box, cio);
1476   if (MJ2_URN != box.type) {
1477     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected URN Marker\n");
1478     return 1;
1479   }
1480         
1481   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1482     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in URN box\n");
1483     return 1;
1484   }
1485         
1486   if (1 != cio_read(cio, 3)) {  /* If flags = 1 --> media data in file */
1487     tk->urn[urn_num].name[0] = cio_read(cio, 4);
1488     tk->urn[urn_num].name[1] = cio_read(cio, 4);
1489     tk->urn[urn_num].name[2] = cio_read(cio, 4);
1490     tk->urn[urn_num].name[3] = cio_read(cio, 4);
1491     tk->urn[urn_num].location[0] = cio_read(cio, 4);
1492     tk->urn[urn_num].location[1] = cio_read(cio, 4);
1493     tk->urn[urn_num].location[2] = cio_read(cio, 4);
1494     tk->urn[urn_num].location[3] = cio_read(cio, 4);
1495   }
1496         
1497         
1498   if (cio_tell(cio) - box.init_pos != box.length) {
1499     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with URN Box size\n");
1500     return 1;
1501   }
1502   return 0;
1503 }
1504
1505
1506 /*
1507 * Write the DREF box
1508 *
1509 * Data reference box
1510 *
1511 */
1512 void mj2_write_dref(mj2_tk_t * tk, opj_cio_t *cio)
1513 {
1514   int i;
1515   mj2_box_t box;
1516         
1517   box.init_pos = cio_tell(cio);
1518   cio_skip(cio,4);
1519   cio_write(cio, MJ2_DREF, 4);  /* DREF       */
1520         
1521   cio_write(cio, 0, 4);         /* Version = 0, flags = 0 */
1522         
1523   if (tk->num_url + tk->num_urn == 0) { /* Media data in same file */
1524     cio_write(cio, 1, 4);               /* entry_count = 1 */
1525     mj2_write_url(tk, 0, cio);
1526   } else {
1527     cio_write(cio, tk->num_url + tk->num_urn, 4);       /* entry_count */
1528                 
1529     for (i = 0; i < tk->num_url; i++)
1530       mj2_write_url(tk, i + 1, cio);
1531                 
1532     for (i = 0; i < tk->num_urn; i++)
1533       mj2_write_urn(tk, i, cio);
1534   }
1535         
1536   box.length = cio_tell(cio) - box.init_pos;
1537   cio_seek(cio, box.init_pos);
1538   cio_write(cio, box.length, 4);        /* L          */
1539   cio_seek(cio, box.init_pos + box.length);
1540 }
1541
1542 /*
1543 * Read the DREF box
1544 *
1545 * Data reference box
1546 *
1547 */
1548 int mj2_read_dref(mj2_tk_t * tk, opj_cio_t *cio)
1549 {
1550         
1551   int i;
1552   int entry_count, marker;
1553   mj2_box_t box;
1554         
1555   mj2_read_boxhdr(&box, cio);
1556   if (MJ2_DREF != box.type) {
1557     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DREF Marker\n");
1558     return 1;
1559   }
1560         
1561   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1562     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in DREF box\n");
1563     return 1;
1564   }
1565         
1566   if (0 != cio_read(cio, 3)) {  /* Flags = 0  */
1567     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in DREF box. Expected flag 0\n");
1568     return 1;
1569   }
1570         
1571   entry_count = cio_read(cio, 4);
1572   tk->num_url = 0;
1573   tk->num_urn = 0;
1574         
1575   for (i = 0; i < entry_count; i++) {
1576     cio_skip(cio,4);
1577     marker = cio_read(cio, 4);
1578     if (marker == MJ2_URL) {
1579       cio_skip(cio,-8);
1580       tk->num_url++;
1581       if (mj2_read_url(tk, tk->num_url, cio))
1582                                 return 1;
1583     } else if (marker == MJ2_URN) {
1584       cio_skip(cio,-8);
1585       tk->num_urn++;
1586       if (mj2_read_urn(tk, tk->num_urn, cio))
1587                                 return 1;
1588     } else {
1589       opj_event_msg(cio->cinfo, EVT_ERROR, "Error with in DREF box. Expected URN or URL box\n");
1590       return 1;
1591     }
1592                 
1593   }
1594         
1595         
1596   if (cio_tell(cio) - box.init_pos != box.length) {
1597     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DREF Box size\n");
1598     return 1;
1599   }
1600   return 0;
1601 }
1602
1603 /*
1604 * Write the DINF box
1605 *
1606 * Data information box
1607 *
1608 */
1609 void mj2_write_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1610 {
1611   mj2_box_t box;
1612         
1613   box.init_pos = cio_tell(cio);
1614   cio_skip(cio,4);
1615   cio_write(cio, MJ2_DINF, 4);  /* DINF       */
1616         
1617   mj2_write_dref(tk, cio);
1618         
1619   box.length = cio_tell(cio) - box.init_pos;
1620   cio_seek(cio, box.init_pos);
1621   cio_write(cio, box.length, 4);        /* L          */
1622   cio_seek(cio, box.init_pos + box.length);
1623 }
1624
1625 /*
1626 * Read the DINF box
1627 *
1628 * Data information box
1629 *
1630 */
1631 int mj2_read_dinf(mj2_tk_t * tk, opj_cio_t *cio)
1632 {
1633   mj2_box_t box;
1634         
1635   mj2_read_boxhdr(&box, cio);
1636   if (MJ2_DINF != box.type) {
1637     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected DINF Marker\n");
1638     return 1;
1639   }
1640         
1641   if (mj2_read_dref(tk, cio))
1642     return 1;
1643         
1644   if (cio_tell(cio) - box.init_pos != box.length) {
1645     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with DINF Box size\n");
1646     return 1;
1647   }
1648   return 0;
1649 }
1650
1651 /*
1652 * Write the VMHD box
1653 *
1654 * Video Media information box
1655 *
1656 */
1657 void mj2_write_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1658 {
1659   mj2_box_t box;
1660         
1661   box.init_pos = cio_tell(cio);
1662   cio_skip(cio,4);
1663   cio_write(cio, MJ2_VMHD, 4);  /* VMHD       */
1664         
1665   cio_write(cio, 1, 4);         /* Version = 0, flags = 1 */
1666         
1667   cio_write(cio, tk->graphicsmode, 2);
1668   cio_write(cio, tk->opcolor[0], 2);
1669   cio_write(cio, tk->opcolor[1], 2);
1670   cio_write(cio, tk->opcolor[2], 2);
1671         
1672   box.length = cio_tell(cio) - box.init_pos;
1673   cio_seek(cio, box.init_pos);
1674   cio_write(cio, box.length, 4);        /* L          */
1675   cio_seek(cio, box.init_pos + box.length);
1676 }
1677
1678 /*
1679 * Read the VMHD box
1680 *
1681 * Video Media information box
1682 *
1683 */
1684 int mj2_read_vmhd(mj2_tk_t * tk, opj_cio_t *cio)
1685 {
1686   mj2_box_t box;
1687         
1688   mj2_read_boxhdr(&box, cio);
1689   if (MJ2_VMHD != box.type) {
1690     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected VMHD Marker\n");
1691     return 1;
1692   }
1693         
1694   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1695     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in VMHD box\n");
1696     return 1;
1697   }
1698         
1699   if (1 != cio_read(cio, 3)) {  /* Flags = 1  */
1700     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in VMHD box. Expected flag 1\n");
1701     return 1;
1702   }
1703         
1704   tk->track_type = 0;
1705   tk->graphicsmode = cio_read(cio, 2);
1706   tk->opcolor[0] = cio_read(cio, 2);
1707   tk->opcolor[1] = cio_read(cio, 2);
1708   tk->opcolor[2] = cio_read(cio, 2);
1709         
1710   if (cio_tell(cio) - box.init_pos != box.length) {
1711     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with VMHD Box size\n");
1712     return 1;
1713   }
1714   return 0;
1715 }
1716
1717 /*
1718 * Write the SMHD box
1719 *
1720 * Sound Media information box
1721 *
1722 */
1723 void mj2_write_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1724 {
1725   mj2_box_t box;
1726         
1727   box.init_pos = cio_tell(cio);
1728   cio_skip(cio,4);
1729   cio_write(cio, MJ2_SMHD, 4);  /* SMHD       */
1730         
1731   cio_write(cio, 0, 4);         /* Version = 0, flags = 0 */
1732         
1733   cio_write(cio, tk->balance, 2);
1734         
1735   cio_write(cio, 0, 2);         /* Reserved */
1736         
1737   box.length = cio_tell(cio) - box.init_pos;
1738   cio_seek(cio, box.init_pos);
1739   cio_write(cio, box.length, 4);        /* L          */
1740   cio_seek(cio, box.init_pos + box.length);
1741 }
1742
1743 /*
1744 * Read the SMHD box
1745 *
1746 * Sound Media information box
1747 *
1748 */
1749 int mj2_read_smhd(mj2_tk_t * tk, opj_cio_t *cio)
1750 {
1751   mj2_box_t box;
1752         
1753   mj2_read_boxhdr(&box, cio);
1754   if (MJ2_SMHD != box.type) {
1755     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected SMHD Marker\n");
1756     return 1;
1757   }
1758         
1759   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1760     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in SMHD box\n");
1761     return 1;
1762   }
1763         
1764   if (0 != cio_read(cio, 3)) {  /* Flags = 0  */
1765     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in SMHD box. Expected flag 0\n");
1766     return 1;
1767   }
1768         
1769   tk->track_type = 1;
1770   tk->balance = cio_read(cio, 2);
1771         
1772   /* Init variables to zero to avoid problems when freeeing memory
1773   The values will possibly be overidded when decoding the track structure */
1774   tk->num_br = 0;
1775   tk->num_url = 0;
1776   tk->num_urn = 0;
1777   tk->num_chunks = 0;
1778   tk->num_tts = 0;
1779   tk->num_samplestochunk = 0;
1780   tk->num_samples = 0;
1781         
1782   cio_skip(cio,2);                      /* Reserved */
1783         
1784   if (cio_tell(cio) - box.init_pos != box.length) {
1785     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with SMHD Box size\n");
1786     return 1;
1787   }
1788   return 0;
1789 }
1790
1791 /*
1792 * Write the HMHD box
1793 *
1794 * Hint Media information box
1795 *
1796 */
1797 void mj2_write_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1798 {
1799   mj2_box_t box;
1800         
1801   box.init_pos = cio_tell(cio);
1802   cio_skip(cio,4);
1803   cio_write(cio, MJ2_HMHD, 4);  /* HMHD       */
1804         
1805   cio_write(cio, 0, 4);         /* Version = 0, flags = 0 */
1806         
1807   cio_write(cio, tk->maxPDUsize, 2);
1808   cio_write(cio, tk->avgPDUsize, 2);
1809   cio_write(cio, tk->maxbitrate, 4);
1810   cio_write(cio, tk->avgbitrate, 4);
1811   cio_write(cio, tk->slidingavgbitrate, 4);
1812         
1813   box.length = cio_tell(cio) - box.init_pos;
1814   cio_seek(cio, box.init_pos);
1815   cio_write(cio, box.length, 4);        /* L          */
1816   cio_seek(cio, box.init_pos + box.length);
1817 }
1818
1819 /*
1820 * Read the HMHD box
1821 *
1822 * Hint Media information box
1823 *
1824 */
1825 int mj2_read_hmhd(mj2_tk_t * tk, opj_cio_t *cio)
1826 {
1827   mj2_box_t box;
1828         
1829   mj2_read_boxhdr(&box, cio);
1830   if (MJ2_HMHD != box.type) {
1831     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HMHD Marker\n");
1832     return 1;
1833   }
1834         
1835   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
1836     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HMHD box\n");
1837     return 1;
1838   }
1839         
1840   if (0 != cio_read(cio, 3)) {  /* Flags = 0  */
1841     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HMHD box. Expected flag 0\n");
1842     return 1;
1843   }
1844         
1845   tk->track_type = 2;
1846   tk->maxPDUsize = cio_read(cio, 2);
1847   tk->avgPDUsize = cio_read(cio, 2);
1848   tk->maxbitrate = cio_read(cio, 4);
1849   tk->avgbitrate = cio_read(cio, 4);
1850   tk->slidingavgbitrate = cio_read(cio, 4);
1851         
1852   /* Init variables to zero to avoid problems when freeeing memory
1853   The values will possibly be overidded when decoding the track structure */
1854   tk->num_br = 0;
1855   tk->num_url = 0;
1856   tk->num_urn = 0;
1857   tk->num_chunks = 0;
1858   tk->num_tts = 0;
1859   tk->num_samplestochunk = 0;
1860   tk->num_samples = 0;
1861         
1862         
1863   if (cio_tell(cio) - box.init_pos != box.length) {
1864     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HMHD Box size\n");
1865     return 1;
1866   }
1867   return 0;
1868 }
1869
1870 /*
1871 * Write the MINF box
1872 *
1873 * Media information box
1874 *
1875 */
1876 void mj2_write_minf(mj2_tk_t * tk, opj_cio_t *cio)
1877 {
1878   mj2_box_t box;
1879         
1880   box.init_pos = cio_tell(cio);
1881   cio_skip(cio,4);
1882   cio_write(cio, MJ2_MINF, 4);  /* MINF       */
1883         
1884   if (tk->track_type == 0) {
1885     mj2_write_vmhd(tk, cio);
1886   } else if (tk->track_type == 1) {
1887     mj2_write_smhd(tk, cio);
1888   } else if (tk->track_type == 2) {
1889     mj2_write_hmhd(tk, cio);
1890   }
1891         
1892   mj2_write_dinf(tk, cio);
1893   mj2_write_stbl(tk, cio);
1894         
1895   box.length = cio_tell(cio) - box.init_pos;
1896   cio_seek(cio, box.init_pos);
1897   cio_write(cio, box.length, 4);        /* L          */
1898   cio_seek(cio, box.init_pos + box.length);
1899 }
1900
1901 /*
1902 * Read the MINF box
1903 *
1904 * Media information box
1905 *
1906 */
1907 int mj2_read_minf(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
1908 {
1909         
1910   unsigned int box_type;
1911   mj2_box_t box;
1912         
1913   mj2_read_boxhdr(&box, cio);
1914   if (MJ2_MINF != box.type) {
1915     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MINF Marker\n");
1916     return 1;
1917   }
1918         
1919   cio_skip(cio,4);
1920   box_type = cio_read(cio, 4);
1921   cio_skip(cio,-8);
1922         
1923   if (box_type == MJ2_VMHD) {
1924     if (mj2_read_vmhd(tk, cio))
1925       return 1;
1926   } else if (box_type == MJ2_SMHD) {
1927     if (mj2_read_smhd(tk, cio))
1928       return 1;
1929   } else if (box_type == MJ2_HMHD) {
1930     if (mj2_read_hmhd(tk, cio))
1931       return 1;
1932   } else {
1933     opj_event_msg(cio->cinfo, EVT_ERROR, "Error in MINF box expected vmhd, smhd or hmhd\n");
1934     return 1;
1935   }
1936         
1937   if (mj2_read_dinf(tk, cio))
1938     return 1;
1939         
1940   if (mj2_read_stbl(tk, img, cio))
1941     return 1;
1942         
1943   if (cio_tell(cio) - box.init_pos != box.length) {
1944     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MINF Box size\n");
1945     return 1;
1946   }
1947   return 0;
1948 }
1949
1950 /*
1951 * Write the HDLR box
1952 *
1953 * Handler reference box
1954 *
1955 */
1956 void mj2_write_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
1957 {
1958   mj2_box_t box;
1959         
1960   box.init_pos = cio_tell(cio);
1961   cio_skip(cio,4);
1962   cio_write(cio, MJ2_HDLR, 4);  /* HDLR       */
1963         
1964   cio_write(cio, 0, 4);         /* Version = 0, flags = 0 */
1965         
1966   cio_write(cio, 0, 4);         /* Predefine */
1967         
1968   tk->name = 0;                 /* The track name is immediately determined by the track type */
1969         
1970   if (tk->track_type == 0) {
1971     tk->handler_type = 0x76696465;      /* Handler type: vide */
1972     cio_write(cio, tk->handler_type, 4);
1973                 
1974     cio_write(cio, 0, 4);
1975     cio_write(cio, 0, 4);
1976     cio_write(cio, 0, 4);               /* Reserved */
1977                 
1978     cio_write(cio, 0x76696465, 4);
1979     cio_write(cio, 0x6F206d65, 4);
1980     cio_write(cio, 0x64696120, 4);
1981     cio_write(cio, 0x74726163, 4);
1982     cio_write(cio, 0x6b00, 2);  /* String: video media track */
1983   } else if (tk->track_type == 1) {
1984     tk->handler_type = 0x736F756E;      /* Handler type: soun */
1985     cio_write(cio, tk->handler_type, 4);
1986                 
1987     cio_write(cio, 0, 4);
1988     cio_write(cio, 0, 4);
1989     cio_write(cio, 0, 4);               /* Reserved */
1990                 
1991     cio_write(cio, 0x536F756E, 4);
1992     cio_write(cio, 0x6400, 2);  /* String: Sound */
1993   } else if (tk->track_type == 2) {
1994     tk->handler_type = 0x68696E74;      /* Handler type: hint */
1995     cio_write(cio, tk->handler_type, 4);
1996                 
1997     cio_write(cio, 0, 4);
1998     cio_write(cio, 0, 4);
1999     cio_write(cio, 0, 4);               /* Reserved */
2000                 
2001     cio_write(cio, 0x48696E74, 4);
2002     cio_write(cio, 0, 2);               /* String: Hint */
2003   }
2004         
2005   box.length = cio_tell(cio) - box.init_pos;
2006   cio_seek(cio, box.init_pos);
2007   cio_write(cio, box.length, 4);        /* L          */
2008   cio_seek(cio, box.init_pos + box.length);
2009 }
2010
2011 /*
2012 * Read the HDLR box
2013 *
2014 * Handler reference box
2015 *
2016 */
2017 int mj2_read_hdlr(mj2_tk_t * tk, opj_cio_t *cio)
2018 {
2019   int i;
2020   mj2_box_t box;
2021         
2022   mj2_read_boxhdr(&box, cio);
2023   if (MJ2_HDLR != box.type) {
2024     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected HDLR Marker\n");
2025     return 1;
2026   }
2027         
2028         
2029   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
2030     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in HDLR box\n");
2031     return 1;
2032   }
2033         
2034   if (0 != cio_read(cio, 3)) {  /* Flags = 0  */
2035     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in HDLR box. Expected flag 0\n");
2036     return 1;
2037   }
2038         
2039   cio_skip(cio,4);                      /* Reserved */
2040         
2041   tk->handler_type = cio_read(cio, 4);
2042   cio_skip(cio,12);                     /* Reserved */
2043         
2044   tk->name_size = box.length - 32;
2045
2046   tk->name = (char*) opj_malloc(tk->name_size * sizeof(char));
2047   for (i = 0; i < tk->name_size; i++) {
2048     tk->name[i] = cio_read(cio, 1);     /* Name */
2049   }
2050         
2051   if (cio_tell(cio) - box.init_pos != box.length) {
2052     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with HDLR Box size\n");
2053     return 1;
2054   }
2055   return 0;
2056 }
2057
2058 /*
2059 * Write the MDHD box
2060 *
2061 * Media Header Box
2062 *
2063 */
2064 void mj2_write_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2065 {
2066   mj2_box_t box;
2067   unsigned int i;
2068   time_t ltime;
2069   unsigned int modification_time;
2070         
2071   box.init_pos = cio_tell(cio);
2072   cio_skip(cio,4);
2073   cio_write(cio, MJ2_MDHD, 4);  /* MDHD       */
2074         
2075   cio_write(cio, 0, 4);         /* Version = 0, flags = 0 */
2076         
2077   cio_write(cio, tk->creation_time, 4); /* Creation Time */
2078         
2079   time(&ltime);                 /* Time since 1/1/70 */
2080   modification_time = (unsigned int)ltime + 2082844800; /* Seoonds between 1/1/04 and 1/1/70 */
2081         
2082   cio_write(cio, modification_time, 4); /* Modification Time */
2083         
2084   cio_write(cio, tk->timescale, 4);     /* Timescale */
2085         
2086   tk->duration = 0;
2087         
2088   for (i = 0; i < tk->num_samples; i++)
2089     tk->duration += tk->sample[i].sample_delta;
2090         
2091   cio_write(cio, tk->duration, 4);      /* Duration */
2092         
2093   cio_write(cio, tk->language, 2);      /* Language */
2094         
2095   cio_write(cio, 0, 2);         /* Predefined */
2096         
2097   box.length = cio_tell(cio) - box.init_pos;
2098   cio_seek(cio, box.init_pos);
2099   cio_write(cio, box.length, 4);        /* L          */
2100   cio_seek(cio, box.init_pos + box.length);
2101 }
2102
2103 /*
2104 * Read the MDHD box
2105 *
2106 * Media Header Box
2107 *
2108 */
2109 int mj2_read_mdhd(mj2_tk_t * tk, opj_cio_t *cio)
2110 {
2111   mj2_box_t box;
2112         
2113   mj2_read_boxhdr(&box, cio);
2114   if (!(MJ2_MHDR == box.type || MJ2_MDHD == box.type)) {        /* Kakadu writes MHDR instead of MDHD*/
2115     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDHD Marker\n");
2116     return 1;
2117   }
2118         
2119   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
2120     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MDHD box\n");
2121     return 1;
2122   }
2123         
2124   if (0 != cio_read(cio, 3)) {  /* Flags = 0 */
2125     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with flag in MDHD box. Expected flag 0\n");
2126     return 1;
2127   }
2128         
2129         
2130   tk->creation_time = cio_read(cio, 4); /* Creation Time */
2131         
2132   tk->modification_time = cio_read(cio, 4);     /* Modification Time */
2133         
2134   tk->timescale = cio_read(cio, 4);     /* Timescale */
2135         
2136   tk->duration = cio_read(cio, 4);      /* Duration */
2137         
2138   tk->language = cio_read(cio, 2);      /* Language */
2139         
2140   cio_skip(cio,2);                      /* Predefined */
2141         
2142   if (cio_tell(cio) - box.init_pos != box.length) {
2143     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDHD Box size\n");
2144     return 1;
2145   }
2146   return 0;
2147 }
2148
2149 /*
2150 * Write the MDIA box
2151 *
2152 * Media box
2153 *
2154 */
2155 void mj2_write_mdia(mj2_tk_t * tk, opj_cio_t *cio)
2156 {
2157   mj2_box_t box;
2158         
2159   box.init_pos = cio_tell(cio);
2160   cio_skip(cio,4);
2161   cio_write(cio, MJ2_MDIA, 4);  /* MDIA       */
2162         
2163   mj2_write_mdhd(tk, cio);
2164   mj2_write_hdlr(tk, cio);
2165   mj2_write_minf(tk, cio);
2166         
2167   box.length = cio_tell(cio) - box.init_pos;
2168   cio_seek(cio, box.init_pos);
2169   cio_write(cio, box.length, 4);        /* L          */
2170   cio_seek(cio, box.init_pos + box.length);
2171 }
2172
2173 /*
2174 * Read the MDIA box
2175 *
2176 * Media box
2177 *
2178 */
2179 int mj2_read_mdia(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2180 {
2181   mj2_box_t box;
2182         
2183   mj2_read_boxhdr(&box, cio);
2184   if (MJ2_MDIA != box.type) {
2185     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MDIA Marker\n");
2186     return 1;
2187   }
2188         
2189   if (mj2_read_mdhd(tk, cio))
2190     return 1;
2191   if (mj2_read_hdlr(tk, cio))
2192     return 1;
2193   if (mj2_read_minf(tk, img, cio))
2194     return 1;
2195         
2196   if (cio_tell(cio) - box.init_pos != box.length) {
2197     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MDIA Box size\n");
2198     return 1;
2199   }
2200   return 0;
2201 }
2202
2203 /*
2204 * Write the TKHD box
2205 *
2206 * Track Header box
2207 *
2208 */
2209 void mj2_write_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2210 {
2211   mj2_box_t box;
2212   unsigned int i;
2213   time_t ltime;
2214         
2215   box.init_pos = cio_tell(cio);
2216   cio_skip(cio,4);
2217         
2218   cio_write(cio, MJ2_TKHD, 4);  /* TKHD       */
2219         
2220   cio_write(cio, 3, 4);         /* Version=0, flags=3 */
2221         
2222   time(&ltime);                 /* Time since 1/1/70 */
2223   tk->modification_time = (unsigned int)ltime + 2082844800;     /* Seoonds between 1/1/04 and 1/1/70 */
2224         
2225   cio_write(cio, tk->creation_time, 4); /* Creation Time */
2226         
2227   cio_write(cio, tk->modification_time, 4);     /* Modification Time */
2228         
2229   cio_write(cio, tk->track_ID, 4);      /* Track ID */
2230         
2231   cio_write(cio, 0, 4);         /* Reserved */
2232         
2233   tk->duration = 0;
2234         
2235   for (i = 0; i < tk->num_samples; i++)
2236     tk->duration += tk->sample[i].sample_delta;
2237         
2238   cio_write(cio, tk->duration, 4);      /* Duration */
2239         
2240   cio_write(cio, 0, 4);         /* Reserved */
2241   cio_write(cio, 0, 4);         /* Reserved */
2242         
2243   cio_write(cio, tk->layer, 2); /* Layer    */
2244         
2245   cio_write(cio, 0, 2);         /* Predefined */
2246         
2247   cio_write(cio, tk->volume, 2);        /* Volume       */
2248         
2249   cio_write(cio, 0, 2);         /* Reserved */
2250         
2251   cio_write(cio, tk->trans_matrix[0], 4);       /* Transformation matrix for track */
2252   cio_write(cio, tk->trans_matrix[1], 4);
2253   cio_write(cio, tk->trans_matrix[2], 4);
2254   cio_write(cio, tk->trans_matrix[3], 4);
2255   cio_write(cio, tk->trans_matrix[4], 4);
2256   cio_write(cio, tk->trans_matrix[5], 4);
2257   cio_write(cio, tk->trans_matrix[6], 4);
2258   cio_write(cio, tk->trans_matrix[7], 4);
2259   cio_write(cio, tk->trans_matrix[8], 4);
2260         
2261   cio_write(cio, tk->visual_w, 4);      /* Video Visual Width  */
2262         
2263   cio_write(cio, tk->visual_h, 4);      /* Video Visual Height */
2264         
2265   box.length = cio_tell(cio) - box.init_pos;
2266   cio_seek(cio, box.init_pos);
2267   cio_write(cio, box.length, 4);        /* L          */
2268   cio_seek(cio, box.init_pos + box.length);
2269 }
2270
2271 /*
2272 * Read the TKHD box
2273 *
2274 * Track Header box
2275 *
2276 */
2277 int mj2_read_tkhd(mj2_tk_t * tk, opj_cio_t *cio)
2278 {
2279   int flag;
2280         
2281   mj2_box_t box;
2282         
2283   mj2_read_boxhdr(&box, cio);
2284         
2285   if (MJ2_TKHD != box.type) {
2286     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TKHD Marker\n");
2287     return 1;
2288   }
2289         
2290   if (0 != cio_read(cio, 1)) {  /* Version = 0 */
2291     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in TKHD box\n");
2292     return 1;
2293   }
2294         
2295   flag = cio_read(cio, 3);
2296         
2297   if (!(flag == 1 || flag == 2 || flag == 3 || flag == 4)) {    /* Flags = 1,2,3 or 4 */
2298     opj_event_msg(cio->cinfo, EVT_ERROR,
2299                         "Error with flag in TKHD box: Expected flag 1,2,3 or 4\n");
2300     return 1;
2301   }
2302         
2303   tk->creation_time = cio_read(cio, 4); /* Creation Time */
2304         
2305   tk->modification_time = cio_read(cio, 4);     /* Modification Time */
2306         
2307   tk->track_ID = cio_read(cio, 4);      /* Track ID */
2308         
2309   cio_skip(cio,4);                      /* Reserved */
2310         
2311   tk->duration = cio_read(cio, 4);      /* Duration */
2312         
2313   cio_skip(cio,8);                      /* Reserved */
2314         
2315   tk->layer = cio_read(cio, 2); /* Layer    */
2316         
2317   cio_read(cio, 2);                     /* Predefined */
2318         
2319   tk->volume = cio_read(cio, 2);        /* Volume       */
2320         
2321   cio_skip(cio,2);                      /* Reserved */
2322         
2323   tk->trans_matrix[0] = cio_read(cio, 4);       /* Transformation matrix for track */
2324   tk->trans_matrix[1] = cio_read(cio, 4);
2325   tk->trans_matrix[2] = cio_read(cio, 4);
2326   tk->trans_matrix[3] = cio_read(cio, 4);
2327   tk->trans_matrix[4] = cio_read(cio, 4);
2328   tk->trans_matrix[5] = cio_read(cio, 4);
2329   tk->trans_matrix[6] = cio_read(cio, 4);
2330   tk->trans_matrix[7] = cio_read(cio, 4);
2331   tk->trans_matrix[8] = cio_read(cio, 4);
2332         
2333   tk->visual_w = cio_read(cio, 4);      /* Video Visual Width  */
2334         
2335   tk->visual_h = cio_read(cio, 4);      /* Video Visual Height */
2336         
2337   if (cio_tell(cio) - box.init_pos != box.length) {
2338     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TKHD Box size\n");
2339     return 1;
2340   }
2341   return 0;
2342 }
2343
2344 /*
2345 * Write the TRAK box
2346 *
2347 * Track box
2348 *
2349 */
2350 void mj2_write_trak(mj2_tk_t * tk, opj_cio_t *cio)
2351 {
2352   mj2_box_t box;
2353         
2354   box.init_pos = cio_tell(cio);
2355   cio_skip(cio,4);
2356         
2357   cio_write(cio, MJ2_TRAK, 4);  /* TRAK       */
2358         
2359   mj2_write_tkhd(tk, cio);
2360   mj2_write_mdia(tk, cio);
2361         
2362   box.length = cio_tell(cio) - box.init_pos;
2363   cio_seek(cio, box.init_pos);
2364   cio_write(cio, box.length, 4);        /* L          */
2365   cio_seek(cio, box.init_pos + box.length);
2366 }
2367
2368 /*
2369 * Read the TRAK box
2370 *
2371 * Track box
2372 *
2373 */
2374 int mj2_read_trak(mj2_tk_t * tk, opj_image_t * img, opj_cio_t *cio)
2375 {
2376   mj2_box_t box;
2377         
2378   mj2_read_boxhdr(&box, cio);
2379   if (MJ2_TRAK != box.type) {
2380     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected TRAK Marker\n");
2381     return 1;
2382   }
2383   if (mj2_read_tkhd(tk, cio))
2384     return 1;
2385   if (mj2_read_mdia(tk, img, cio))
2386     return 1;
2387   if (cio_tell(cio) - box.init_pos != box.length) {
2388     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with TRAK Box\n");
2389     return 1;
2390   }
2391   return 0;
2392 }
2393
2394 /*
2395 * Write the MVHD box
2396 *
2397 * Movie header Box
2398 *
2399 */
2400 void mj2_write_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2401 {
2402   int i;
2403   mj2_box_t box;
2404   unsigned j;
2405   time_t ltime;
2406   int max_tk_num = 0;
2407         
2408   box.init_pos = cio_tell(cio);
2409   cio_skip(cio,4);
2410   cio_write(cio, MJ2_MVHD, 4);  /* MVHD       */
2411         
2412   cio_write(cio, 0, 4);         /* Version = 0, flags = 0 */
2413         
2414   time(&ltime);                 /* Time since 1/1/70 */
2415   movie->modification_time = (unsigned int)ltime + 2082844800;  /* Seoonds between 1/1/04 and 1/1/70 */
2416         
2417   cio_write(cio, movie->creation_time, 4);      /* Creation Time */
2418         
2419   cio_write(cio, movie->modification_time, 4);  /* Modification Time */
2420         
2421   cio_write(cio, movie->timescale, 4);  /* Timescale */
2422         
2423   movie->duration = 0;
2424         
2425   for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2426     mj2_tk_t *tk = &movie->tk[i];
2427                 
2428     for (j = 0; j < tk->num_samples; j++) {
2429       movie->duration += tk->sample[j].sample_delta;
2430     }
2431   }
2432         
2433   cio_write(cio, movie->duration, 4);
2434         
2435   cio_write(cio, movie->rate, 4);       /* Rate to play presentation    */
2436         
2437   cio_write(cio, movie->volume, 2);     /* Volume       */
2438         
2439   cio_write(cio, 0, 2);         /* Reserved */
2440   cio_write(cio, 0, 4);         /* Reserved */
2441   cio_write(cio, 0, 4);         /* Reserved */
2442         
2443   cio_write(cio, movie->trans_matrix[0], 4);    /* Transformation matrix for video */
2444   cio_write(cio, movie->trans_matrix[1], 4);
2445   cio_write(cio, movie->trans_matrix[2], 4);
2446   cio_write(cio, movie->trans_matrix[3], 4);
2447   cio_write(cio, movie->trans_matrix[4], 4);
2448   cio_write(cio, movie->trans_matrix[5], 4);
2449   cio_write(cio, movie->trans_matrix[6], 4);
2450   cio_write(cio, movie->trans_matrix[7], 4);
2451   cio_write(cio, movie->trans_matrix[8], 4);
2452         
2453   cio_write(cio, 0, 4);         /* Pre-defined */
2454   cio_write(cio, 0, 4);         /* Pre-defined */
2455   cio_write(cio, 0, 4);         /* Pre-defined */
2456   cio_write(cio, 0, 4);         /* Pre-defined */
2457   cio_write(cio, 0, 4);         /* Pre-defined */
2458   cio_write(cio, 0, 4);         /* Pre-defined */
2459         
2460         
2461   for (i = 0; i < movie->num_htk + movie->num_stk + movie->num_vtk; i++) {
2462     if (max_tk_num < movie->tk[i].track_ID)
2463       max_tk_num = movie->tk[i].track_ID;
2464   }
2465         
2466   movie->next_tk_id = max_tk_num + 1;
2467         
2468   cio_write(cio, movie->next_tk_id, 4); /* ID of Next track to be added */
2469         
2470   box.length = cio_tell(cio) - box.init_pos;
2471   cio_seek(cio, box.init_pos);
2472   cio_write(cio, box.length, 4);        /* L          */
2473   cio_seek(cio, box.init_pos + box.length);
2474 }
2475
2476 /*
2477 * Read the MVHD box
2478 *
2479 * Movie header Box
2480 *
2481 */
2482 int mj2_read_mvhd(opj_mj2_t * movie, opj_cio_t *cio)
2483 {
2484   mj2_box_t box;
2485         
2486   mj2_read_boxhdr(&box, cio);
2487   if (MJ2_MVHD != box.type) {
2488     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MVHD Marker\n");
2489     return 1;
2490   }
2491         
2492         
2493   if (0 != cio_read(cio, 4)) {  /* Version = 0, flags = 0 */
2494     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Only Version 0 handled in MVHD box\n");
2495   }
2496         
2497   movie->creation_time = cio_read(cio, 4);      /* Creation Time */
2498         
2499   movie->modification_time = cio_read(cio, 4);  /* Modification Time */
2500         
2501   movie->timescale = cio_read(cio, 4);  /* Timescale */
2502         
2503   movie->duration = cio_read(cio, 4);   /* Duration */
2504         
2505   movie->rate = cio_read(cio, 4);               /* Rate to play presentation    */
2506         
2507   movie->volume = cio_read(cio, 2);             /* Volume       */
2508         
2509   cio_skip(cio,10);                             /* Reserved */
2510         
2511   movie->trans_matrix[0] = cio_read(cio, 4);    /* Transformation matrix for video */
2512   movie->trans_matrix[1] = cio_read(cio, 4);
2513   movie->trans_matrix[2] = cio_read(cio, 4);
2514   movie->trans_matrix[3] = cio_read(cio, 4);
2515   movie->trans_matrix[4] = cio_read(cio, 4);
2516   movie->trans_matrix[5] = cio_read(cio, 4);
2517   movie->trans_matrix[6] = cio_read(cio, 4);
2518   movie->trans_matrix[7] = cio_read(cio, 4);
2519   movie->trans_matrix[8] = cio_read(cio, 4);
2520         
2521   cio_skip(cio,24);                     /* Pre-defined */
2522         
2523   movie->next_tk_id = cio_read(cio, 4); /* ID of Next track to be added */
2524         
2525   if (cio_tell(cio) - box.init_pos != box.length) {
2526     opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MVHD Box Size\n");
2527     return 1;
2528   }
2529   return 0;
2530 }
2531
2532
2533 /*
2534 * Write the MOOV box
2535 *
2536 * Movie Box
2537 *
2538 */
2539 void mj2_write_moov(opj_mj2_t * movie, opj_cio_t *cio)
2540 {
2541   int i;
2542   mj2_box_t box;
2543         
2544   box.init_pos = cio_tell(cio);
2545   cio_skip(cio,4);
2546   cio_write(cio, MJ2_MOOV, 4);  /* MOOV       */
2547         
2548   mj2_write_mvhd(movie, cio);
2549         
2550   for (i = 0; i < (movie->num_stk + movie->num_htk + movie->num_vtk); i++) {
2551     mj2_write_trak(&movie->tk[i], cio);
2552   }
2553         
2554   box.length = cio_tell(cio) - box.init_pos;
2555   cio_seek(cio, box.init_pos);
2556   cio_write(cio, box.length, 4);        /* L          */
2557   cio_seek(cio, box.init_pos + box.length);     
2558 }
2559
2560 /*
2561 * Read the MOOV box
2562 *
2563 * Movie Box
2564 *
2565 */
2566 int mj2_read_moov(opj_mj2_t * movie, opj_image_t * img, opj_cio_t *cio)
2567 {
2568   unsigned int i;
2569   mj2_box_t box;
2570   mj2_box_t box2;
2571         
2572   mj2_read_boxhdr(&box, cio);
2573   if (MJ2_MOOV != box.type) {
2574     opj_event_msg(cio->cinfo, EVT_ERROR, "Error: Expected MOOV Marker\n");
2575     return 1;
2576   }
2577         
2578   if (mj2_read_mvhd(movie, cio))
2579     return 1;
2580
2581   movie->tk = (mj2_tk_t*) opj_malloc((movie->next_tk_id - 1) * sizeof(mj2_tk_t));
2582
2583   for (i = 0; cio_tell(cio) - box.init_pos < box.length; i++) {
2584                 mj2_tk_t *tk = &movie->tk[i];
2585                 tk->cinfo = movie->cinfo;
2586     mj2_read_boxhdr(&box2, cio);
2587     if (box2.type == MJ2_TRAK) {
2588       cio_seek(cio, box2.init_pos);
2589       if (mj2_read_trak(tk, img, cio))
2590                                 return 1;
2591                         
2592       if (tk->track_type == 0) {
2593                                 movie->num_vtk++;
2594       } else if (tk->track_type == 1) {
2595                                 movie->num_stk++;
2596       } else if (tk->track_type == 2) {
2597                                 movie->num_htk++;
2598       }
2599     } else if (box2.type == MJ2_MVEX) {
2600       cio_seek(cio, box2.init_pos);
2601       cio_skip(cio,box2.length);
2602       i--;
2603     } else {
2604       opj_event_msg(cio->cinfo, EVT_ERROR, "Error with MOOV Box: Expected TRAK or MVEX box\n");
2605       return 1;
2606     }
2607   }
2608   return 0;
2609 }
2610
2611 int mj2_read_struct(FILE *file, opj_mj2_t *movie) {
2612   mj2_box_t box;
2613   opj_image_t img;
2614   unsigned char * src;
2615   int fsresult;
2616   int foffset;
2617         opj_cio_t *cio;
2618         
2619         /* open a byte stream for reading */    
2620         src = (unsigned char*) opj_malloc(300 * sizeof(unsigned char)); 
2621
2622         /* Assuming that jp and ftyp markers size do
2623      not exceed 300 bytes */
2624   fread(src,300,1, file);  
2625   
2626   cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2627   
2628   if (mj2_read_jp(cio))
2629     return 1;
2630   if (mj2_read_ftyp(movie, cio))
2631     return 1;
2632         
2633   fsresult = fseek(file,cio_tell(cio),SEEK_SET);
2634   if( fsresult ) {
2635     opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read data after FTYP box\n" );
2636     return 1;
2637   }
2638         
2639   foffset = cio_tell(cio);
2640   
2641   box.type = 0;
2642   
2643   fread(src,30,1,file);
2644   cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 300);
2645   mj2_read_boxhdr(&box, cio);
2646   
2647   while(box.type != MJ2_MOOV) {
2648     
2649     switch(box.type)
2650     {
2651     case MJ2_MDAT:
2652       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2653       if( fsresult ) {
2654                                 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MDAT box\n" );
2655                                 return 1;
2656       }
2657       foffset += box.length;
2658       break;
2659       
2660     case MJ2_MOOF:
2661       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2662       if( fsresult ) {
2663                                 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOF box\n" );
2664                                 return 1;
2665       }
2666       foffset += box.length;
2667       break;      
2668     case MJ2_FREE:
2669       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2670       if( fsresult ) {
2671                                 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read FREE box\n" );
2672                                 return 1;
2673       }
2674       foffset += box.length;
2675       break;      
2676     case MJ2_SKIP:
2677       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2678       if( fsresult ) {
2679                                 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read SKIP box\n" );
2680                                 return 1;
2681       }
2682       foffset += box.length;
2683       break;      
2684     default:
2685       opj_event_msg(cio->cinfo, EVT_ERROR, "Unknown box in MJ2 stream\n");
2686       fsresult = fseek(file,foffset+box.length,SEEK_SET);
2687       if( fsresult ) {
2688                                 opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read end of unknown box\n"); 
2689                                 return 1;
2690       }      
2691       foffset += box.length;
2692       break;
2693     }
2694     fsresult = fread(src,8,1,file);
2695     if (fsresult != 1) {
2696       opj_event_msg(cio->cinfo, EVT_ERROR, "MOOV box not found in file\n"); 
2697       return 1;
2698     }
2699                 cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, 8);               
2700     mj2_read_boxhdr(&box, cio);
2701   }     
2702
2703   fseek(file,foffset,SEEK_SET);
2704   src = (unsigned char*)opj_realloc(src,box.length);
2705   fsresult = fread(src,box.length,1,file);
2706   if (fsresult != 1) {
2707     opj_event_msg(cio->cinfo, EVT_ERROR, "End of file reached while trying to read MOOV box\n"); 
2708     return 1;
2709   }
2710         
2711         cio = opj_cio_open((opj_common_ptr)movie->cinfo, src, box.length);
2712   
2713   if (mj2_read_moov(movie, &img, cio))
2714     return 1;
2715
2716   opj_free(src);
2717   return 0;
2718 }
2719
2720 /* ----------------------------------------------------------------------- */
2721 /* MJ2 decoder interface                                                                                                                                             */
2722 /* ----------------------------------------------------------------------- */
2723
2724 opj_dinfo_t* mj2_create_decompress() {
2725         opj_mj2_t* mj2;
2726         opj_dinfo_t *dinfo = (opj_dinfo_t*) opj_calloc(1, sizeof(opj_dinfo_t));
2727         if(!dinfo) return NULL;
2728
2729         dinfo->is_decompressor = OPJ_TRUE;      
2730
2731         mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2732         dinfo->mj2_handle = mj2;
2733         if(mj2) {
2734                 mj2->cinfo = (opj_common_ptr)dinfo;
2735         }
2736         mj2->j2k = j2k_create_decompress((opj_common_ptr)dinfo);
2737         dinfo->j2k_handle = mj2->j2k;
2738
2739         return dinfo;
2740 }
2741
2742 void mj2_setup_decoder(opj_mj2_t *movie, mj2_dparameters_t *mj2_parameters) {
2743         movie->num_vtk=0;
2744   movie->num_stk=0;
2745   movie->num_htk=0;     
2746
2747         /* setup the J2K decoder parameters */
2748         j2k_setup_decoder((opj_j2k_t*)movie->cinfo->j2k_handle, 
2749                 &mj2_parameters->j2k_parameters);
2750
2751 }
2752
2753 void mj2_destroy_decompress(opj_mj2_t *movie) {
2754         if(movie) {
2755                 int i;
2756                 mj2_tk_t *tk=NULL;
2757
2758                 if (movie->cinfo->j2k_handle) 
2759                         j2k_destroy_compress(movie->j2k);
2760                 
2761                 if (movie->num_cl != 0)
2762                         opj_free(movie->cl);
2763                 
2764                 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2765                         tk = &movie->tk[i];
2766                         if (tk->name_size != 0)
2767                                 opj_free(tk->name);
2768                         if (tk->track_type == 0)  {/* Video track*/
2769                                 if (tk->jp2_struct.comps != NULL)
2770                                         opj_free(tk->jp2_struct.comps);
2771                                 if (tk->jp2_struct.cl != NULL)
2772                                         opj_free(tk->jp2_struct.cl);
2773                                 if (tk->num_jp2x != 0)
2774                                         opj_free(tk->jp2xdata);
2775                                 
2776                         }
2777                         if (tk->num_url != 0)
2778                                 opj_free(tk->url);
2779                         if (tk->num_urn != 0)
2780                                 opj_free(tk->urn);
2781                         if (tk->num_br != 0)
2782                                 opj_free(tk->br);
2783                         if (tk->num_tts != 0)
2784                                 opj_free(tk->tts);
2785                         if (tk->num_chunks != 0)
2786                                 opj_free(tk->chunk);
2787                         if (tk->num_samplestochunk != 0)
2788                                 opj_free(tk->sampletochunk);
2789                         if (tk->num_samples != 0)
2790                                 opj_free(tk->sample);
2791                 }
2792                 
2793                 opj_free(movie->tk);
2794         }       
2795         opj_free(movie);
2796 }
2797
2798 /* ----------------------------------------------------------------------- */
2799 /* MJ2 encoder interface                                                                                                                                             */
2800 /* ----------------------------------------------------------------------- */
2801
2802
2803 opj_cinfo_t* mj2_create_compress() {
2804         opj_mj2_t* mj2;
2805         opj_cinfo_t *cinfo = (opj_cinfo_t*) opj_calloc(1, sizeof(opj_cinfo_t));
2806         if(!cinfo) return NULL;
2807
2808         mj2 = (opj_mj2_t*) opj_calloc(1, sizeof(opj_mj2_t));
2809         cinfo->mj2_handle = mj2;
2810         if(mj2) {
2811                 mj2->cinfo = (opj_common_ptr)cinfo;
2812         }
2813
2814         mj2->j2k = j2k_create_compress(mj2->cinfo);
2815         cinfo->j2k_handle = mj2->j2k;
2816
2817         return cinfo;
2818 }
2819
2820 void mj2_setup_encoder(opj_mj2_t *movie, mj2_cparameters_t *parameters) {
2821         if(movie && parameters) {
2822                 opj_jp2_t *jp2_struct;
2823                         
2824                 movie->num_htk = 0;       /* No hint tracks*/
2825                 movie->num_stk = 0;       /* No sound tracks*/
2826                 movie->num_vtk = 1;       /* One video track*/
2827
2828                 movie->brand = MJ2_MJ2;  /* One brand: MJ2*/
2829                 movie->num_cl = 2;        /* Two compatible brands: MJ2 and MJ2S*/
2830                 movie->cl = (unsigned int*) opj_malloc(movie->num_cl * sizeof(unsigned int));
2831                 movie->cl[0] = MJ2_MJ2;
2832                 movie->cl[1] = MJ2_MJ2S;
2833                 movie->minversion = 0;    /* Minimum version: 0 */
2834
2835                 movie->tk = (mj2_tk_t*) opj_malloc(sizeof(mj2_tk_t)); /*Memory allocation for the video track*/
2836                 movie->tk[0].track_ID = 1;        /* Track ID = 1 */
2837                 movie->tk[0].track_type = 0;      /* Video track */
2838                 movie->tk[0].Dim[0] = parameters->Dim[0];
2839                 movie->tk[0].Dim[1] = parameters->Dim[1];
2840                 movie->tk[0].w = parameters->w;
2841                 movie->tk[0].h = parameters->h;
2842                 movie->tk[0].CbCr_subsampling_dx = parameters->CbCr_subsampling_dx;
2843                 movie->tk[0].CbCr_subsampling_dy = parameters->CbCr_subsampling_dy;
2844                 movie->tk[0].sample_rate = parameters->frame_rate;
2845                 movie->tk[0].name_size = 0;
2846                 movie->tk[0].chunk = (mj2_chunk_t*) opj_malloc(sizeof(mj2_chunk_t));  
2847                 movie->tk[0].sample = (mj2_sample_t*) opj_malloc(sizeof(mj2_sample_t));
2848                 movie->tk[0].depth = parameters->prec;
2849
2850                 jp2_struct = &movie->tk[0].jp2_struct;
2851                 jp2_struct->numcomps = parameters->numcomps;    /* NC */
2852                 jp2_struct->comps = (opj_jp2_comps_t*) opj_malloc(jp2_struct->numcomps * sizeof(opj_jp2_comps_t));
2853                 jp2_struct->precedence = 0;   /* PRECEDENCE*/
2854                 jp2_struct->approx = 0;   /* APPROX*/           
2855                 jp2_struct->brand = JP2_JP2;    /* BR         */
2856                 jp2_struct->minversion = 0;     /* MinV       */
2857                 jp2_struct->numcl = 1;
2858                 jp2_struct->cl = (unsigned int*) opj_malloc(jp2_struct->numcl * sizeof(unsigned int));
2859                 jp2_struct->cl[0] = JP2_JP2;    /* CL0 : JP2  */                
2860                 jp2_struct->C = 7;      /* C : Always 7*/
2861                 jp2_struct->UnkC = 0;      /* UnkC, colorspace specified in colr box*/
2862                 jp2_struct->IPR = 0;      /* IPR, no intellectual property*/                                            
2863                 jp2_struct->w = parameters->w;
2864                 jp2_struct->h = parameters->h;
2865                 jp2_struct->bpc = 7;  
2866                 jp2_struct->meth = parameters->meth;
2867                 jp2_struct->enumcs = parameters->enumcs;
2868   }
2869 }
2870
2871 void mj2_destroy_compress(opj_mj2_t *movie) {
2872         if(movie) {
2873                 int i;
2874                 mj2_tk_t *tk=NULL;
2875
2876                 if (movie->cinfo->j2k_handle) {
2877                         j2k_destroy_compress(movie->j2k);
2878                 }
2879                 
2880                 if (movie->num_cl != 0)
2881                         opj_free(movie->cl);
2882                 
2883                 for (i = 0; i < movie->num_vtk + movie->num_stk + movie->num_htk; i++) {
2884                         tk = &movie->tk[i];
2885                         if (tk->name_size != 0)
2886                                 opj_free(tk->name);
2887                         if (tk->track_type == 0)  {/* Video track*/
2888                                 if (tk->jp2_struct.comps != NULL)
2889                                         opj_free(tk->jp2_struct.comps);
2890                                 if (tk->jp2_struct.cl != NULL)
2891                                         opj_free(tk->jp2_struct.cl);
2892                                 if (tk->num_jp2x != 0)
2893                                         opj_free(tk->jp2xdata);
2894                                 
2895                         }
2896                         if (tk->num_url != 0)
2897                                 opj_free(tk->url);
2898                         if (tk->num_urn != 0)
2899                                 opj_free(tk->urn);
2900                         if (tk->num_br != 0)
2901                                 opj_free(tk->br);
2902                         if (tk->num_tts != 0)
2903                                 opj_free(tk->tts);
2904                         if (tk->num_chunks != 0)
2905                                 opj_free(tk->chunk);
2906                         if (tk->num_samplestochunk != 0)
2907                                 opj_free(tk->sampletochunk);
2908                         if (tk->num_samples != 0)
2909                                 opj_free(tk->sample);
2910                 }
2911                 
2912                 opj_free(movie->tk);
2913         }       
2914         opj_free(movie);
2915 }
2916
2917 /*@}*/
2918
2919 /*@}*/
2920