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