summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/metadata.c723
1 files changed, 427 insertions, 296 deletions
diff --git a/apps/metadata.c b/apps/metadata.c
index 1b2dde3a24..ff0cb76cbe 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -22,6 +22,7 @@
22#include <ctype.h> 22#include <ctype.h>
23#include <inttypes.h> 23#include <inttypes.h>
24 24
25#include "errno.h"
25#include "metadata.h" 26#include "metadata.h"
26#include "mp3_playback.h" 27#include "mp3_playback.h"
27#include "logf.h" 28#include "logf.h"
@@ -40,6 +41,37 @@ enum tagtype { TAGTYPE_APE = 1, TAGTYPE_VORBIS };
40#define TAG_NAME_LENGTH 32 41#define TAG_NAME_LENGTH 32
41#define TAG_VALUE_LENGTH 128 42#define TAG_VALUE_LENGTH 128
42 43
44#define MP4_ID(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
45
46#define MP4_3gp6 MP4_ID('3', 'g', 'p', '6')
47#define MP4_alac MP4_ID('a', 'l', 'a', 'c')
48#define MP4_calb MP4_ID(0xa9, 'a', 'l', 'b')
49#define MP4_cART MP4_ID(0xa9, 'A', 'R', 'T')
50#define MP4_cnam MP4_ID(0xa9, 'n', 'a', 'm')
51#define MP4_cwrt MP4_ID(0xa9, 'w', 'r', 't')
52#define MP4_ftyp MP4_ID('f', 't', 'y', 'p')
53#define MP4_gnre MP4_ID('g', 'n', 'r', 'e')
54#define MP4_hdlr MP4_ID('h', 'd', 'l', 'r')
55#define MP4_ilst MP4_ID('i', 'l', 's', 't')
56#define MP4_M4A MP4_ID('M', '4', 'A', ' ')
57#define MP4_mdat MP4_ID('m', 'd', 'a', 't')
58#define MP4_mdia MP4_ID('m', 'd', 'i', 'a')
59#define MP4_mdir MP4_ID('m', 'd', 'i', 'r')
60#define MP4_meta MP4_ID('m', 'e', 't', 'a')
61#define MP4_minf MP4_ID('m', 'i', 'n', 'f')
62#define MP4_moov MP4_ID('m', 'o', 'o', 'v')
63#define MP4_mp4a MP4_ID('m', 'p', '4', 'a')
64#define MP4_mp42 MP4_ID('m', 'p', '4', '2')
65#define MP4_qt MP4_ID('q', 't', ' ', ' ')
66#define MP4_soun MP4_ID('s', 'o', 'u', 'n')
67#define MP4_stbl MP4_ID('s', 't', 'b', 'l')
68#define MP4_stsd MP4_ID('s', 't', 's', 'd')
69#define MP4_stts MP4_ID('s', 't', 't', 's')
70#define MP4_trak MP4_ID('t', 'r', 'a', 'k')
71#define MP4_trkn MP4_ID('t', 'r', 'k', 'n')
72#define MP4_udta MP4_ID('u', 'd', 't', 'a')
73#define MP4_extra MP4_ID('-', '-', '-', '-')
74
43struct apetag_header 75struct apetag_header
44{ 76{
45 char id[8]; 77 char id[8];
@@ -190,28 +222,31 @@ static void convert_endian(void *data, const char *format)
190 } 222 }
191} 223}
192 224
193/* read_uint32be() - read an unsigned integer from a big-endian 225/* Read an unsigned 16-bit integer from a big-endian file. */
194 (e.g. Quicktime) file. This is used by the .m4a parser
195*/
196#ifdef ROCKBOX_BIG_ENDIAN 226#ifdef ROCKBOX_BIG_ENDIAN
197#define read_uint32be(fd,buf) read((fd),(buf),4) 227#define read_uint16be(fd, buf) read((fd), (buf), 2)
198#else 228#else
199int read_uint32be(int fd, unsigned int* buf) { 229int read_uint16be(int fd, unsigned short* buf)
200 char tmp; 230{
201 char* p=(char*)buf; 231 size_t n;
202 size_t n; 232
233 n = read(fd, (char*) buf, 2);
234 *buf = betoh16(*buf);
235 return n;
236}
237#endif
203 238
204 n=read(fd,p,4); 239/* Read an unsigned 32-bit integer from a big-endian file. */
205 if (n==4) { 240#ifdef ROCKBOX_BIG_ENDIAN
206 tmp=p[0]; 241#define read_uint32be(fd,buf) read((fd), (buf), 4)
207 p[0]=p[3]; 242#else
208 p[3]=tmp; 243int read_uint32be(int fd, unsigned int* buf)
209 tmp=p[2]; 244{
210 p[2]=p[1]; 245 size_t n;
211 p[1]=tmp;
212 }
213 246
214 return(n); 247 n = read(fd, (char*) buf, 4);
248 *buf = betoh32(*buf);
249 return n;
215} 250}
216#endif 251#endif
217 252
@@ -921,292 +956,388 @@ static bool get_wave_metadata(int fd, struct mp3entry* id3)
921 return true; 956 return true;
922} 957}
923 958
924static bool get_m4a_metadata(int fd, struct mp3entry* id3) 959/* Read the tag data from an MP4 file, storing up to buffer_size bytes in
960 * buffer.
961 */
962unsigned long read_mp4_tag(int fd, unsigned int size_left, char* buffer,
963 unsigned int buffer_left)
925{ 964{
926 unsigned char* buf; 965 unsigned int bytes_read = 0;
927 unsigned long totalsamples; 966
928 int i,j,k; 967 if (buffer_left == 0)
929 size_t n; 968 {
930 size_t bytes_remaining; 969 lseek(fd, size_left, SEEK_CUR); /* Skip everything */
931 char* id3buf; 970 }
932 unsigned int compressedsize; 971 else
933 unsigned int sample_count; 972 {
934 unsigned int sample_duration; 973 /* Skip the data tag header - maybe we should parse it properly? */
935 int numentries; 974 lseek(fd, 16, SEEK_CUR);
936 int entry_size; 975 size_left -= 16;
937 int size_remaining; 976
938 int chunk_len; 977 if (size_left > buffer_left)
939 unsigned char chunk_id[4]; 978 {
940 int sub_chunk_len; 979 read(fd, buffer, buffer_left);
941 unsigned char sub_chunk_id[4]; 980 lseek(fd, size_left - buffer_left, SEEK_CUR);
942 981 bytes_read = buffer_left;
943 /* A simple parser to read vital metadata from an ALAC file. 982 }
944 This parser also works for AAC files - they are both stored in 983 else
945 a Quicktime M4A container. */ 984 {
946 985 read(fd, buffer, size_left);
947 /* Use the trackname part of the id3 structure as a temporary buffer */ 986 bytes_read = size_left;
948 buf=id3->path; 987 }
949 988 }
950 lseek(fd, 0, SEEK_SET); 989
951 990 return bytes_read;
952 totalsamples=0; 991}
953 compressedsize=0; 992
954 /* read the chunks - we stop when we find the mdat chunk and set compressedsize */ 993/* Read a string tag from an MP4 file */
955 while (compressedsize==0) { 994unsigned int read_mp4_tag_string(int fd, int size_left, char** buffer,
956 n=read_uint32be(fd,&chunk_len); 995 unsigned int* buffer_left, char** dest)
957 996{
958 // This means it was a 64-bit file, so we have problems. 997 unsigned int bytes_read = read_mp4_tag(fd, size_left, *buffer,
959 if (chunk_len == 1) { 998 *buffer_left - 1);
960 logf("need 64bit support\n"); 999 unsigned int length = 0;
961 return false; 1000
962 } 1001 if (bytes_read)
963 1002 {
964 n=read(fd,&chunk_id,4); 1003 (*buffer)[bytes_read] = 0;
965 if (n < 4) 1004 *dest = *buffer;
966 return false; 1005 length = strlen(*buffer) + 1;
967 1006 *buffer_left -= length;
968 if (memcmp(&chunk_id,"ftyp",4)==0) { 1007 *buffer += length;
969 /* Check for M4A type */ 1008 }
970 n=read(fd,&chunk_id,4); 1009 else
971 if ((memcmp(&chunk_id,"M4A ",4)!=0) && 1010 {
972 (memcmp(&chunk_id,"mp42",4)!=0)) { 1011 *dest = NULL;
973 logf("Not an M4A file, aborting\n"); 1012 }
974 return false; 1013
975 } 1014 return length;
976 /* Skip rest of chunk */ 1015}
977 lseek(fd, chunk_len - 8 - 4, SEEK_CUR); /* FIXME not 8 */ 1016
978 } else if (memcmp(&chunk_id,"moov",4)==0) { 1017static unsigned int read_mp4_atom(int fd, unsigned int* size,
979 size_remaining=chunk_len - 8; /* FIXME not 8 */ 1018 unsigned int* type, unsigned int size_left)
980 1019{
981 while (size_remaining > 0) { 1020 read_uint32be(fd, size);
982 n=read_uint32be(fd,&sub_chunk_len); 1021 read_uint32be(fd, type);
983 if ((sub_chunk_len < 1) || (sub_chunk_len > size_remaining)) { 1022
984 logf("Strange sub_chunk_len value inside moov: %d (remaining: %d)\n",sub_chunk_len,size_remaining); 1023 if (*size == 1)
985 return false; 1024 {
1025 /* FAT32 doesn't support files this big, so something seems to
1026 * be wrong. (64-bit sizes should only be used when required.)
1027 */
1028 errno = EFBIG;
1029 *type = 0;
1030 return 0;
1031 }
1032
1033 if (*size > 0)
1034 {
1035 if (*size > size_left)
1036 {
1037 size_left = 0;
986 } 1038 }
987 n=read(fd,&sub_chunk_id,4); 1039 else
988 size_remaining-=8; 1040 {
989 1041 size_left -= *size;
990 if (memcmp(&sub_chunk_id,"mvhd",4)==0) { 1042 }
991 /* We don't need anything from here - skip */ 1043
992 lseek(fd, sub_chunk_len - 8, SEEK_CUR); /* FIXME not 8 */ 1044 *size -= 8;
993 size_remaining-=(sub_chunk_len-8); 1045 }
994 } else if (memcmp(&sub_chunk_id,"udta",4)==0) { 1046 else
995 /* The udta chunk contains the metadata - track, artist, album etc. 1047 {
996 The format appears to be: 1048 *size = size_left;
997 udta 1049 size_left = 0;
998 meta 1050 }
999 hdlr 1051
1000 ilst 1052 return size_left;
1001 .nam 1053}
1002 [rest of tags] 1054
1003 free 1055static bool read_mp4_tags(int fd, struct mp3entry* id3,
1004 1056 unsigned int size_left)
1005 NOTE: This code was written by examination of some .m4a files 1057{
1006 produced by iTunes v4.9 - it may not therefore be 100% 1058 unsigned int size;
1007 compliant with all streams. But it should fail gracefully. 1059 unsigned int type;
1008 */ 1060 unsigned int buffer_left = sizeof(id3->id3v2buf) + sizeof(id3->id3v1buf);
1009 j=(sub_chunk_len-8); 1061 char* buffer = id3->id3v2buf;
1010 size_remaining-=j; 1062 bool cwrt = false;
1011 n=read_uint32be(fd,&sub_chunk_len); 1063
1012 n=read(fd,&sub_chunk_id,4); 1064 do
1013 j-=8; 1065 {
1014 if (memcmp(&sub_chunk_id,"meta",4)==0) { 1066 size_left = read_mp4_atom(fd, &size, &type, size_left);
1015 lseek(fd, 4, SEEK_CUR); 1067
1016 j-=4; 1068 /* DEBUGF("Tag atom: '%c%c%c%c' (%d bytes left)\n", type >> 24 & 0xff,
1017 n=read_uint32be(fd,&sub_chunk_len); 1069 type >> 16 & 0xff, type >> 8 & 0xff, type & 0xff, size); */
1018 n=read(fd,&sub_chunk_id,4); 1070
1019 j-=8; 1071 switch (type)
1020 if (memcmp(&sub_chunk_id,"hdlr",4)==0) { 1072 {
1021 lseek(fd, sub_chunk_len - 8, SEEK_CUR); 1073 case MP4_cnam:
1022 j-=(sub_chunk_len - 8); 1074 read_mp4_tag_string(fd, size, &buffer, &buffer_left,
1023 n=read_uint32be(fd,&sub_chunk_len); 1075 &id3->title);
1024 n=read(fd,&sub_chunk_id,4); 1076 break;
1025 j-=8; 1077
1026 if (memcmp(&sub_chunk_id,"ilst",4)==0) { 1078 case MP4_cART:
1027 /* Here are the actual tags. We use the id3v2 300-byte buffer 1079 read_mp4_tag_string(fd, size, &buffer, &buffer_left,
1028 to store the string data */ 1080 &id3->artist);
1029 bytes_remaining=sizeof(id3->id3v2buf); 1081 break;
1030 id3->genre=255; /* Not every track is the Blues */ 1082
1031 id3buf=id3->id3v2buf; 1083 case MP4_calb:
1032 k=sub_chunk_len-8; 1084 read_mp4_tag_string(fd, size, &buffer, &buffer_left,
1033 j-=k; 1085 &id3->album);
1034 while (k > 0) { 1086 break;
1035 n=read_uint32be(fd,&sub_chunk_len); 1087
1036 n=read(fd,&sub_chunk_id,4); 1088 case MP4_cwrt:
1037 k-=8; 1089 read_mp4_tag_string(fd, size, &buffer, &buffer_left,
1038 if (memcmp(sub_chunk_id,"\251nam",4)==0) { 1090 &id3->composer);
1039 read_m4a_tag_string(fd,sub_chunk_len-8,&id3buf,&bytes_remaining,&id3->title); 1091 cwrt = false;
1040 } else if (memcmp(sub_chunk_id,"\251ART",4)==0) { 1092 break;
1041 read_m4a_tag_string(fd,sub_chunk_len-8,&id3buf,&bytes_remaining,&id3->artist); 1093
1042 } else if (memcmp(sub_chunk_id,"\251alb",4)==0) { 1094 case MP4_gnre:
1043 read_m4a_tag_string(fd,sub_chunk_len-8,&id3buf,&bytes_remaining,&id3->album); 1095 {
1044 } else if (memcmp(sub_chunk_id,"\251gen",4)==0) { 1096 unsigned short genre;
1045 read_m4a_tag_string(fd,sub_chunk_len-8,&id3buf,&bytes_remaining,&id3->genre_string); 1097
1046 } else if (memcmp(sub_chunk_id,"\251day",4)==0) { 1098 read_mp4_tag(fd, size, (char*) &genre, sizeof(genre));
1047 read_m4a_tag_string(fd,sub_chunk_len-8,&id3buf,&bytes_remaining,&id3->year_string); 1099 id3->genre = betoh16(genre);
1048 } else if (memcmp(sub_chunk_id,"trkn",4)==0) { 1100 }
1049 if (sub_chunk_len==0x20) { 1101 break;
1050 read(fd,buf,sub_chunk_len-8); 1102
1051 id3->tracknum=buf[19]; 1103 case MP4_trkn:
1052 } else { 1104 {
1053 lseek(fd, sub_chunk_len-8,SEEK_CUR); 1105 unsigned short n[2];
1106
1107 read_mp4_tag(fd, size, (char*) &n, sizeof(n));
1108 id3->tracknum = betoh16(n[1]);
1109 }
1110 break;
1111
1112 case MP4_extra:
1113 {
1114 char tag_name[TAG_NAME_LENGTH];
1115 unsigned int sub_size;
1116
1117 /* "mean" atom */
1118 read_uint32be(fd, &sub_size);
1119 size -= sub_size;
1120 lseek(fd, sub_size - 4, SEEK_CUR);
1121 /* "name" atom */
1122 read_uint32be(fd, &sub_size);
1123 size -= sub_size;
1124 lseek(fd, 8, SEEK_CUR);
1125 sub_size -= 12;
1126
1127 if (sub_size > sizeof(tag_name) - 1)
1128 {
1129 read(fd, tag_name, sizeof(tag_name) - 1);
1130 lseek(fd, sub_size - sizeof(tag_name) - 1, SEEK_CUR);
1131 tag_name[sizeof(tag_name) - 1] = 0;
1132 }
1133 else
1134 {
1135 read(fd, tag_name, sub_size);
1136 tag_name[sub_size] = 0;
1137 }
1138
1139 if ((strcasecmp(tag_name, "composer") == 0) && !cwrt)
1140 {
1141 read_mp4_tag_string(fd, size, &buffer, &buffer_left,
1142 &id3->composer);
1143 }
1144 else
1145 {
1146 char* any;
1147 unsigned int length = read_mp4_tag_string(fd, size,
1148 &buffer, &buffer_left, &any);
1149
1150 if (length > 0)
1151 {
1152 /* Re-use the read buffer as the dest buffer... */
1153 buffer -= length;
1154 buffer_left += length;
1155
1156 parse_replaygain(tag_name, buffer, id3, buffer,
1157 buffer_left);
1054 } 1158 }
1055 } else {
1056 lseek(fd, sub_chunk_len-8,SEEK_CUR);
1057 }
1058 k-=(sub_chunk_len-8);
1059 } 1159 }
1060 }
1061 } 1160 }
1062 } 1161 break;
1063 /* Skip any remaining data in udta chunk */ 1162
1064 lseek(fd, j, SEEK_CUR); 1163 default:
1065 } else if (memcmp(&sub_chunk_id,"trak",4)==0) { 1164 lseek(fd, size, SEEK_CUR);
1066 /* Format of trak chunk: 1165 break;
1067 tkhd
1068 mdia
1069 mdhd
1070 hdlr
1071 minf
1072 smhd
1073 dinf
1074 stbl
1075 stsd - Samplerate, Samplesize, Numchannels
1076 stts - time_to_sample array - RLE'd table containing duration of each block
1077 stsz - sample_byte_size array - ?Size in bytes of each compressed block
1078 stsc - Seek table related?
1079 stco - Seek table related?
1080 */
1081
1082 /* Skip tkhd - not needed */
1083 n=read_uint32be(fd,&sub_chunk_len);
1084 n=read(fd,&sub_chunk_id,4);
1085 if (memcmp(&sub_chunk_id,"tkhd",4)!=0) {
1086 logf("Expecting tkhd\n");
1087 return false;
1088 }
1089 lseek(fd, sub_chunk_len - 8, SEEK_CUR); /* FIXME not 8 */
1090 size_remaining-=sub_chunk_len;
1091
1092 /* Process mdia - skipping possible edts */
1093 n=read_uint32be(fd,&sub_chunk_len);
1094 n=read(fd,&sub_chunk_id,4);
1095 if (memcmp(&sub_chunk_id,"edts",4)==0) {
1096 lseek(fd, sub_chunk_len - 8, SEEK_CUR); /* FIXME not 8 */
1097 size_remaining-=sub_chunk_len;
1098 n=read_uint32be(fd,&sub_chunk_len);
1099 n=read(fd,&sub_chunk_id,4);
1100 }
1101
1102 if (memcmp(&sub_chunk_id,"mdia",4)!=0) {
1103 logf("Expecting mdia\n");
1104 return false;
1105 }
1106 size_remaining-=sub_chunk_len;
1107 j=sub_chunk_len-8;
1108
1109 while (j > 0) {
1110 n=read_uint32be(fd,&sub_chunk_len);
1111 n=read(fd,&sub_chunk_id,4);
1112 j-=4;
1113 if (memcmp(&sub_chunk_id,"minf",4)==0) {
1114 j=sub_chunk_len-8;
1115 } else if (memcmp(&sub_chunk_id,"stbl",4)==0) {
1116 j=sub_chunk_len-8;
1117 } else if (memcmp(&sub_chunk_id,"stsd",4)==0) {
1118 n=read(fd,buf,sub_chunk_len-8);
1119 j-=sub_chunk_len;
1120 i=0;
1121 /* Skip version and flags */
1122 i+=4;
1123
1124 numentries=(buf[i]<<24)|(buf[i+1]<<16)|(buf[i+2]<<8)|buf[i+3];
1125 i+=4;
1126 if (numentries!=1) {
1127 logf("ERROR: Expecting only one entry in stsd\n");
1128 }
1129
1130 entry_size=(buf[i]<<24)|(buf[i+1]<<16)|(buf[i+2]<<8)|buf[i+3];
1131 i+=4;
1132
1133 if (memcmp(&buf[i],"alac",4)==0) {
1134 id3->codectype=AFMT_ALAC;
1135 } else if (memcmp(&buf[i],"mp4a",4)==0) {
1136 id3->codectype=AFMT_AAC;
1137 } else {
1138 logf("Not an ALAC or AAC file\n");
1139 return false;
1140 }
1141
1142 //numchannels=(buf[i+20]<<8)|buf[i+21]; /* Not used - assume Stereo */
1143 //samplesize=(buf[i+22]<<8)|buf[i+23]; /* Not used - assume 16-bit */
1144
1145 /* Samplerate is 32-bit fixed point, but this works for < 65536 Hz */
1146 id3->frequency=(buf[i+28]<<8)|buf[i+29];
1147 } else if (memcmp(&sub_chunk_id,"stts",4)==0) {
1148 j-=sub_chunk_len;
1149 i=8;
1150 n=read(fd,buf,8);
1151 i+=8;
1152 numentries=(buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7];
1153 for (k=0;k<numentries;k++) {
1154 n=read_uint32be(fd,&sample_count);
1155 n=read_uint32be(fd,&sample_duration);
1156 totalsamples+=sample_count*sample_duration;
1157 i+=8;
1158 }
1159 if (i > 0) lseek(fd, sub_chunk_len - i, SEEK_CUR);
1160 } else if (memcmp(&sub_chunk_id,"stsz",4)==0) {
1161 j-=sub_chunk_len;
1162 i=8;
1163 n=read(fd,buf,8);
1164 i+=8;
1165 numentries=(buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7];
1166 for (k=0;k<numentries;k++) {
1167 n=read_uint32be(fd,&sample_count);
1168 n=read_uint32be(fd,&sample_duration);
1169 totalsamples+=sample_count*sample_duration;
1170 i+=8;
1171 }
1172 if (i > 0) lseek(fd, sub_chunk_len - i, SEEK_CUR);
1173 } else {
1174 lseek(fd, sub_chunk_len - 8, SEEK_CUR); /* FIXME not 8 */
1175 j-=sub_chunk_len;
1176 }
1177 }
1178 } else {
1179 logf("Unexpected sub_chunk_id inside moov: %c%c%c%c\n",
1180 sub_chunk_id[0],sub_chunk_id[1],sub_chunk_id[2],sub_chunk_id[3]);
1181 return false;
1182 } 1166 }
1183 }
1184 } else if (memcmp(&chunk_id,"mdat",4)==0) {
1185 /* once we hit mdat we stop reading and return.
1186 * this is on the assumption that there is no furhter interesting
1187 * stuff in the stream. if there is stuff will fail (:()).
1188 * But we need the read pointer to be at the mdat stuff
1189 * for the decoder. And we don't want to rely on fseek/ftell,
1190 * as they may not always be avilable */
1191 lseek(fd, chunk_len - 8, SEEK_CUR); /* FIXME not 8 */
1192 compressedsize=chunk_len-8;
1193 } else if (memcmp(&chunk_id,"free",4)==0) {
1194 /* these following atoms can be skipped !!!! */
1195 lseek(fd, chunk_len - 8, SEEK_CUR); /* FIXME not 8 */
1196 } else {
1197 logf("(top) unknown chunk id: %c%c%c%c\n", chunk_id[0],chunk_id[1],chunk_id[2],chunk_id[3]);
1198 return false;
1199 } 1167 }
1200 } 1168 while ((size_left > 0) && (errno == 0));
1201 1169
1202 id3->vbr=true; /* All ALAC files are VBR */ 1170 return true;
1203 id3->filesize=filesize(fd); 1171}
1204 id3->samples=totalsamples;
1205 id3->length=(10*totalsamples)/(id3->frequency/100);
1206 id3->bitrate=(compressedsize*8)/id3->length;;
1207 1172
1208 return true; 1173static bool read_mp4_container(int fd, struct mp3entry* id3,
1209} 1174 unsigned int size_left)
1175{
1176 unsigned int size;
1177 unsigned int type;
1178 unsigned int handler = 0;
1179 bool rc = true;
1180
1181 do
1182 {
1183 size_left = read_mp4_atom(fd, &size, &type, size_left);
1184
1185 /* DEBUGF("Atom: '%c%c%c%c' (0x%08x, %d bytes left)\n",
1186 (type >> 24) & 0xff, (type >> 16) & 0xff, (type >> 8) & 0xff,
1187 type & 0xff, type, size); */
1188
1189 switch (type)
1190 {
1191 case MP4_ftyp:
1192 {
1193 unsigned int id;
1194
1195 read_uint32be(fd, &id);
1196 size -= 4;
1197
1198 if ((id != MP4_M4A) && (id != MP4_mp42) && (id != MP4_qt)
1199 && (id != MP4_3gp6))
1200 {
1201 DEBUGF("Unknown MP4 file type: '%c%c%c%c'\n",
1202 id >> 24 & 0xff, id >> 16 & 0xff, id >> 8 & 0xff,
1203 id & 0xff);
1204 return false;
1205 }
1206 }
1207 break;
1208
1209 case MP4_meta:
1210 lseek(fd, 4, SEEK_CUR); /* Skip version */
1211 size -= 4;
1212 /* Fall through */
1213
1214 case MP4_moov:
1215 case MP4_udta:
1216 case MP4_mdia:
1217 case MP4_stbl:
1218 case MP4_trak:
1219 rc = read_mp4_container(fd, id3, size);
1220 size = 0;
1221 break;
1222
1223 case MP4_ilst:
1224 if (handler == MP4_mdir)
1225 {
1226 rc = read_mp4_tags(fd, id3, size);
1227 size = 0;
1228 }
1229 break;
1230
1231 case MP4_minf:
1232 if (handler == MP4_soun)
1233 {
1234 rc = read_mp4_container(fd, id3, size);
1235 size = 0;
1236 }
1237 break;
1238
1239 case MP4_stsd:
1240 lseek(fd, 8, SEEK_CUR);
1241 size -= 8;
1242 rc = read_mp4_container(fd, id3, size);
1243 size = 0;
1244 break;
1245
1246 case MP4_hdlr:
1247 lseek(fd, 8, SEEK_CUR);
1248 read_uint32be(fd, &handler);
1249 size -= 12;
1250 /* DEBUGF(" Handler '%c%c%c%c'\n", handler >> 24 & 0xff,
1251 handler >> 16 & 0xff, handler >> 8 & 0xff,handler & 0xff); */
1252 break;
1253
1254 case MP4_stts:
1255 {
1256 unsigned int entries;
1257 unsigned int i;
1258
1259 lseek(fd, 4, SEEK_CUR);
1260 read_uint32be(fd, &entries);
1261 id3->samples = 0;
1262
1263 for (i = 0; i < entries; i++)
1264 {
1265 unsigned int n;
1266 unsigned int l;
1267
1268 read_uint32be(fd, &n);
1269 read_uint32be(fd, &l);
1270 id3->samples += n * l;
1271 }
1272
1273 size = 0;
1274 }
1275 break;
1276
1277 case MP4_mp4a:
1278 case MP4_alac:
1279 {
1280 unsigned int frequency;
1281
1282 id3->codectype = (type == MP4_mp4a) ? AFMT_AAC : AFMT_ALAC;
1283 lseek(fd, 22, SEEK_CUR);
1284 read_uint32be(fd, &frequency);
1285 size -= 26;
1286 id3->frequency = frequency;
1287 /* There're some child atoms here, but we don't need them */
1288 }
1289 break;
1290
1291 case MP4_mdat:
1292 id3->filesize = size;
1293 break;
1294
1295 default:
1296 break;
1297 }
1298
1299 lseek(fd, size, SEEK_CUR);
1300 }
1301 while (rc && (size_left > 0) && (errno == 0) && (id3->filesize == 0));
1302 /* Break on non-zero filesize, since Rockbox currently doesn't support
1303 * metadata after the mdat atom (which sets the filesize field).
1304 */
1305
1306 return rc;
1307}
1308
1309static bool get_mp4_metadata(int fd, struct mp3entry* id3)
1310{
1311 id3->codectype = AFMT_UNKNOWN;
1312 id3->genre = 255;
1313 id3->filesize = 0;
1314 errno = 0;
1315
1316 if (read_mp4_container(fd, id3, filesize(fd)) && (errno == 0)
1317 && (id3->samples > 0) && (id3->frequency > 0)
1318 && (id3->filesize > 0))
1319 {
1320 if (id3->codectype == AFMT_UNKNOWN)
1321 {
1322 logf("Not an ALAC or AAC file");
1323 return false;
1324 }
1325
1326 id3->length = (id3->samples / id3->frequency) * 1000;
1327 id3->bitrate = ((int64_t) id3->filesize * 8) / id3->length;
1328 DEBUGF("MP4 bitrate %d, frequency %d Hz, length %d ms\n",
1329 id3->bitrate, id3->frequency, id3->length);
1330 }
1331 else
1332 {
1333 logf("MP4 metadata error");
1334 DEBUGF("MP4 metadata error. errno %d, length %d, frequency %d, filesize %d\n",
1335 errno, id3->length, id3->frequency, id3->filesize);
1336 return false;
1337 }
1338
1339 return true;
1340}
1210 1341
1211static bool get_musepack_metadata(int fd, struct mp3entry *id3) 1342static bool get_musepack_metadata(int fd, struct mp3entry *id3)
1212{ 1343{
@@ -1718,7 +1849,7 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname,
1718 1849
1719 case AFMT_ALAC: 1850 case AFMT_ALAC:
1720 case AFMT_AAC: 1851 case AFMT_AAC:
1721 if (!get_m4a_metadata(fd, &(track->id3))) 1852 if (!get_mp4_metadata(fd, &(track->id3)))
1722 { 1853 {
1723 return false; 1854 return false;
1724 } 1855 }