00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00029 #include "id3v2.h"
00030 #include "id3v1.h"
00031 #include "libavutil/avstring.h"
00032 #include "libavutil/intreadwrite.h"
00033 #include "libavutil/dict.h"
00034 #include "avio_internal.h"
00035
00036 int ff_id3v2_match(const uint8_t *buf, const char * magic)
00037 {
00038 return buf[0] == magic[0] &&
00039 buf[1] == magic[1] &&
00040 buf[2] == magic[2] &&
00041 buf[3] != 0xff &&
00042 buf[4] != 0xff &&
00043 (buf[6] & 0x80) == 0 &&
00044 (buf[7] & 0x80) == 0 &&
00045 (buf[8] & 0x80) == 0 &&
00046 (buf[9] & 0x80) == 0;
00047 }
00048
00049 int ff_id3v2_tag_len(const uint8_t * buf)
00050 {
00051 int len = ((buf[6] & 0x7f) << 21) +
00052 ((buf[7] & 0x7f) << 14) +
00053 ((buf[8] & 0x7f) << 7) +
00054 (buf[9] & 0x7f) +
00055 ID3v2_HEADER_SIZE;
00056 if (buf[5] & 0x10)
00057 len += ID3v2_HEADER_SIZE;
00058 return len;
00059 }
00060
00061 static unsigned int get_size(AVIOContext *s, int len)
00062 {
00063 int v = 0;
00064 while (len--)
00065 v = (v << 7) + (avio_r8(s) & 0x7F);
00066 return v;
00067 }
00068
00069 static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key)
00070 {
00071 char *q, dst[512];
00072 const char *val = NULL;
00073 int len, dstlen = sizeof(dst) - 1;
00074 unsigned genre;
00075 unsigned int (*get)(AVIOContext*) = avio_rb16;
00076
00077 dst[0] = 0;
00078 if (taglen < 1)
00079 return;
00080
00081 taglen--;
00082
00083 switch (avio_r8(pb)) {
00084
00085 case ID3v2_ENCODING_ISO8859:
00086 q = dst;
00087 while (taglen-- && q - dst < dstlen - 7) {
00088 uint8_t tmp;
00089 PUT_UTF8(avio_r8(pb), tmp, *q++ = tmp;)
00090 }
00091 *q = 0;
00092 break;
00093
00094 case ID3v2_ENCODING_UTF16BOM:
00095 taglen -= 2;
00096 switch (avio_rb16(pb)) {
00097 case 0xfffe:
00098 get = avio_rl16;
00099 case 0xfeff:
00100 break;
00101 default:
00102 av_log(s, AV_LOG_ERROR, "Incorrect BOM value in tag %s.\n", key);
00103 return;
00104 }
00105
00106
00107 case ID3v2_ENCODING_UTF16BE:
00108 q = dst;
00109 while (taglen > 1 && q - dst < dstlen - 7) {
00110 uint32_t ch;
00111 uint8_t tmp;
00112
00113 GET_UTF16(ch, ((taglen -= 2) >= 0 ? get(pb) : 0), break;)
00114 PUT_UTF8(ch, tmp, *q++ = tmp;)
00115 }
00116 *q = 0;
00117 break;
00118
00119 case ID3v2_ENCODING_UTF8:
00120 len = FFMIN(taglen, dstlen);
00121 avio_read(pb, dst, len);
00122 dst[len] = 0;
00123 break;
00124 default:
00125 av_log(s, AV_LOG_WARNING, "Unknown encoding in tag %s.\n", key);
00126 }
00127
00128 if (!(strcmp(key, "TCON") && strcmp(key, "TCO"))
00129 && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1)
00130 && genre <= ID3v1_GENRE_MAX)
00131 val = ff_id3v1_genre_str[genre];
00132 else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
00133
00134 dst[dstlen] = 0;
00135 len = strlen(dst);
00136 key = dst;
00137 val = dst + FFMIN(len + 1, dstlen);
00138 }
00139 else if (*dst)
00140 val = dst;
00141
00142 if (val)
00143 av_dict_set(&s->metadata, key, val, AV_DICT_DONT_OVERWRITE);
00144 }
00145
00146 static int is_number(const char *str)
00147 {
00148 while (*str >= '0' && *str <= '9') str++;
00149 return !*str;
00150 }
00151
00152 static AVDictionaryEntry* get_date_tag(AVDictionary *m, const char *tag)
00153 {
00154 AVDictionaryEntry *t;
00155 if ((t = av_dict_get(m, tag, NULL, AV_DICT_MATCH_CASE)) &&
00156 strlen(t->value) == 4 && is_number(t->value))
00157 return t;
00158 return NULL;
00159 }
00160
00161 static void merge_date(AVDictionary **m)
00162 {
00163 AVDictionaryEntry *t;
00164 char date[17] = {0};
00165
00166 if (!(t = get_date_tag(*m, "TYER")) &&
00167 !(t = get_date_tag(*m, "TYE")))
00168 return;
00169 av_strlcpy(date, t->value, 5);
00170 av_dict_set(m, "TYER", NULL, 0);
00171 av_dict_set(m, "TYE", NULL, 0);
00172
00173 if (!(t = get_date_tag(*m, "TDAT")) &&
00174 !(t = get_date_tag(*m, "TDA")))
00175 goto finish;
00176 snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value);
00177 av_dict_set(m, "TDAT", NULL, 0);
00178 av_dict_set(m, "TDA", NULL, 0);
00179
00180 if (!(t = get_date_tag(*m, "TIME")) &&
00181 !(t = get_date_tag(*m, "TIM")))
00182 goto finish;
00183 snprintf(date + 10, sizeof(date) - 10, " %.2s:%.2s", t->value, t->value + 2);
00184 av_dict_set(m, "TIME", NULL, 0);
00185 av_dict_set(m, "TIM", NULL, 0);
00186
00187 finish:
00188 if (date[0])
00189 av_dict_set(m, "date", date, 0);
00190 }
00191
00192 static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
00193 {
00194 int isv34, unsync;
00195 unsigned tlen;
00196 char tag[5];
00197 int64_t next, end = avio_tell(s->pb) + len;
00198 int taghdrlen;
00199 const char *reason = NULL;
00200 AVIOContext pb;
00201 unsigned char *buffer = NULL;
00202 int buffer_size = 0;
00203
00204 switch (version) {
00205 case 2:
00206 if (flags & 0x40) {
00207 reason = "compression";
00208 goto error;
00209 }
00210 isv34 = 0;
00211 taghdrlen = 6;
00212 break;
00213
00214 case 3:
00215 case 4:
00216 isv34 = 1;
00217 taghdrlen = 10;
00218 break;
00219
00220 default:
00221 reason = "version";
00222 goto error;
00223 }
00224
00225 unsync = flags & 0x80;
00226
00227 if (isv34 && flags & 0x40) {
00228 int extlen = get_size(s->pb, 4);
00229 if (version == 4)
00230 extlen -= 4;
00231
00232 if (extlen < 0) {
00233 reason = "invalid extended header length";
00234 goto error;
00235 }
00236 avio_skip(s->pb, extlen);
00237 }
00238
00239 while (len >= taghdrlen) {
00240 unsigned int tflags = 0;
00241 int tunsync = 0;
00242
00243 if (isv34) {
00244 avio_read(s->pb, tag, 4);
00245 tag[4] = 0;
00246 if(version==3){
00247 tlen = avio_rb32(s->pb);
00248 }else
00249 tlen = get_size(s->pb, 4);
00250 tflags = avio_rb16(s->pb);
00251 tunsync = tflags & ID3v2_FLAG_UNSYNCH;
00252 } else {
00253 avio_read(s->pb, tag, 3);
00254 tag[3] = 0;
00255 tlen = avio_rb24(s->pb);
00256 }
00257 if (tlen > (1<<28) || !tlen)
00258 break;
00259 len -= taghdrlen + tlen;
00260
00261 if (len < 0)
00262 break;
00263
00264 next = avio_tell(s->pb) + tlen;
00265
00266 if (tflags & ID3v2_FLAG_DATALEN) {
00267 if (tlen < 4)
00268 break;
00269 avio_rb32(s->pb);
00270 tlen -= 4;
00271 }
00272
00273 if (tflags & (ID3v2_FLAG_ENCRYPTION | ID3v2_FLAG_COMPRESSION)) {
00274 av_log(s, AV_LOG_WARNING, "Skipping encrypted/compressed ID3v2 frame %s.\n", tag);
00275 avio_skip(s->pb, tlen);
00276 } else if (tag[0] == 'T') {
00277 if (unsync || tunsync) {
00278 int i, j;
00279 av_fast_malloc(&buffer, &buffer_size, tlen);
00280 if (!buffer) {
00281 av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", tlen);
00282 goto seek;
00283 }
00284 for (i = 0, j = 0; i < tlen; i++, j++) {
00285 buffer[j] = avio_r8(s->pb);
00286 if (j > 0 && !buffer[j] && buffer[j - 1] == 0xff) {
00287
00288 j--;
00289 }
00290 }
00291 ffio_init_context(&pb, buffer, j, 0, NULL, NULL, NULL, NULL);
00292 read_ttag(s, &pb, j, tag);
00293 } else {
00294 read_ttag(s, s->pb, tlen, tag);
00295 }
00296 }
00297 else if (!tag[0]) {
00298 if (tag[1])
00299 av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding");
00300 avio_skip(s->pb, tlen);
00301 break;
00302 }
00303
00304 seek:
00305 avio_seek(s->pb, next, SEEK_SET);
00306 }
00307
00308 if (version == 4 && flags & 0x10)
00309 end += 10;
00310
00311 error:
00312 if (reason)
00313 av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
00314 avio_seek(s->pb, end, SEEK_SET);
00315 av_free(buffer);
00316 return;
00317 }
00318
00319 void ff_id3v2_read(AVFormatContext *s, const char *magic)
00320 {
00321 int len, ret;
00322 uint8_t buf[ID3v2_HEADER_SIZE];
00323 int found_header;
00324 int64_t off;
00325
00326 do {
00327
00328 off = avio_tell(s->pb);
00329 ret = avio_read(s->pb, buf, ID3v2_HEADER_SIZE);
00330 if (ret != ID3v2_HEADER_SIZE)
00331 break;
00332 found_header = ff_id3v2_match(buf, magic);
00333 if (found_header) {
00334
00335 len = ((buf[6] & 0x7f) << 21) |
00336 ((buf[7] & 0x7f) << 14) |
00337 ((buf[8] & 0x7f) << 7) |
00338 (buf[9] & 0x7f);
00339 ff_id3v2_parse(s, len, buf[3], buf[5]);
00340 } else {
00341 avio_seek(s->pb, off, SEEK_SET);
00342 }
00343 } while (found_header);
00344 ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
00345 ff_metadata_conv(&s->metadata, NULL, ff_id3v2_2_metadata_conv);
00346 ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
00347 merge_date(&s->metadata);
00348 }
00349
00350 const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
00351 { "TALB", "album"},
00352 { "TCOM", "composer"},
00353 { "TCON", "genre"},
00354 { "TCOP", "copyright"},
00355 { "TENC", "encoded_by"},
00356 { "TIT2", "title"},
00357 { "TLAN", "language"},
00358 { "TPE1", "artist"},
00359 { "TPE2", "album_artist"},
00360 { "TPE3", "performer"},
00361 { "TPOS", "disc"},
00362 { "TPUB", "publisher"},
00363 { "TRCK", "track"},
00364 { "TSSE", "encoder"},
00365 { 0 }
00366 };
00367
00368 const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
00369 { "TDRL", "date"},
00370 { "TDRC", "date"},
00371 { "TDEN", "creation_time"},
00372 { "TSOA", "album-sort"},
00373 { "TSOP", "artist-sort"},
00374 { "TSOT", "title-sort"},
00375 { 0 }
00376 };
00377
00378 const AVMetadataConv ff_id3v2_2_metadata_conv[] = {
00379 { "TAL", "album"},
00380 { "TCO", "genre"},
00381 { "TT2", "title"},
00382 { "TEN", "encoded_by"},
00383 { "TP1", "artist"},
00384 { "TP2", "album_artist"},
00385 { "TP3", "performer"},
00386 { "TRK", "track"},
00387 { 0 }
00388 };
00389
00390
00391 const char ff_id3v2_tags[][4] = {
00392 "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
00393 "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
00394 "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
00395 "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
00396 { 0 },
00397 };
00398
00399 const char ff_id3v2_4_tags[][4] = {
00400 "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
00401 "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
00402 { 0 },
00403 };
00404
00405 const char ff_id3v2_3_tags[][4] = {
00406 "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
00407 { 0 },
00408 };