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