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 | }>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><>><>><>>>><>><> |