1020
|
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 int8_t *data)
|
|
35 {
|
|
36 uint32_t result;
|
|
37 uint32_t a, b, c, d;
|
|
38
|
|
39 a = (uint8_t)data[0];
|
|
40 b = (uint8_t)data[1];
|
|
41 c = (uint8_t)data[2];
|
|
42 d = (uint8_t)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 int8_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 }
|