Mercurial > audlegacy-plugins
comparison src/Input/aac/mp4ff/mp4atom.c @ 0:13389e613d67 trunk
[svn] - initial import of audacious-plugins tree (lots to do)
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 01:11:49 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:13389e613d67 |
---|---|
1 /* | |
2 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding | |
3 ** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com | |
4 ** | |
5 ** This program is free software; you can redistribute it and/or modify | |
6 ** it under the terms of the GNU General Public License as published by | |
7 ** the Free Software Foundation; either version 2 of the License, or | |
8 ** (at your option) any later version. | |
9 ** | |
10 ** This program is distributed in the hope that it will be useful, | |
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 ** GNU General Public License for more details. | |
14 ** | |
15 ** You should have received a copy of the GNU General Public License | |
16 ** along with this program; if not, write to the Free Software | |
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
18 ** | |
19 ** Any non-GPL usage of this software or parts of this software is strictly | |
20 ** forbidden. | |
21 ** | |
22 ** Commercial non-GPL licensing of this software is possible. | |
23 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. | |
24 ** | |
25 ** $Id: mp4atom.c,v 1.17 2004/01/11 15:52:18 menno Exp $ | |
26 **/ | |
27 | |
28 #include <stdlib.h> | |
29 #include "mp4ffint.h" | |
30 | |
31 #include "drms.h" | |
32 | |
33 /* parse atom header size */ | |
34 int32_t mp4ff_atom_get_size(const uint8_t *data) | |
35 { | |
36 uint32_t result; | |
37 uint32_t a, b, c, d; | |
38 | |
39 a = data[0]; | |
40 b = data[1]; | |
41 c = data[2]; | |
42 d = data[3]; | |
43 | |
44 result = (a<<24) | (b<<16) | (c<<8) | d; | |
45 //if (result > 0 && result < 8) result = 8; | |
46 | |
47 return (int32_t)result; | |
48 } | |
49 | |
50 /* comnapre 2 atom names, returns 1 for equal, 0 for unequal */ | |
51 int32_t mp4ff_atom_compare(const int8_t a1, const int8_t b1, const int8_t c1, const int8_t d1, | |
52 const int8_t a2, const int8_t b2, const int8_t c2, const int8_t d2) | |
53 { | |
54 if (a1 == a2 && b1 == b2 && c1 == c2 && d1 == d2) | |
55 return 1; | |
56 else | |
57 return 0; | |
58 } | |
59 | |
60 uint8_t mp4ff_atom_name_to_type(const int8_t a, const int8_t b, | |
61 const int8_t c, const int8_t d) | |
62 { | |
63 if (a == 'm') | |
64 { | |
65 if (mp4ff_atom_compare(a,b,c,d, 'm','o','o','v')) | |
66 return ATOM_MOOV; | |
67 else if (mp4ff_atom_compare(a,b,c,d, 'm','i','n','f')) | |
68 return ATOM_MINF; | |
69 else if (mp4ff_atom_compare(a,b,c,d, 'm','d','i','a')) | |
70 return ATOM_MDIA; | |
71 else if (mp4ff_atom_compare(a,b,c,d, 'm','d','a','t')) | |
72 return ATOM_MDAT; | |
73 else if (mp4ff_atom_compare(a,b,c,d, 'm','d','h','d')) | |
74 return ATOM_MDHD; | |
75 else if (mp4ff_atom_compare(a,b,c,d, 'm','v','h','d')) | |
76 return ATOM_MVHD; | |
77 else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','a')) | |
78 return ATOM_MP4A; | |
79 else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','v')) | |
80 return ATOM_MP4V; | |
81 else if (mp4ff_atom_compare(a,b,c,d, 'm','p','4','s')) | |
82 return ATOM_MP4S; | |
83 else if (mp4ff_atom_compare(a,b,c,d, 'm','e','t','a')) | |
84 return ATOM_META; | |
85 } else if (a == 't') { | |
86 if (mp4ff_atom_compare(a,b,c,d, 't','r','a','k')) | |
87 return ATOM_TRAK; | |
88 else if (mp4ff_atom_compare(a,b,c,d, 't','k','h','d')) | |
89 return ATOM_TKHD; | |
90 else if (mp4ff_atom_compare(a,b,c,d, 't','r','e','f')) | |
91 return ATOM_TREF; | |
92 else if (mp4ff_atom_compare(a,b,c,d, 't','r','k','n')) | |
93 return ATOM_TRACK; | |
94 else if (mp4ff_atom_compare(a,b,c,d, 't','m','p','o')) | |
95 return ATOM_TEMPO; | |
96 } else if (a == 's') { | |
97 if (mp4ff_atom_compare(a,b,c,d, 's','t','b','l')) | |
98 return ATOM_STBL; | |
99 else if (mp4ff_atom_compare(a,b,c,d, 's','m','h','d')) | |
100 return ATOM_SMHD; | |
101 else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','d')) | |
102 return ATOM_STSD; | |
103 else if (mp4ff_atom_compare(a,b,c,d, 's','t','t','s')) | |
104 return ATOM_STTS; | |
105 else if (mp4ff_atom_compare(a,b,c,d, 's','t','c','o')) | |
106 return ATOM_STCO; | |
107 else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','c')) | |
108 return ATOM_STSC; | |
109 else if (mp4ff_atom_compare(a,b,c,d, 's','t','s','z')) | |
110 return ATOM_STSZ; | |
111 else if (mp4ff_atom_compare(a,b,c,d, 's','t','z','2')) | |
112 return ATOM_STZ2; | |
113 else if (mp4ff_atom_compare(a,b,c,d, 's','k','i','p')) | |
114 return ATOM_SKIP; | |
115 else if (mp4ff_atom_compare(a,b,c,d, 's','i','n','f')) | |
116 return ATOM_SINF; | |
117 else if (mp4ff_atom_compare(a,b,c,d, 's','c','h','i')) | |
118 return ATOM_SCHI; | |
119 } else if (a == '©') { | |
120 if (mp4ff_atom_compare(a,b,c,d, '©','n','a','m')) | |
121 return ATOM_TITLE; | |
122 else if (mp4ff_atom_compare(a,b,c,d, '©','A','R','T')) | |
123 return ATOM_ARTIST; | |
124 else if (mp4ff_atom_compare(a,b,c,d, '©','w','r','t')) | |
125 return ATOM_WRITER; | |
126 else if (mp4ff_atom_compare(a,b,c,d, '©','a','l','b')) | |
127 return ATOM_ALBUM; | |
128 else if (mp4ff_atom_compare(a,b,c,d, '©','d','a','y')) | |
129 return ATOM_DATE; | |
130 else if (mp4ff_atom_compare(a,b,c,d, '©','t','o','o')) | |
131 return ATOM_TOOL; | |
132 else if (mp4ff_atom_compare(a,b,c,d, '©','c','m','t')) | |
133 return ATOM_COMMENT; | |
134 else if (mp4ff_atom_compare(a,b,c,d, '©','g','e','n')) | |
135 return ATOM_GENRE1; | |
136 } | |
137 | |
138 if (mp4ff_atom_compare(a,b,c,d, 'e','d','t','s')) | |
139 return ATOM_EDTS; | |
140 else if (mp4ff_atom_compare(a,b,c,d, 'e','s','d','s')) | |
141 return ATOM_ESDS; | |
142 else if (mp4ff_atom_compare(a,b,c,d, 'f','t','y','p')) | |
143 return ATOM_FTYP; | |
144 else if (mp4ff_atom_compare(a,b,c,d, 'f','r','e','e')) | |
145 return ATOM_FREE; | |
146 else if (mp4ff_atom_compare(a,b,c,d, 'h','m','h','d')) | |
147 return ATOM_HMHD; | |
148 else if (mp4ff_atom_compare(a,b,c,d, 'v','m','h','d')) | |
149 return ATOM_VMHD; | |
150 else if (mp4ff_atom_compare(a,b,c,d, 'u','d','t','a')) | |
151 return ATOM_UDTA; | |
152 else if (mp4ff_atom_compare(a,b,c,d, 'i','l','s','t')) | |
153 return ATOM_ILST; | |
154 else if (mp4ff_atom_compare(a,b,c,d, 'n','a','m','e')) | |
155 return ATOM_NAME; | |
156 else if (mp4ff_atom_compare(a,b,c,d, 'd','a','t','a')) | |
157 return ATOM_DATA; | |
158 else if (mp4ff_atom_compare(a,b,c,d, 'd','i','s','k')) | |
159 return ATOM_DISC; | |
160 else if (mp4ff_atom_compare(a,b,c,d, 'g','n','r','e')) | |
161 return ATOM_GENRE2; | |
162 else if (mp4ff_atom_compare(a,b,c,d, 'c','o','v','r')) | |
163 return ATOM_COVER; | |
164 else if (mp4ff_atom_compare(a,b,c,d, 'c','p','i','l')) | |
165 return ATOM_COMPILATION; | |
166 else if (mp4ff_atom_compare(a,b,c,d, 'c','t','t','s')) | |
167 return ATOM_CTTS; | |
168 else if (mp4ff_atom_compare(a,b,c,d, 'd','r','m','s')) | |
169 return ATOM_DRMS; | |
170 else if (mp4ff_atom_compare(a,b,c,d, 'f','r','m','a')) | |
171 return ATOM_FRMA; | |
172 else if (mp4ff_atom_compare(a,b,c,d, 'p','r','i','v')) | |
173 return ATOM_PRIV; | |
174 else if (mp4ff_atom_compare(a,b,c,d, 'i','v','i','v')) | |
175 return ATOM_IVIV; | |
176 else | |
177 return ATOM_UNKNOWN; | |
178 } | |
179 | |
180 /* read atom header, return atom size, atom size is with header included */ | |
181 uint64_t mp4ff_atom_read_header(mp4ff_t *f, uint8_t *atom_type, uint8_t *header_size) | |
182 { | |
183 uint64_t size; | |
184 int32_t ret; | |
185 uint8_t atom_header[8]; | |
186 | |
187 ret = mp4ff_read_data(f, atom_header, 8); | |
188 if (ret != 8) | |
189 return 0; | |
190 | |
191 size = mp4ff_atom_get_size(atom_header); | |
192 *header_size = 8; | |
193 | |
194 /* check for 64 bit atom size */ | |
195 if (size == 1) | |
196 { | |
197 *header_size = 16; | |
198 size = mp4ff_read_int64(f); | |
199 } | |
200 | |
201 //printf("%c%c%c%c\n", atom_header[4], atom_header[5], atom_header[6], atom_header[7]); | |
202 | |
203 *atom_type = mp4ff_atom_name_to_type(atom_header[4], atom_header[5], atom_header[6], atom_header[7]); | |
204 | |
205 return size; | |
206 } | |
207 | |
208 int32_t mp4ff_read_stsz(mp4ff_t *f) | |
209 { | |
210 mp4ff_read_char(f); /* version */ | |
211 mp4ff_read_int24(f); /* flags */ | |
212 f->track[f->total_tracks - 1]->stsz_sample_size = mp4ff_read_int32(f); | |
213 f->track[f->total_tracks - 1]->stsz_sample_count = mp4ff_read_int32(f); | |
214 | |
215 if (f->track[f->total_tracks - 1]->stsz_sample_size == 0) | |
216 { | |
217 int32_t i; | |
218 f->track[f->total_tracks - 1]->stsz_table = | |
219 (int32_t*)malloc(f->track[f->total_tracks - 1]->stsz_sample_count*sizeof(int32_t)); | |
220 | |
221 for (i = 0; i < f->track[f->total_tracks - 1]->stsz_sample_count; i++) | |
222 { | |
223 f->track[f->total_tracks - 1]->stsz_table[i] = mp4ff_read_int32(f); | |
224 } | |
225 } | |
226 | |
227 return 0; | |
228 } | |
229 | |
230 int32_t mp4ff_read_esds(mp4ff_t *f) | |
231 { | |
232 uint8_t tag; | |
233 uint32_t temp; | |
234 | |
235 mp4ff_read_char(f); /* version */ | |
236 mp4ff_read_int24(f); /* flags */ | |
237 | |
238 /* get and verify ES_DescrTag */ | |
239 tag = mp4ff_read_char(f); | |
240 if (tag == 0x03) | |
241 { | |
242 /* read length */ | |
243 if (mp4ff_read_mp4_descr_length(f) < 5 + 15) | |
244 { | |
245 return 1; | |
246 } | |
247 /* skip 3 bytes */ | |
248 mp4ff_read_int24(f); | |
249 } else { | |
250 /* skip 2 bytes */ | |
251 mp4ff_read_int16(f); | |
252 } | |
253 | |
254 /* get and verify DecoderConfigDescrTab */ | |
255 if (mp4ff_read_char(f) != 0x04) | |
256 { | |
257 return 1; | |
258 } | |
259 | |
260 /* read length */ | |
261 temp = mp4ff_read_mp4_descr_length(f); | |
262 if (temp < 13) return 1; | |
263 | |
264 f->track[f->total_tracks - 1]->audioType = mp4ff_read_char(f); | |
265 mp4ff_read_int32(f);//0x15000414 ???? | |
266 f->track[f->total_tracks - 1]->maxBitrate = mp4ff_read_int32(f); | |
267 f->track[f->total_tracks - 1]->avgBitrate = mp4ff_read_int32(f); | |
268 | |
269 /* get and verify DecSpecificInfoTag */ | |
270 if (mp4ff_read_char(f) != 0x05) | |
271 { | |
272 return 1; | |
273 } | |
274 | |
275 /* read length */ | |
276 f->track[f->total_tracks - 1]->decoderConfigLen = mp4ff_read_mp4_descr_length(f); | |
277 | |
278 if (f->track[f->total_tracks - 1]->decoderConfig) | |
279 free(f->track[f->total_tracks - 1]->decoderConfig); | |
280 f->track[f->total_tracks - 1]->decoderConfig = malloc(f->track[f->total_tracks - 1]->decoderConfigLen); | |
281 if (f->track[f->total_tracks - 1]->decoderConfig) | |
282 { | |
283 mp4ff_read_data(f, f->track[f->total_tracks - 1]->decoderConfig, f->track[f->total_tracks - 1]->decoderConfigLen); | |
284 } else { | |
285 f->track[f->total_tracks - 1]->decoderConfigLen = 0; | |
286 } | |
287 | |
288 /* will skip the remainder of the atom */ | |
289 return 0; | |
290 } | |
291 | |
292 int32_t mp4ff_read_mp4a(mp4ff_t *f) | |
293 { | |
294 uint64_t size; | |
295 int32_t i; | |
296 uint8_t atom_type = 0; | |
297 uint8_t header_size = 0; | |
298 | |
299 for (i = 0; i < 6; i++) | |
300 { | |
301 mp4ff_read_char(f); /* reserved */ | |
302 } | |
303 /* data_reference_index */ mp4ff_read_int16(f); | |
304 | |
305 mp4ff_read_int32(f); /* reserved */ | |
306 mp4ff_read_int32(f); /* reserved */ | |
307 | |
308 f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f); | |
309 f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f); | |
310 | |
311 mp4ff_read_int16(f); | |
312 mp4ff_read_int16(f); | |
313 | |
314 f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f); | |
315 | |
316 mp4ff_read_int16(f); | |
317 | |
318 size = mp4ff_atom_read_header(f, &atom_type, &header_size); | |
319 if (atom_type == ATOM_ESDS) | |
320 { | |
321 mp4ff_read_esds(f); | |
322 } | |
323 | |
324 return 0; | |
325 } | |
326 | |
327 #ifdef ITUNES_DRM | |
328 int32_t mp4ff_read_drms(mp4ff_t *f, uint64_t skip) | |
329 { | |
330 uint64_t size; | |
331 int32_t i; | |
332 uint8_t atom_type = 0; | |
333 uint8_t header_size = 0; | |
334 uint32_t drms_user_key[4]; | |
335 | |
336 if (drms_get_user_key(NULL, drms_user_key) == 0) | |
337 { | |
338 f->track[f->total_tracks - 1]->p_drms = drms_alloc(); | |
339 | |
340 drms_init( f->track[f->total_tracks - 1]->p_drms, | |
341 DRMS_INIT_UKEY, (uint8_t *)drms_user_key, | |
342 sizeof(drms_user_key) ); | |
343 } | |
344 | |
345 for (i = 0; i < 6; i++) | |
346 { | |
347 mp4ff_read_char(f); /* reserved */ | |
348 } | |
349 /* data_reference_index */ mp4ff_read_int16(f); | |
350 | |
351 mp4ff_read_int32(f); /* reserved */ | |
352 mp4ff_read_int32(f); /* reserved */ | |
353 | |
354 f->track[f->total_tracks - 1]->channelCount = mp4ff_read_int16(f); | |
355 f->track[f->total_tracks - 1]->sampleSize = mp4ff_read_int16(f); | |
356 | |
357 mp4ff_read_int16(f); | |
358 mp4ff_read_int16(f); | |
359 | |
360 f->track[f->total_tracks - 1]->sampleRate = mp4ff_read_int16(f); | |
361 | |
362 mp4ff_read_int16(f); | |
363 | |
364 size = mp4ff_atom_read_header(f, &atom_type, &header_size); | |
365 if (atom_type == ATOM_ESDS) | |
366 { | |
367 mp4ff_read_esds(f); | |
368 } | |
369 mp4ff_set_position(f, skip+size+28); | |
370 | |
371 size = mp4ff_atom_read_header(f, &atom_type, &header_size); | |
372 if (atom_type == ATOM_SINF) | |
373 { | |
374 parse_sub_atoms(f, size-header_size); | |
375 } | |
376 | |
377 return 0; | |
378 } | |
379 | |
380 int32_t mp4ff_read_frma(mp4ff_t *f) | |
381 { | |
382 uint8_t atom_type; | |
383 int8_t type[4]; | |
384 | |
385 mp4ff_read_data(f, type, 4); | |
386 | |
387 atom_type = mp4ff_atom_name_to_type(type[0], type[1], type[2], type[3]); | |
388 | |
389 if (atom_type == ATOM_MP4A) | |
390 { | |
391 f->track[f->total_tracks - 1]->type = TRACK_AUDIO; | |
392 } else if (atom_type == ATOM_MP4V) { | |
393 f->track[f->total_tracks - 1]->type = TRACK_VIDEO; | |
394 } else if (atom_type == ATOM_MP4S) { | |
395 f->track[f->total_tracks - 1]->type = TRACK_SYSTEM; | |
396 } else { | |
397 f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN; | |
398 } | |
399 | |
400 return 0; | |
401 } | |
402 | |
403 int32_t mp4ff_read_name(mp4ff_t *f, uint64_t size) | |
404 { | |
405 uint8_t *data = malloc(size); | |
406 mp4ff_read_data(f, data, size); | |
407 | |
408 if (f->track[f->total_tracks - 1]->p_drms != NULL) | |
409 { | |
410 drms_init(f->track[f->total_tracks - 1]->p_drms, | |
411 DRMS_INIT_NAME, data, strlen(data) ); | |
412 } | |
413 | |
414 if (data) | |
415 free(data); | |
416 | |
417 return 0; | |
418 } | |
419 | |
420 int32_t mp4ff_read_priv(mp4ff_t *f, uint64_t size) | |
421 { | |
422 uint8_t *data = malloc(size); | |
423 mp4ff_read_data(f, data, size); | |
424 | |
425 if (f->track[f->total_tracks - 1]->p_drms != 0) | |
426 { | |
427 drms_init(f->track[f->total_tracks - 1]->p_drms, | |
428 DRMS_INIT_PRIV, data, size ); | |
429 } | |
430 | |
431 if (data) | |
432 free(data); | |
433 | |
434 return 0; | |
435 } | |
436 | |
437 int32_t mp4ff_read_iviv(mp4ff_t *f, uint64_t size) | |
438 { | |
439 uint8_t *data = malloc(size); | |
440 mp4ff_read_data(f, data, size); | |
441 | |
442 if (f->track[f->total_tracks - 1]->p_drms != 0) | |
443 { | |
444 drms_init(f->track[f->total_tracks - 1]->p_drms, | |
445 DRMS_INIT_IVIV, data, sizeof(uint32_t) * 4 ); | |
446 } | |
447 | |
448 if (data) | |
449 free(data); | |
450 | |
451 return 0; | |
452 } | |
453 #endif | |
454 | |
455 int32_t mp4ff_read_stsd(mp4ff_t *f) | |
456 { | |
457 int32_t i; | |
458 uint8_t header_size = 0; | |
459 | |
460 mp4ff_read_char(f); /* version */ | |
461 mp4ff_read_int24(f); /* flags */ | |
462 | |
463 f->track[f->total_tracks - 1]->stsd_entry_count = mp4ff_read_int32(f); | |
464 | |
465 for (i = 0; i < f->track[f->total_tracks - 1]->stsd_entry_count; i++) | |
466 { | |
467 uint64_t skip = mp4ff_position(f); | |
468 uint64_t size; | |
469 uint8_t atom_type = 0; | |
470 size = mp4ff_atom_read_header(f, &atom_type, &header_size); | |
471 skip += size; | |
472 | |
473 if (atom_type == ATOM_MP4A) | |
474 { | |
475 f->track[f->total_tracks - 1]->type = TRACK_AUDIO; | |
476 mp4ff_read_mp4a(f); | |
477 } else if (atom_type == ATOM_MP4V) { | |
478 f->track[f->total_tracks - 1]->type = TRACK_VIDEO; | |
479 } else if (atom_type == ATOM_MP4S) { | |
480 f->track[f->total_tracks - 1]->type = TRACK_SYSTEM; | |
481 #ifdef ITUNES_DRM | |
482 } else if (atom_type == ATOM_DRMS) { | |
483 // track type is read from the "frma" atom | |
484 f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN; | |
485 mp4ff_read_drms(f, skip-size+header_size); | |
486 #endif | |
487 } else { | |
488 f->track[f->total_tracks - 1]->type = TRACK_UNKNOWN; | |
489 } | |
490 | |
491 mp4ff_set_position(f, skip); | |
492 } | |
493 | |
494 return 0; | |
495 } | |
496 | |
497 int32_t mp4ff_read_stsc(mp4ff_t *f) | |
498 { | |
499 int32_t i; | |
500 | |
501 mp4ff_read_char(f); /* version */ | |
502 mp4ff_read_int24(f); /* flags */ | |
503 f->track[f->total_tracks - 1]->stsc_entry_count = mp4ff_read_int32(f); | |
504 | |
505 f->track[f->total_tracks - 1]->stsc_first_chunk = | |
506 (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t)); | |
507 f->track[f->total_tracks - 1]->stsc_samples_per_chunk = | |
508 (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t)); | |
509 f->track[f->total_tracks - 1]->stsc_sample_desc_index = | |
510 (int32_t*)malloc(f->track[f->total_tracks - 1]->stsc_entry_count*sizeof(int32_t)); | |
511 | |
512 for (i = 0; i < f->track[f->total_tracks - 1]->stsc_entry_count; i++) | |
513 { | |
514 f->track[f->total_tracks - 1]->stsc_first_chunk[i] = mp4ff_read_int32(f); | |
515 f->track[f->total_tracks - 1]->stsc_samples_per_chunk[i] = mp4ff_read_int32(f); | |
516 f->track[f->total_tracks - 1]->stsc_sample_desc_index[i] = mp4ff_read_int32(f); | |
517 } | |
518 | |
519 return 0; | |
520 } | |
521 | |
522 int32_t mp4ff_read_stco(mp4ff_t *f) | |
523 { | |
524 int32_t i; | |
525 | |
526 mp4ff_read_char(f); /* version */ | |
527 mp4ff_read_int24(f); /* flags */ | |
528 f->track[f->total_tracks - 1]->stco_entry_count = mp4ff_read_int32(f); | |
529 | |
530 f->track[f->total_tracks - 1]->stco_chunk_offset = | |
531 (int32_t*)malloc(f->track[f->total_tracks - 1]->stco_entry_count*sizeof(int32_t)); | |
532 | |
533 for (i = 0; i < f->track[f->total_tracks - 1]->stco_entry_count; i++) | |
534 { | |
535 f->track[f->total_tracks - 1]->stco_chunk_offset[i] = mp4ff_read_int32(f); | |
536 } | |
537 | |
538 return 0; | |
539 } | |
540 | |
541 int32_t mp4ff_read_ctts(mp4ff_t *f) | |
542 { | |
543 int32_t i; | |
544 mp4ff_track_t * p_track = f->track[f->total_tracks - 1]; | |
545 | |
546 if (p_track->ctts_entry_count) return 0; | |
547 | |
548 mp4ff_read_char(f); /* version */ | |
549 mp4ff_read_int24(f); /* flags */ | |
550 p_track->ctts_entry_count = mp4ff_read_int32(f); | |
551 | |
552 p_track->ctts_sample_count = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t)); | |
553 p_track->ctts_sample_offset = (int32_t*)malloc(p_track->ctts_entry_count * sizeof(int32_t)); | |
554 | |
555 if (p_track->ctts_sample_count == 0 || p_track->ctts_sample_offset == 0) | |
556 { | |
557 if (p_track->ctts_sample_count) {free(p_track->ctts_sample_count);p_track->ctts_sample_count=0;} | |
558 if (p_track->ctts_sample_offset) {free(p_track->ctts_sample_offset);p_track->ctts_sample_offset=0;} | |
559 p_track->ctts_entry_count = 0; | |
560 return 0; | |
561 } | |
562 else | |
563 { | |
564 for (i = 0; i < f->track[f->total_tracks - 1]->ctts_entry_count; i++) | |
565 { | |
566 p_track->ctts_sample_count[i] = mp4ff_read_int32(f); | |
567 p_track->ctts_sample_offset[i] = mp4ff_read_int32(f); | |
568 } | |
569 return 1; | |
570 } | |
571 } | |
572 | |
573 int32_t mp4ff_read_stts(mp4ff_t *f) | |
574 { | |
575 int32_t i; | |
576 mp4ff_track_t * p_track = f->track[f->total_tracks - 1]; | |
577 | |
578 if (p_track->stts_entry_count) return 0; | |
579 | |
580 mp4ff_read_char(f); /* version */ | |
581 mp4ff_read_int24(f); /* flags */ | |
582 p_track->stts_entry_count = mp4ff_read_int32(f); | |
583 | |
584 p_track->stts_sample_count = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t)); | |
585 p_track->stts_sample_delta = (int32_t*)malloc(p_track->stts_entry_count * sizeof(int32_t)); | |
586 | |
587 if (p_track->stts_sample_count == 0 || p_track->stts_sample_delta == 0) | |
588 { | |
589 if (p_track->stts_sample_count) {free(p_track->stts_sample_count);p_track->stts_sample_count=0;} | |
590 if (p_track->stts_sample_delta) {free(p_track->stts_sample_delta);p_track->stts_sample_delta=0;} | |
591 p_track->stts_entry_count = 0; | |
592 return 0; | |
593 } | |
594 else | |
595 { | |
596 for (i = 0; i < f->track[f->total_tracks - 1]->stts_entry_count; i++) | |
597 { | |
598 p_track->stts_sample_count[i] = mp4ff_read_int32(f); | |
599 p_track->stts_sample_delta[i] = mp4ff_read_int32(f); | |
600 } | |
601 return 1; | |
602 } | |
603 } | |
604 | |
605 int32_t mp4ff_read_mvhd(mp4ff_t *f) | |
606 { | |
607 int32_t i; | |
608 | |
609 mp4ff_read_char(f); /* version */ | |
610 mp4ff_read_int24(f); /* flags */ | |
611 /* creation_time */ mp4ff_read_int32(f); | |
612 /* modification_time */ mp4ff_read_int32(f); | |
613 f->time_scale = mp4ff_read_int32(f); | |
614 f->duration = mp4ff_read_int32(f); | |
615 /* preferred_rate */ mp4ff_read_int32(f); /*mp4ff_read_fixed32(f);*/ | |
616 /* preferred_volume */ mp4ff_read_int16(f); /*mp4ff_read_fixed16(f);*/ | |
617 for (i = 0; i < 10; i++) | |
618 { | |
619 /* reserved */ mp4ff_read_char(f); | |
620 } | |
621 for (i = 0; i < 9; i++) | |
622 { | |
623 mp4ff_read_int32(f); /* matrix */ | |
624 } | |
625 /* preview_time */ mp4ff_read_int32(f); | |
626 /* preview_duration */ mp4ff_read_int32(f); | |
627 /* poster_time */ mp4ff_read_int32(f); | |
628 /* selection_time */ mp4ff_read_int32(f); | |
629 /* selection_duration */ mp4ff_read_int32(f); | |
630 /* current_time */ mp4ff_read_int32(f); | |
631 /* next_track_id */ mp4ff_read_int32(f); | |
632 | |
633 return 0; | |
634 } | |
635 | |
636 #if 0 | |
637 int32_t mp4ff_read_tkhd(mp4ff_t *f) | |
638 { | |
639 uint8_t version; | |
640 uint32_t flags; | |
641 version = mp4ff_read_char(f); /* version */ | |
642 flags = mp4ff_read_int24(f); /* flags */ | |
643 if (version==1) | |
644 { | |
645 mp4ff_read_int64(f);//creation-time | |
646 mp4ff_read_int64(f);//modification-time | |
647 mp4ff_read_int32(f);//track-id | |
648 mp4ff_read_int32(f);//reserved | |
649 f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration | |
650 } | |
651 else //version == 0 | |
652 { | |
653 mp4ff_read_int32(f);//creation-time | |
654 mp4ff_read_int32(f);//modification-time | |
655 mp4ff_read_int32(f);//track-id | |
656 mp4ff_read_int32(f);//reserved | |
657 f->track[f->total_tracks - 1]->duration = mp4ff_read_int32(f);//duration | |
658 if (f->track[f->total_tracks - 1]->duration == 0xFFFFFFFF) | |
659 f->track[f->total_tracks - 1]->duration = 0xFFFFFFFFFFFFFFFF; | |
660 | |
661 } | |
662 mp4ff_read_int32(f);//reserved | |
663 mp4ff_read_int32(f);//reserved | |
664 mp4ff_read_int16(f);//layer | |
665 mp4ff_read_int16(f);//pre-defined | |
666 mp4ff_read_int16(f);//volume | |
667 mp4ff_read_int16(f);//reserved | |
668 | |
669 //matrix | |
670 mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f); | |
671 mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f); | |
672 mp4ff_read_int32(f); mp4ff_read_int32(f); mp4ff_read_int32(f); | |
673 mp4ff_read_int32(f);//width | |
674 mp4ff_read_int32(f);//height | |
675 return 1; | |
676 } | |
677 #endif | |
678 | |
679 int32_t mp4ff_read_mdhd(mp4ff_t *f) | |
680 { | |
681 uint32_t version; | |
682 | |
683 version = mp4ff_read_int32(f); | |
684 if (version==1) | |
685 { | |
686 mp4ff_read_int64(f);//creation-time | |
687 mp4ff_read_int64(f);//modification-time | |
688 f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale | |
689 f->track[f->total_tracks - 1]->duration = mp4ff_read_int64(f);//duration | |
690 } | |
691 else //version == 0 | |
692 { | |
693 uint32_t temp; | |
694 | |
695 mp4ff_read_int32(f);//creation-time | |
696 mp4ff_read_int32(f);//modification-time | |
697 f->track[f->total_tracks - 1]->timeScale = mp4ff_read_int32(f);//timescale | |
698 temp = mp4ff_read_int32(f); | |
699 f->track[f->total_tracks - 1]->duration = (temp == (uint32_t)(-1)) ? (uint64_t)(-1) : (uint64_t)(temp); | |
700 } | |
701 mp4ff_read_int16(f); | |
702 mp4ff_read_int16(f); | |
703 return 1; | |
704 } | |
705 #ifdef USE_TAGGING | |
706 int32_t mp4ff_read_meta(mp4ff_t *f, const uint64_t size) | |
707 { | |
708 uint64_t subsize, sumsize = 0; | |
709 uint8_t atom_type; | |
710 uint8_t header_size = 0; | |
711 | |
712 mp4ff_read_char(f); /* version */ | |
713 mp4ff_read_int24(f); /* flags */ | |
714 | |
715 while (sumsize < (size-12)) | |
716 { | |
717 subsize = mp4ff_atom_read_header(f, &atom_type, &header_size); | |
718 if (atom_type == ATOM_ILST) | |
719 { | |
720 mp4ff_parse_metadata(f, (uint32_t)(subsize-(header_size+4))); | |
721 } else { | |
722 mp4ff_set_position(f, mp4ff_position(f)+subsize-header_size); | |
723 } | |
724 sumsize += subsize; | |
725 } | |
726 | |
727 return 0; | |
728 } | |
729 #endif | |
730 | |
731 int32_t mp4ff_atom_read(mp4ff_t *f, const int32_t size, const uint8_t atom_type) | |
732 { | |
733 uint64_t dest_position = mp4ff_position(f)+size-8; | |
734 if (atom_type == ATOM_STSZ) | |
735 { | |
736 /* sample size box */ | |
737 mp4ff_read_stsz(f); | |
738 } else if (atom_type == ATOM_STTS) { | |
739 /* time to sample box */ | |
740 mp4ff_read_stts(f); | |
741 } else if (atom_type == ATOM_CTTS) { | |
742 /* composition offset box */ | |
743 mp4ff_read_ctts(f); | |
744 } else if (atom_type == ATOM_STSC) { | |
745 /* sample to chunk box */ | |
746 mp4ff_read_stsc(f); | |
747 } else if (atom_type == ATOM_STCO) { | |
748 /* chunk offset box */ | |
749 mp4ff_read_stco(f); | |
750 } else if (atom_type == ATOM_STSD) { | |
751 /* sample description box */ | |
752 mp4ff_read_stsd(f); | |
753 } else if (atom_type == ATOM_MVHD) { | |
754 /* movie header box */ | |
755 mp4ff_read_mvhd(f); | |
756 } else if (atom_type == ATOM_MDHD) { | |
757 /* track header */ | |
758 mp4ff_read_mdhd(f); | |
759 #ifdef ITUNES_DRM | |
760 } else if (atom_type == ATOM_FRMA) { | |
761 /* DRM track format */ | |
762 mp4ff_read_frma(f); | |
763 } else if (atom_type == ATOM_IVIV) { | |
764 mp4ff_read_iviv(f, size-8); | |
765 } else if (atom_type == ATOM_NAME) { | |
766 mp4ff_read_name(f, size-8); | |
767 } else if (atom_type == ATOM_PRIV) { | |
768 mp4ff_read_priv(f, size-8); | |
769 #endif | |
770 #ifdef USE_TAGGING | |
771 } else if (atom_type == ATOM_META) { | |
772 /* iTunes Metadata box */ | |
773 mp4ff_read_meta(f, size); | |
774 #endif | |
775 } | |
776 | |
777 mp4ff_set_position(f, dest_position); | |
778 | |
779 | |
780 return 0; | |
781 } |