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