diff options
-rw-r--r-- | apps/metadata.c | 159 |
1 files changed, 158 insertions, 1 deletions
diff --git a/apps/metadata.c b/apps/metadata.c index 2f00787e6f..872dfd72f5 100644 --- a/apps/metadata.c +++ b/apps/metadata.c | |||
@@ -49,6 +49,7 @@ enum tagtype { TAGTYPE_APE = 1, TAGTYPE_VORBIS }; | |||
49 | #define MP4_cART MP4_ID(0xa9, 'A', 'R', 'T') | 49 | #define MP4_cART MP4_ID(0xa9, 'A', 'R', 'T') |
50 | #define MP4_cnam MP4_ID(0xa9, 'n', 'a', 'm') | 50 | #define MP4_cnam MP4_ID(0xa9, 'n', 'a', 'm') |
51 | #define MP4_cwrt MP4_ID(0xa9, 'w', 'r', 't') | 51 | #define MP4_cwrt MP4_ID(0xa9, 'w', 'r', 't') |
52 | #define MP4_esds MP4_ID('e', 's', 'd', 's') | ||
52 | #define MP4_ftyp MP4_ID('f', 't', 'y', 'p') | 53 | #define MP4_ftyp MP4_ID('f', 't', 'y', 'p') |
53 | #define MP4_gnre MP4_ID('g', 'n', 'r', 'e') | 54 | #define MP4_gnre MP4_ID('g', 'n', 'r', 'e') |
54 | #define MP4_hdlr MP4_ID('h', 'd', 'l', 'r') | 55 | #define MP4_hdlr MP4_ID('h', 'd', 'l', 'r') |
@@ -228,6 +229,14 @@ static unsigned long get_long(void* buf) | |||
228 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | 229 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); |
229 | } | 230 | } |
230 | 231 | ||
232 | /* Read an unaligned 32-bit big endian long from buffer. */ | ||
233 | static unsigned long get_long_be(void* buf) | ||
234 | { | ||
235 | unsigned char* p = (unsigned char*) buf; | ||
236 | |||
237 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | ||
238 | } | ||
239 | |||
231 | /* Read a string tag from an M4A file */ | 240 | /* Read a string tag from an M4A file */ |
232 | void read_m4a_tag_string(int fd, int len,char** bufptr,size_t* bytes_remaining, char** dest) | 241 | void read_m4a_tag_string(int fd, int len,char** bufptr,size_t* bytes_remaining, char** dest) |
233 | { | 242 | { |
@@ -1036,6 +1045,136 @@ static unsigned int read_mp4_atom(int fd, unsigned int* size, | |||
1036 | return size_left; | 1045 | return size_left; |
1037 | } | 1046 | } |
1038 | 1047 | ||
1048 | static unsigned int read_mp4_length(int fd, unsigned int* size) | ||
1049 | { | ||
1050 | unsigned int length = 0; | ||
1051 | int bytes = 0; | ||
1052 | unsigned char c; | ||
1053 | |||
1054 | do | ||
1055 | { | ||
1056 | read(fd, &c, 1); | ||
1057 | bytes++; | ||
1058 | (*size)--; | ||
1059 | length = (length << 7) | (c & 0x7F); | ||
1060 | } | ||
1061 | while ((c & 0x80) && (bytes < 4) && (*size > 0)); | ||
1062 | |||
1063 | return length; | ||
1064 | } | ||
1065 | |||
1066 | static bool read_mp4_esds(int fd, struct mp3entry* id3, | ||
1067 | unsigned int* size) | ||
1068 | { | ||
1069 | unsigned char buf[8]; | ||
1070 | bool sbr = false; | ||
1071 | |||
1072 | lseek(fd, 4, SEEK_CUR); /* Version and flags. */ | ||
1073 | read(fd, buf, 1); /* Verify ES_DescrTag. */ | ||
1074 | *size -= 5; | ||
1075 | |||
1076 | if (*buf == 3) | ||
1077 | { | ||
1078 | /* read length */ | ||
1079 | if (read_mp4_length(fd, size) < 20) | ||
1080 | { | ||
1081 | return sbr; | ||
1082 | } | ||
1083 | |||
1084 | lseek(fd, 3, SEEK_CUR); | ||
1085 | *size -= 3; | ||
1086 | } | ||
1087 | else | ||
1088 | { | ||
1089 | lseek(fd, 2, SEEK_CUR); | ||
1090 | *size -= 2; | ||
1091 | } | ||
1092 | |||
1093 | read(fd, buf, 1); /* Verify DecoderConfigDescrTab. */ | ||
1094 | *size -= 1; | ||
1095 | |||
1096 | if (*buf != 4) | ||
1097 | { | ||
1098 | return sbr; | ||
1099 | } | ||
1100 | |||
1101 | if (read_mp4_length(fd, size) < 13) | ||
1102 | { | ||
1103 | return sbr; | ||
1104 | } | ||
1105 | |||
1106 | lseek(fd, 13, SEEK_CUR); /* Skip audio type, bit rates, etc. */ | ||
1107 | read(fd, buf, 1); | ||
1108 | *size -= 14; | ||
1109 | |||
1110 | if (*buf != 5) /* Verify DecSpecificInfoTag. */ | ||
1111 | { | ||
1112 | return sbr; | ||
1113 | } | ||
1114 | |||
1115 | { | ||
1116 | static const int sample_rates[] = | ||
1117 | { | ||
1118 | 96000, 88200, 64000, 48000, 44100, 32000, | ||
1119 | 24000, 22050, 16000, 12000, 11025, 8000 | ||
1120 | }; | ||
1121 | unsigned long bits; | ||
1122 | unsigned int length; | ||
1123 | unsigned int index; | ||
1124 | int type; | ||
1125 | |||
1126 | /* Read the (leading part of the) decoder config. */ | ||
1127 | length = read_mp4_length(fd, size); | ||
1128 | length = MIN(length, *size); | ||
1129 | length = MIN(length, sizeof(buf)); | ||
1130 | read(fd, buf, length); | ||
1131 | *size -= length; | ||
1132 | |||
1133 | /* Decoder config format: | ||
1134 | * Object type - 5 bits | ||
1135 | * Frequency index - 4 bits | ||
1136 | * Channel configuration - 4 bits | ||
1137 | */ | ||
1138 | bits = get_long_be(buf); | ||
1139 | type = bits >> 27; | ||
1140 | index = (bits >> 23) & 0xf; | ||
1141 | |||
1142 | if (index < (sizeof(sample_rates) / sizeof(*sample_rates))) | ||
1143 | { | ||
1144 | id3->frequency = sample_rates[index]; | ||
1145 | } | ||
1146 | |||
1147 | if (type == 5) | ||
1148 | { | ||
1149 | sbr = true; | ||
1150 | /* Extended frequency index - 4 bits */ | ||
1151 | index = (bits >> 15) & 0xf; | ||
1152 | |||
1153 | if (index == 15) | ||
1154 | { | ||
1155 | /* 17 bits read so far... */ | ||
1156 | bits = get_long_be(&buf[2]); | ||
1157 | id3->frequency = (bits >> 7) & 0x00FFFFFF; | ||
1158 | } | ||
1159 | else if (index < (sizeof(sample_rates) / sizeof(*sample_rates))) | ||
1160 | { | ||
1161 | id3->frequency = sample_rates[index]; | ||
1162 | } | ||
1163 | } | ||
1164 | else if (id3->frequency < 24000) | ||
1165 | { | ||
1166 | /* SBR not indicated, but the file might still contain SBR. | ||
1167 | * MPEG specification says that one should assume SBR if | ||
1168 | * samplerate <= 24000 Hz. | ||
1169 | */ | ||
1170 | id3->frequency *= 2; | ||
1171 | sbr = true; | ||
1172 | } | ||
1173 | } | ||
1174 | |||
1175 | return sbr; | ||
1176 | } | ||
1177 | |||
1039 | static bool read_mp4_tags(int fd, struct mp3entry* id3, | 1178 | static bool read_mp4_tags(int fd, struct mp3entry* id3, |
1040 | unsigned int size_left) | 1179 | unsigned int size_left) |
1041 | { | 1180 | { |
@@ -1268,7 +1407,25 @@ static bool read_mp4_container(int fd, struct mp3entry* id3, | |||
1268 | read_uint32be(fd, &frequency); | 1407 | read_uint32be(fd, &frequency); |
1269 | size -= 26; | 1408 | size -= 26; |
1270 | id3->frequency = frequency; | 1409 | id3->frequency = frequency; |
1271 | /* There're some child atoms here, but we don't need them */ | 1410 | |
1411 | if (type == MP4_mp4a) | ||
1412 | { | ||
1413 | unsigned int subsize; | ||
1414 | unsigned int subtype; | ||
1415 | |||
1416 | /* Get frequency from the decoder info tag, if possible. */ | ||
1417 | lseek(fd, 2, SEEK_CUR); | ||
1418 | /* The esds atom is a part of the mp4a atom, so ignore | ||
1419 | * the returned size (it's already accounted for). | ||
1420 | */ | ||
1421 | read_mp4_atom(fd, &subsize, &subtype, size); | ||
1422 | size -= 10; | ||
1423 | |||
1424 | if (subtype == MP4_esds) | ||
1425 | { | ||
1426 | read_mp4_esds(fd, id3, &size); | ||
1427 | } | ||
1428 | } | ||
1272 | } | 1429 | } |
1273 | break; | 1430 | break; |
1274 | 1431 | ||