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