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