diff options
author | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-02-02 09:38:24 +0000 |
---|---|---|
committer | Andree Buschmann <AndreeBuschmann@t-online.de> | 2011-02-02 09:38:24 +0000 |
commit | 4343399473929fd5e746ceee23350d5c6cb264cf (patch) | |
tree | eb2f2306ada36dd7fdb755cfb03a800e45efe0c3 /apps/metadata/mp4.c | |
parent | 0a93396cdeab4eb96c7e21531a2d9e2dfde15a2b (diff) | |
download | rockbox-4343399473929fd5e746ceee23350d5c6cb264cf.tar.gz rockbox-4343399473929fd5e746ceee23350d5c6cb264cf.zip |
Recognize AAC-HE SBR with upsampling and correct duration, bitrate, seek and resume behaviour for such files. When SBR upsampling is used the decoder outputs the double amount of samples per frame. As the seek and resume functions do not know about this fact a special handling is introduced. Fixes issues reported in FS#11916.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29186 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/metadata/mp4.c')
-rw-r--r-- | apps/metadata/mp4.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/apps/metadata/mp4.c b/apps/metadata/mp4.c index a59b3f9819..c9c691f0c4 100644 --- a/apps/metadata/mp4.c +++ b/apps/metadata/mp4.c | |||
@@ -73,6 +73,9 @@ | |||
73 | #define MP4_udta FOURCC('u', 'd', 't', 'a') | 73 | #define MP4_udta FOURCC('u', 'd', 't', 'a') |
74 | #define MP4_extra FOURCC('-', '-', '-', '-') | 74 | #define MP4_extra FOURCC('-', '-', '-', '-') |
75 | 75 | ||
76 | /* Used to correct id3->samples, if SBR upsampling was detected in esds atom. */ | ||
77 | static bool SBR_upsampling_used = false; | ||
78 | |||
76 | /* Read the tag data from an MP4 file, storing up to buffer_size bytes in | 79 | /* Read the tag data from an MP4 file, storing up to buffer_size bytes in |
77 | * buffer. | 80 | * buffer. |
78 | */ | 81 | */ |
@@ -272,7 +275,6 @@ static bool read_mp4_esds(int fd, struct mp3entry* id3, uint32_t* size) | |||
272 | 275 | ||
273 | if (type == 5) | 276 | if (type == 5) |
274 | { | 277 | { |
275 | DEBUGF("MP4: SBR\n"); | ||
276 | unsigned int old_index = index; | 278 | unsigned int old_index = index; |
277 | 279 | ||
278 | sbr = true; | 280 | sbr = true; |
@@ -342,6 +344,12 @@ static bool read_mp4_esds(int fd, struct mp3entry* id3, uint32_t* size) | |||
342 | * decoding (parts of) the file. | 344 | * decoding (parts of) the file. |
343 | */ | 345 | */ |
344 | id3->frequency *= 2; | 346 | id3->frequency *= 2; |
347 | |||
348 | /* Set this to true to be able to calculate the correct runtime | ||
349 | * and bitrate. */ | ||
350 | SBR_upsampling_used = true; | ||
351 | |||
352 | sbr = true; | ||
345 | } | 353 | } |
346 | } | 354 | } |
347 | 355 | ||
@@ -665,6 +673,7 @@ static bool read_mp4_container(int fd, struct mp3entry* id3, | |||
665 | { | 673 | { |
666 | uint32_t subsize; | 674 | uint32_t subsize; |
667 | uint32_t subtype; | 675 | uint32_t subtype; |
676 | bool sbr_used; | ||
668 | 677 | ||
669 | /* Get frequency from the decoder info tag, if possible. */ | 678 | /* Get frequency from the decoder info tag, if possible. */ |
670 | lseek(fd, 2, SEEK_CUR); | 679 | lseek(fd, 2, SEEK_CUR); |
@@ -676,7 +685,14 @@ static bool read_mp4_container(int fd, struct mp3entry* id3, | |||
676 | 685 | ||
677 | if (subtype == MP4_esds) | 686 | if (subtype == MP4_esds) |
678 | { | 687 | { |
679 | read_mp4_esds(fd, id3, &size); | 688 | sbr_used = read_mp4_esds(fd, id3, &size); |
689 | if (sbr_used) | ||
690 | { | ||
691 | if (SBR_upsampling_used) | ||
692 | DEBUGF("MP4: AAC-HE, SBR upsampling\n"); | ||
693 | else | ||
694 | DEBUGF("MP4: AAC-HE, SBR\n"); | ||
695 | } | ||
680 | } | 696 | } |
681 | } | 697 | } |
682 | } | 698 | } |
@@ -730,6 +746,7 @@ static bool read_mp4_container(int fd, struct mp3entry* id3, | |||
730 | 746 | ||
731 | bool get_mp4_metadata(int fd, struct mp3entry* id3) | 747 | bool get_mp4_metadata(int fd, struct mp3entry* id3) |
732 | { | 748 | { |
749 | SBR_upsampling_used = false; | ||
733 | id3->codectype = AFMT_UNKNOWN; | 750 | id3->codectype = AFMT_UNKNOWN; |
734 | id3->filesize = 0; | 751 | id3->filesize = 0; |
735 | errno = 0; | 752 | errno = 0; |
@@ -743,6 +760,12 @@ bool get_mp4_metadata(int fd, struct mp3entry* id3) | |||
743 | logf("Not an ALAC or AAC file"); | 760 | logf("Not an ALAC or AAC file"); |
744 | return false; | 761 | return false; |
745 | } | 762 | } |
763 | |||
764 | /* SBR upsampling will output double amount of samples per frame. */ | ||
765 | if (SBR_upsampling_used) | ||
766 | { | ||
767 | id3->samples *= 2; | ||
768 | } | ||
746 | 769 | ||
747 | id3->length = ((int64_t) id3->samples * 1000) / id3->frequency; | 770 | id3->length = ((int64_t) id3->samples * 1000) / id3->frequency; |
748 | 771 | ||