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