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