diff options
Diffstat (limited to 'lib/rbcodec/metadata/mp4.c')
-rw-r--r-- | lib/rbcodec/metadata/mp4.c | 842 |
1 files changed, 842 insertions, 0 deletions
diff --git a/lib/rbcodec/metadata/mp4.c b/lib/rbcodec/metadata/mp4.c new file mode 100644 index 0000000000..df164436f5 --- /dev/null +++ b/lib/rbcodec/metadata/mp4.c | |||
@@ -0,0 +1,842 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Magnus Holmgren | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include <stdio.h> | ||
22 | #include <string.h> | ||
23 | #include <stdlib.h> | ||
24 | #include <ctype.h> | ||
25 | #include <inttypes.h> | ||
26 | |||
27 | #include "system.h" | ||
28 | #include "errno.h" | ||
29 | #include "metadata.h" | ||
30 | #include "metadata_common.h" | ||
31 | #include "metadata_parsers.h" | ||
32 | #include "logf.h" | ||
33 | #include "debug.h" | ||
34 | #include "replaygain.h" | ||
35 | |||
36 | #ifdef DEBUGF | ||
37 | #undef DEBUGF | ||
38 | #define DEBUGF(...) | ||
39 | #endif | ||
40 | |||
41 | #define MP4_3gp6 FOURCC('3', 'g', 'p', '6') | ||
42 | #define MP4_aART FOURCC('a', 'A', 'R', 'T') | ||
43 | #define MP4_alac FOURCC('a', 'l', 'a', 'c') | ||
44 | #define MP4_calb FOURCC(0xa9, 'a', 'l', 'b') | ||
45 | #define MP4_cART FOURCC(0xa9, 'A', 'R', 'T') | ||
46 | #define MP4_cgrp FOURCC(0xa9, 'g', 'r', 'p') | ||
47 | #define MP4_cgen FOURCC(0xa9, 'g', 'e', 'n') | ||
48 | #define MP4_chpl FOURCC('c', 'h', 'p', 'l') | ||
49 | #define MP4_cnam FOURCC(0xa9, 'n', 'a', 'm') | ||
50 | #define MP4_cwrt FOURCC(0xa9, 'w', 'r', 't') | ||
51 | #define MP4_ccmt FOURCC(0xa9, 'c', 'm', 't') | ||
52 | #define MP4_cday FOURCC(0xa9, 'd', 'a', 'y') | ||
53 | #define MP4_covr FOURCC('c', 'o', 'v', 'r') | ||
54 | #define MP4_disk FOURCC('d', 'i', 's', 'k') | ||
55 | #define MP4_esds FOURCC('e', 's', 'd', 's') | ||
56 | #define MP4_ftyp FOURCC('f', 't', 'y', 'p') | ||
57 | #define MP4_gnre FOURCC('g', 'n', 'r', 'e') | ||
58 | #define MP4_hdlr FOURCC('h', 'd', 'l', 'r') | ||
59 | #define MP4_ilst FOURCC('i', 'l', 's', 't') | ||
60 | #define MP4_isom FOURCC('i', 's', 'o', 'm') | ||
61 | #define MP4_M4A FOURCC('M', '4', 'A', ' ') | ||
62 | #define MP4_m4a FOURCC('m', '4', 'a', ' ') /*technically its "M4A "*/ | ||
63 | #define MP4_M4B FOURCC('M', '4', 'B', ' ') /*but files exist with lower case*/ | ||
64 | #define MP4_mdat FOURCC('m', 'd', 'a', 't') | ||
65 | #define MP4_mdia FOURCC('m', 'd', 'i', 'a') | ||
66 | #define MP4_mdir FOURCC('m', 'd', 'i', 'r') | ||
67 | #define MP4_meta FOURCC('m', 'e', 't', 'a') | ||
68 | #define MP4_minf FOURCC('m', 'i', 'n', 'f') | ||
69 | #define MP4_moov FOURCC('m', 'o', 'o', 'v') | ||
70 | #define MP4_mp4a FOURCC('m', 'p', '4', 'a') | ||
71 | #define MP4_mp42 FOURCC('m', 'p', '4', '2') | ||
72 | #define MP4_qt FOURCC('q', 't', ' ', ' ') | ||
73 | #define MP4_soun FOURCC('s', 'o', 'u', 'n') | ||
74 | #define MP4_stbl FOURCC('s', 't', 'b', 'l') | ||
75 | #define MP4_stsd FOURCC('s', 't', 's', 'd') | ||
76 | #define MP4_stts FOURCC('s', 't', 't', 's') | ||
77 | #define MP4_trak FOURCC('t', 'r', 'a', 'k') | ||
78 | #define MP4_trkn FOURCC('t', 'r', 'k', 'n') | ||
79 | #define MP4_udta FOURCC('u', 'd', 't', 'a') | ||
80 | #define MP4_extra FOURCC('-', '-', '-', '-') | ||
81 | |||
82 | /* Read the tag data from an MP4 file, storing up to buffer_size bytes in | ||
83 | * buffer. | ||
84 | */ | ||
85 | static unsigned long read_mp4_tag(int fd, unsigned int size_left, char* buffer, | ||
86 | unsigned int buffer_left) | ||
87 | { | ||
88 | unsigned int bytes_read = 0; | ||
89 | |||
90 | if (buffer_left == 0) | ||
91 | { | ||
92 | lseek(fd, size_left, SEEK_CUR); /* Skip everything */ | ||
93 | } | ||
94 | else | ||
95 | { | ||
96 | /* Skip the data tag header - maybe we should parse it properly? */ | ||
97 | lseek(fd, 16, SEEK_CUR); | ||
98 | size_left -= 16; | ||
99 | |||
100 | if (size_left > buffer_left) | ||
101 | { | ||
102 | read(fd, buffer, buffer_left); | ||
103 | lseek(fd, size_left - buffer_left, SEEK_CUR); | ||
104 | bytes_read = buffer_left; | ||
105 | } | ||
106 | else | ||
107 | { | ||
108 | read(fd, buffer, size_left); | ||
109 | bytes_read = size_left; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | return bytes_read; | ||
114 | } | ||
115 | |||
116 | /* Read a string tag from an MP4 file */ | ||
117 | static unsigned int read_mp4_tag_string(int fd, int size_left, char** buffer, | ||
118 | unsigned int* buffer_left, char** dest) | ||
119 | { | ||
120 | unsigned int bytes_read = read_mp4_tag(fd, size_left, *buffer, | ||
121 | *buffer_left > 0 ? *buffer_left - 1 : 0); | ||
122 | unsigned int length = 0; | ||
123 | |||
124 | if (bytes_read) | ||
125 | { | ||
126 | /* Do not overwrite already available metadata. Especially when reading | ||
127 | * tags with e.g. multiple genres / artists. This way only the first | ||
128 | * of multiple entries is used, all following are dropped. */ | ||
129 | if (*dest == NULL) | ||
130 | { | ||
131 | (*buffer)[bytes_read] = 0; /* zero-terminate for correct strlen().*/ | ||
132 | length = strlen(*buffer) + 1; | ||
133 | length = MIN(length, ID3V2_MAX_ITEM_SIZE); /* Limit item size. */ | ||
134 | |||
135 | *dest = *buffer; | ||
136 | (*buffer)[length-1] = 0; /* zero-terminate buffer. */ | ||
137 | *buffer_left -= length; | ||
138 | *buffer += length; | ||
139 | } | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | *dest = NULL; | ||
144 | } | ||
145 | |||
146 | return length; | ||
147 | } | ||
148 | |||
149 | static unsigned int read_mp4_atom(int fd, uint32_t* size, | ||
150 | uint32_t* type, uint32_t size_left) | ||
151 | { | ||
152 | read_uint32be(fd, size); | ||
153 | read_uint32be(fd, type); | ||
154 | |||
155 | if (*size == 1) | ||
156 | { | ||
157 | /* FAT32 doesn't support files this big, so something seems to | ||
158 | * be wrong. (64-bit sizes should only be used when required.) | ||
159 | */ | ||
160 | errno = EFBIG; | ||
161 | *type = 0; | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | if (*size > 0) | ||
166 | { | ||
167 | if (*size > size_left) | ||
168 | { | ||
169 | size_left = 0; | ||
170 | } | ||
171 | else | ||
172 | { | ||
173 | size_left -= *size; | ||
174 | } | ||
175 | |||
176 | *size -= 8; | ||
177 | } | ||
178 | else | ||
179 | { | ||
180 | *size = size_left; | ||
181 | size_left = 0; | ||
182 | } | ||
183 | |||
184 | return size_left; | ||
185 | } | ||
186 | |||
187 | static unsigned int read_mp4_length(int fd, uint32_t* size) | ||
188 | { | ||
189 | unsigned int length = 0; | ||
190 | int bytes = 0; | ||
191 | unsigned char c; | ||
192 | |||
193 | do | ||
194 | { | ||
195 | read(fd, &c, 1); | ||
196 | bytes++; | ||
197 | (*size)--; | ||
198 | length = (length << 7) | (c & 0x7F); | ||
199 | } | ||
200 | while ((c & 0x80) && (bytes < 4) && (*size > 0)); | ||
201 | |||
202 | return length; | ||
203 | } | ||
204 | |||
205 | static bool read_mp4_esds(int fd, struct mp3entry* id3, uint32_t* size) | ||
206 | { | ||
207 | unsigned char buf[8]; | ||
208 | bool sbr = false; | ||
209 | |||
210 | lseek(fd, 4, SEEK_CUR); /* Version and flags. */ | ||
211 | read(fd, buf, 1); /* Verify ES_DescrTag. */ | ||
212 | *size -= 5; | ||
213 | |||
214 | if (*buf == 3) | ||
215 | { | ||
216 | /* read length */ | ||
217 | if (read_mp4_length(fd, size) < 20) | ||
218 | { | ||
219 | return sbr; | ||
220 | } | ||
221 | |||
222 | lseek(fd, 3, SEEK_CUR); | ||
223 | *size -= 3; | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | lseek(fd, 2, SEEK_CUR); | ||
228 | *size -= 2; | ||
229 | } | ||
230 | |||
231 | read(fd, buf, 1); /* Verify DecoderConfigDescrTab. */ | ||
232 | *size -= 1; | ||
233 | |||
234 | if (*buf != 4) | ||
235 | { | ||
236 | return sbr; | ||
237 | } | ||
238 | |||
239 | if (read_mp4_length(fd, size) < 13) | ||
240 | { | ||
241 | return sbr; | ||
242 | } | ||
243 | |||
244 | lseek(fd, 13, SEEK_CUR); /* Skip audio type, bit rates, etc. */ | ||
245 | read(fd, buf, 1); | ||
246 | *size -= 14; | ||
247 | |||
248 | if (*buf != 5) /* Verify DecSpecificInfoTag. */ | ||
249 | { | ||
250 | return sbr; | ||
251 | } | ||
252 | |||
253 | { | ||
254 | static const int sample_rates[] = | ||
255 | { | ||
256 | 96000, 88200, 64000, 48000, 44100, 32000, | ||
257 | 24000, 22050, 16000, 12000, 11025, 8000 | ||
258 | }; | ||
259 | unsigned long bits; | ||
260 | unsigned int length; | ||
261 | unsigned int index; | ||
262 | unsigned int type; | ||
263 | |||
264 | /* Read the (leading part of the) decoder config. */ | ||
265 | length = read_mp4_length(fd, size); | ||
266 | length = MIN(length, *size); | ||
267 | length = MIN(length, sizeof(buf)); | ||
268 | memset(buf, 0, sizeof(buf)); | ||
269 | read(fd, buf, length); | ||
270 | *size -= length; | ||
271 | |||
272 | /* Maybe time to write a simple read_bits function... */ | ||
273 | |||
274 | /* Decoder config format: | ||
275 | * Object type - 5 bits | ||
276 | * Frequency index - 4 bits | ||
277 | * Channel configuration - 4 bits | ||
278 | */ | ||
279 | bits = get_long_be(buf); | ||
280 | type = bits >> 27; /* Object type - 5 bits */ | ||
281 | index = (bits >> 23) & 0xf; /* Frequency index - 4 bits */ | ||
282 | |||
283 | if (index < (sizeof(sample_rates) / sizeof(*sample_rates))) | ||
284 | { | ||
285 | id3->frequency = sample_rates[index]; | ||
286 | } | ||
287 | |||
288 | if (type == 5) | ||
289 | { | ||
290 | unsigned int old_index = index; | ||
291 | |||
292 | sbr = true; | ||
293 | index = (bits >> 15) & 0xf; /* Frequency index - 4 bits */ | ||
294 | |||
295 | if (index == 15) | ||
296 | { | ||
297 | /* 17 bits read so far... */ | ||
298 | bits = get_long_be(&buf[2]); | ||
299 | id3->frequency = (bits >> 7) & 0x00ffffff; | ||
300 | } | ||
301 | else if (index < (sizeof(sample_rates) / sizeof(*sample_rates))) | ||
302 | { | ||
303 | id3->frequency = sample_rates[index]; | ||
304 | } | ||
305 | |||
306 | if (old_index == index) | ||
307 | { | ||
308 | /* Downsampled SBR */ | ||
309 | id3->frequency *= 2; | ||
310 | } | ||
311 | } | ||
312 | /* Skip 13 bits from above, plus 3 bits, then read 11 bits */ | ||
313 | else if ((length >= 4) && (((bits >> 5) & 0x7ff) == 0x2b7)) | ||
314 | { | ||
315 | /* We found an extensionAudioObjectType */ | ||
316 | type = bits & 0x1f; /* Object type - 5 bits*/ | ||
317 | bits = get_long_be(&buf[4]); | ||
318 | |||
319 | if (type == 5) | ||
320 | { | ||
321 | sbr = bits >> 31; | ||
322 | |||
323 | if (sbr) | ||
324 | { | ||
325 | unsigned int old_index = index; | ||
326 | |||
327 | /* 1 bit read so far */ | ||
328 | index = (bits >> 27) & 0xf; /* Frequency index - 4 bits */ | ||
329 | |||
330 | if (index == 15) | ||
331 | { | ||
332 | /* 5 bits read so far */ | ||
333 | id3->frequency = (bits >> 3) & 0x00ffffff; | ||
334 | } | ||
335 | else if (index < (sizeof(sample_rates) / sizeof(*sample_rates))) | ||
336 | { | ||
337 | id3->frequency = sample_rates[index]; | ||
338 | } | ||
339 | |||
340 | if (old_index == index) | ||
341 | { | ||
342 | /* Downsampled SBR */ | ||
343 | id3->frequency *= 2; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | } | ||
348 | |||
349 | if (!sbr && (id3->frequency <= 24000) && (length <= 2)) | ||
350 | { | ||
351 | /* Double the frequency for low-frequency files without a "long" | ||
352 | * DecSpecificConfig header. The file may or may not contain SBR, | ||
353 | * but here we guess it does if the header is short. This can | ||
354 | * fail on some files, but it's the best we can do, short of | ||
355 | * decoding (parts of) the file. | ||
356 | */ | ||
357 | id3->frequency *= 2; | ||
358 | sbr = true; | ||
359 | } | ||
360 | } | ||
361 | |||
362 | return sbr; | ||
363 | } | ||
364 | |||
365 | static bool read_mp4_tags(int fd, struct mp3entry* id3, | ||
366 | uint32_t size_left) | ||
367 | { | ||
368 | uint32_t size; | ||
369 | uint32_t type; | ||
370 | unsigned int buffer_left = sizeof(id3->id3v2buf) + sizeof(id3->id3v1buf); | ||
371 | char* buffer = id3->id3v2buf; | ||
372 | bool cwrt = false; | ||
373 | |||
374 | do | ||
375 | { | ||
376 | size_left = read_mp4_atom(fd, &size, &type, size_left); | ||
377 | |||
378 | /* DEBUGF("Tag atom: '%c%c%c%c' (%d bytes left)\n", type >> 24 & 0xff, | ||
379 | type >> 16 & 0xff, type >> 8 & 0xff, type & 0xff, size); */ | ||
380 | |||
381 | switch (type) | ||
382 | { | ||
383 | case MP4_cnam: | ||
384 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
385 | &id3->title); | ||
386 | break; | ||
387 | |||
388 | case MP4_cART: | ||
389 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
390 | &id3->artist); | ||
391 | break; | ||
392 | |||
393 | case MP4_aART: | ||
394 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
395 | &id3->albumartist); | ||
396 | break; | ||
397 | |||
398 | case MP4_cgrp: | ||
399 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
400 | &id3->grouping); | ||
401 | break; | ||
402 | |||
403 | case MP4_calb: | ||
404 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
405 | &id3->album); | ||
406 | break; | ||
407 | |||
408 | case MP4_cwrt: | ||
409 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
410 | &id3->composer); | ||
411 | cwrt = false; | ||
412 | break; | ||
413 | |||
414 | case MP4_ccmt: | ||
415 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
416 | &id3->comment); | ||
417 | break; | ||
418 | |||
419 | case MP4_cday: | ||
420 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
421 | &id3->year_string); | ||
422 | |||
423 | /* Try to parse it as a year, for the benefit of the database. | ||
424 | */ | ||
425 | if(id3->year_string) | ||
426 | { | ||
427 | id3->year = atoi(id3->year_string); | ||
428 | if (id3->year < 1900) | ||
429 | { | ||
430 | id3->year = 0; | ||
431 | } | ||
432 | } | ||
433 | else | ||
434 | id3->year = 0; | ||
435 | |||
436 | break; | ||
437 | |||
438 | case MP4_gnre: | ||
439 | { | ||
440 | unsigned short genre; | ||
441 | |||
442 | read_mp4_tag(fd, size, (char*) &genre, sizeof(genre)); | ||
443 | id3->genre_string = id3_get_num_genre(betoh16(genre) - 1); | ||
444 | } | ||
445 | break; | ||
446 | |||
447 | case MP4_cgen: | ||
448 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
449 | &id3->genre_string); | ||
450 | break; | ||
451 | |||
452 | case MP4_disk: | ||
453 | { | ||
454 | unsigned short n[2]; | ||
455 | |||
456 | read_mp4_tag(fd, size, (char*) &n, sizeof(n)); | ||
457 | id3->discnum = betoh16(n[1]); | ||
458 | } | ||
459 | break; | ||
460 | |||
461 | case MP4_trkn: | ||
462 | { | ||
463 | unsigned short n[2]; | ||
464 | |||
465 | read_mp4_tag(fd, size, (char*) &n, sizeof(n)); | ||
466 | id3->tracknum = betoh16(n[1]); | ||
467 | } | ||
468 | break; | ||
469 | |||
470 | #ifdef HAVE_ALBUMART | ||
471 | case MP4_covr: | ||
472 | { | ||
473 | int pos = lseek(fd, 0, SEEK_CUR) + 16; | ||
474 | |||
475 | read_mp4_tag(fd, size, buffer, 8); | ||
476 | id3->albumart.type = AA_TYPE_UNKNOWN; | ||
477 | if (memcmp(buffer, "\xff\xd8\xff\xe0", 4) == 0) | ||
478 | { | ||
479 | id3->albumart.type = AA_TYPE_JPG; | ||
480 | } | ||
481 | else if (memcmp(buffer, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0) | ||
482 | { | ||
483 | id3->albumart.type = AA_TYPE_PNG; | ||
484 | } | ||
485 | |||
486 | if (id3->albumart.type != AA_TYPE_UNKNOWN) | ||
487 | { | ||
488 | id3->albumart.pos = pos; | ||
489 | id3->albumart.size = size - 16; | ||
490 | id3->has_embedded_albumart = true; | ||
491 | } | ||
492 | } | ||
493 | break; | ||
494 | #endif | ||
495 | |||
496 | case MP4_extra: | ||
497 | { | ||
498 | char tag_name[TAG_NAME_LENGTH]; | ||
499 | uint32_t sub_size; | ||
500 | |||
501 | /* "mean" atom */ | ||
502 | read_uint32be(fd, &sub_size); | ||
503 | size -= sub_size; | ||
504 | lseek(fd, sub_size - 4, SEEK_CUR); | ||
505 | /* "name" atom */ | ||
506 | read_uint32be(fd, &sub_size); | ||
507 | size -= sub_size; | ||
508 | lseek(fd, 8, SEEK_CUR); | ||
509 | sub_size -= 12; | ||
510 | |||
511 | if (sub_size > sizeof(tag_name) - 1) | ||
512 | { | ||
513 | read(fd, tag_name, sizeof(tag_name) - 1); | ||
514 | lseek(fd, sub_size - (sizeof(tag_name) - 1), SEEK_CUR); | ||
515 | tag_name[sizeof(tag_name) - 1] = 0; | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | read(fd, tag_name, sub_size); | ||
520 | tag_name[sub_size] = 0; | ||
521 | } | ||
522 | |||
523 | if ((strcasecmp(tag_name, "composer") == 0) && !cwrt) | ||
524 | { | ||
525 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
526 | &id3->composer); | ||
527 | } | ||
528 | else if (strcasecmp(tag_name, "iTunSMPB") == 0) | ||
529 | { | ||
530 | char value[TAG_VALUE_LENGTH]; | ||
531 | char* value_p = value; | ||
532 | char* any; | ||
533 | unsigned int length = sizeof(value); | ||
534 | |||
535 | read_mp4_tag_string(fd, size, &value_p, &length, &any); | ||
536 | id3->lead_trim = get_itunes_int32(value, 1); | ||
537 | id3->tail_trim = get_itunes_int32(value, 2); | ||
538 | DEBUGF("AAC: lead_trim %d, tail_trim %d\n", | ||
539 | id3->lead_trim, id3->tail_trim); | ||
540 | } | ||
541 | else if (strcasecmp(tag_name, "musicbrainz track id") == 0) | ||
542 | { | ||
543 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
544 | &id3->mb_track_id); | ||
545 | } | ||
546 | else if ((strcasecmp(tag_name, "album artist") == 0)) | ||
547 | { | ||
548 | read_mp4_tag_string(fd, size, &buffer, &buffer_left, | ||
549 | &id3->albumartist); | ||
550 | } | ||
551 | else | ||
552 | { | ||
553 | char* any = NULL; | ||
554 | unsigned int length = read_mp4_tag_string(fd, size, | ||
555 | &buffer, &buffer_left, &any); | ||
556 | |||
557 | if (length > 0) | ||
558 | { | ||
559 | /* Re-use the read buffer as the dest buffer... */ | ||
560 | buffer -= length; | ||
561 | buffer_left += length; | ||
562 | |||
563 | parse_replaygain(tag_name, buffer, id3); | ||
564 | } | ||
565 | } | ||
566 | } | ||
567 | break; | ||
568 | |||
569 | default: | ||
570 | lseek(fd, size, SEEK_CUR); | ||
571 | break; | ||
572 | } | ||
573 | } | ||
574 | while ((size_left > 0) && (errno == 0)); | ||
575 | |||
576 | return true; | ||
577 | } | ||
578 | |||
579 | static bool read_mp4_container(int fd, struct mp3entry* id3, | ||
580 | uint32_t size_left) | ||
581 | { | ||
582 | uint32_t size = 0; | ||
583 | uint32_t type = 0; | ||
584 | uint32_t handler = 0; | ||
585 | bool rc = true; | ||
586 | bool done = false; | ||
587 | |||
588 | do | ||
589 | { | ||
590 | size_left = read_mp4_atom(fd, &size, &type, size_left); | ||
591 | |||
592 | /* DEBUGF("Atom: '%c%c%c%c' (0x%08lx, %lu bytes left)\n", | ||
593 | (int) ((type >> 24) & 0xff), (int) ((type >> 16) & 0xff), | ||
594 | (int) ((type >> 8) & 0xff), (int) (type & 0xff), | ||
595 | type, size); */ | ||
596 | |||
597 | switch (type) | ||
598 | { | ||
599 | case MP4_ftyp: | ||
600 | { | ||
601 | uint32_t id; | ||
602 | |||
603 | read_uint32be(fd, &id); | ||
604 | size -= 4; | ||
605 | |||
606 | if ((id != MP4_M4A) && (id != MP4_M4B) && (id != MP4_mp42) | ||
607 | && (id != MP4_qt) && (id != MP4_3gp6) && (id != MP4_m4a) | ||
608 | && (id != MP4_isom)) | ||
609 | { | ||
610 | DEBUGF("Unknown MP4 file type: '%c%c%c%c'\n", | ||
611 | (int)(id >> 24 & 0xff), (int)(id >> 16 & 0xff), | ||
612 | (int)(id >> 8 & 0xff), (int)(id & 0xff)); | ||
613 | return false; | ||
614 | } | ||
615 | } | ||
616 | break; | ||
617 | |||
618 | case MP4_meta: | ||
619 | lseek(fd, 4, SEEK_CUR); /* Skip version */ | ||
620 | size -= 4; | ||
621 | /* Fall through */ | ||
622 | |||
623 | case MP4_moov: | ||
624 | case MP4_udta: | ||
625 | case MP4_mdia: | ||
626 | case MP4_stbl: | ||
627 | case MP4_trak: | ||
628 | rc = read_mp4_container(fd, id3, size); | ||
629 | size = 0; | ||
630 | break; | ||
631 | |||
632 | case MP4_ilst: | ||
633 | /* We need at least a size of 8 to read the next atom. */ | ||
634 | if (handler == MP4_mdir && size>8) | ||
635 | { | ||
636 | rc = read_mp4_tags(fd, id3, size); | ||
637 | size = 0; | ||
638 | } | ||
639 | break; | ||
640 | |||
641 | case MP4_minf: | ||
642 | if (handler == MP4_soun) | ||
643 | { | ||
644 | rc = read_mp4_container(fd, id3, size); | ||
645 | size = 0; | ||
646 | } | ||
647 | break; | ||
648 | |||
649 | case MP4_stsd: | ||
650 | lseek(fd, 8, SEEK_CUR); | ||
651 | size -= 8; | ||
652 | rc = read_mp4_container(fd, id3, size); | ||
653 | size = 0; | ||
654 | break; | ||
655 | |||
656 | case MP4_hdlr: | ||
657 | lseek(fd, 8, SEEK_CUR); | ||
658 | read_uint32be(fd, &handler); | ||
659 | size -= 12; | ||
660 | /* DEBUGF(" Handler '%c%c%c%c'\n", handler >> 24 & 0xff, | ||
661 | handler >> 16 & 0xff, handler >> 8 & 0xff,handler & 0xff); */ | ||
662 | break; | ||
663 | |||
664 | case MP4_stts: | ||
665 | { | ||
666 | uint32_t entries; | ||
667 | unsigned int i; | ||
668 | |||
669 | /* Reset to false. */ | ||
670 | id3->needs_upsampling_correction = false; | ||
671 | |||
672 | lseek(fd, 4, SEEK_CUR); | ||
673 | read_uint32be(fd, &entries); | ||
674 | id3->samples = 0; | ||
675 | |||
676 | for (i = 0; i < entries; i++) | ||
677 | { | ||
678 | uint32_t n; | ||
679 | uint32_t l; | ||
680 | |||
681 | read_uint32be(fd, &n); | ||
682 | read_uint32be(fd, &l); | ||
683 | |||
684 | /* Some AAC file use HE profile. In this case the number | ||
685 | * of output samples is doubled to a maximum of 2048 | ||
686 | * samples per frame. This means that files which already | ||
687 | * report a frame size of 2048 in their header will not | ||
688 | * need any further special handling. */ | ||
689 | if (id3->codectype==AFMT_MP4_AAC_HE && l<=1024) | ||
690 | { | ||
691 | id3->samples += n * l * 2; | ||
692 | id3->needs_upsampling_correction = true; | ||
693 | } | ||
694 | else | ||
695 | { | ||
696 | id3->samples += n * l; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | size = 0; | ||
701 | } | ||
702 | break; | ||
703 | |||
704 | case MP4_mp4a: | ||
705 | { | ||
706 | uint32_t subsize; | ||
707 | uint32_t subtype; | ||
708 | |||
709 | /* Move to the next expected mp4 atom. */ | ||
710 | lseek(fd, 28, SEEK_CUR); | ||
711 | read_mp4_atom(fd, &subsize, &subtype, size); | ||
712 | size -= 36; | ||
713 | |||
714 | if (subtype == MP4_esds) | ||
715 | { | ||
716 | /* Read esds metadata and return if AAC-HE/SBR is used. */ | ||
717 | if (read_mp4_esds(fd, id3, &size)) | ||
718 | id3->codectype = AFMT_MP4_AAC_HE; | ||
719 | else | ||
720 | id3->codectype = AFMT_MP4_AAC; | ||
721 | } | ||
722 | } | ||
723 | break; | ||
724 | |||
725 | case MP4_alac: | ||
726 | { | ||
727 | uint32_t frequency; | ||
728 | uint32_t subsize; | ||
729 | uint32_t subtype; | ||
730 | |||
731 | /* Move to the next expected mp4 atom. */ | ||
732 | lseek(fd, 28, SEEK_CUR); | ||
733 | read_mp4_atom(fd, &subsize, &subtype, size); | ||
734 | size -= 36; | ||
735 | #if 0 | ||
736 | /* We might need to parse for the alac metadata atom. */ | ||
737 | while (!((subsize==28) && (subtype==MP4_alac)) && (size>0)) | ||
738 | { | ||
739 | lseek(fd, -7, SEEK_CUR); | ||
740 | read_mp4_atom(fd, &subsize, &subtype, size); | ||
741 | size -= 1; | ||
742 | errno = 0; /* will most likely be set while parsing */ | ||
743 | } | ||
744 | #endif | ||
745 | if (subtype == MP4_alac) | ||
746 | { | ||
747 | lseek(fd, 24, SEEK_CUR); | ||
748 | read_uint32be(fd, &frequency); | ||
749 | size -= 28; | ||
750 | id3->frequency = frequency; | ||
751 | id3->codectype = AFMT_MP4_ALAC; | ||
752 | } | ||
753 | } | ||
754 | break; | ||
755 | |||
756 | case MP4_mdat: | ||
757 | /* Some AAC files appear to contain additional empty mdat chunks. | ||
758 | Ignore them. */ | ||
759 | if(size == 0) | ||
760 | break; | ||
761 | id3->filesize = size; | ||
762 | if(id3->samples > 0) { | ||
763 | /* We've already seen the moov chunk. */ | ||
764 | done = true; | ||
765 | } | ||
766 | break; | ||
767 | |||
768 | case MP4_chpl: | ||
769 | { | ||
770 | /* ADDME: add support for real chapters. Right now it's only | ||
771 | * used for Nero's gapless hack */ | ||
772 | uint8_t chapters; | ||
773 | uint64_t timestamp; | ||
774 | |||
775 | lseek(fd, 8, SEEK_CUR); | ||
776 | read_uint8(fd, &chapters); | ||
777 | size -= 9; | ||
778 | |||
779 | /* the first chapter will be used as the lead_trim */ | ||
780 | if (chapters > 0) { | ||
781 | read_uint64be(fd, ×tamp); | ||
782 | id3->lead_trim = (timestamp * id3->frequency) / 10000000; | ||
783 | size -= 8; | ||
784 | } | ||
785 | } | ||
786 | break; | ||
787 | |||
788 | default: | ||
789 | break; | ||
790 | } | ||
791 | |||
792 | /* Skip final seek. */ | ||
793 | if (!done) | ||
794 | { | ||
795 | lseek(fd, size, SEEK_CUR); | ||
796 | } | ||
797 | } while (rc && (size_left > 0) && (errno == 0) && !done); | ||
798 | |||
799 | return rc; | ||
800 | } | ||
801 | |||
802 | bool get_mp4_metadata(int fd, struct mp3entry* id3) | ||
803 | { | ||
804 | id3->codectype = AFMT_UNKNOWN; | ||
805 | id3->filesize = 0; | ||
806 | errno = 0; | ||
807 | |||
808 | if (read_mp4_container(fd, id3, filesize(fd)) && (errno == 0) | ||
809 | && (id3->samples > 0) && (id3->frequency > 0) | ||
810 | && (id3->filesize > 0)) | ||
811 | { | ||
812 | if (id3->codectype == AFMT_UNKNOWN) | ||
813 | { | ||
814 | logf("Not an ALAC or AAC file"); | ||
815 | return false; | ||
816 | } | ||
817 | |||
818 | id3->length = ((int64_t) id3->samples * 1000) / id3->frequency; | ||
819 | |||
820 | id3->vbr = true; /* ALAC is native VBR, AAC very unlikely is CBR. */ | ||
821 | |||
822 | if (id3->length <= 0) | ||
823 | { | ||
824 | logf("mp4 length invalid!"); | ||
825 | return false; | ||
826 | } | ||
827 | |||
828 | id3->bitrate = ((int64_t) id3->filesize * 8) / id3->length; | ||
829 | DEBUGF("MP4 bitrate %d, frequency %ld Hz, length %ld ms\n", | ||
830 | id3->bitrate, id3->frequency, id3->length); | ||
831 | } | ||
832 | else | ||
833 | { | ||
834 | logf("MP4 metadata error"); | ||
835 | DEBUGF("MP4 metadata error. errno %d, samples %ld, frequency %ld, " | ||
836 | "filesize %ld\n", errno, id3->samples, id3->frequency, | ||
837 | id3->filesize); | ||
838 | return false; | ||
839 | } | ||
840 | |||
841 | return true; | ||
842 | } | ||