summaryrefslogtreecommitdiff
path: root/apps/metadata/mp4.c
diff options
context:
space:
mode:
authorSean Bartell <wingedtachikoma@gmail.com>2011-06-24 01:25:21 -0400
committerNils Wallménius <nils@rockbox.org>2012-03-18 12:00:39 +0100
commitb5716df4cb2837bbbc42195cf1aefcf03e21d6a6 (patch)
tree130cd712e2e00893b6df9959a375a8d9523a1aca /apps/metadata/mp4.c
parent24bd9d5393dbe39a5c6194877bc00ede669b1d5d (diff)
downloadrockbox-b5716df4cb2837bbbc42195cf1aefcf03e21d6a6.tar.gz
rockbox-b5716df4cb2837bbbc42195cf1aefcf03e21d6a6.zip
Build librbcodec with DSP and metadata.
All associated files are moved to /lib/rbcodec. Change-Id: I572ddd2b8a996aae1e98c081d06b1ed356dce222
Diffstat (limited to 'apps/metadata/mp4.c')
-rw-r--r--apps/metadata/mp4.c842
1 files changed, 0 insertions, 842 deletions
diff --git a/apps/metadata/mp4.c b/apps/metadata/mp4.c
deleted file mode 100644
index df164436f5..0000000000
--- a/apps/metadata/mp4.c
+++ /dev/null
@@ -1,842 +0,0 @@
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 */
85static 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 */
117static 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
149static 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
187static 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
205static 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
365static 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
579static 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, &timestamp);
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
802bool 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}