Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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