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