00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00029 #include "config.h"
00030
00031 #if CONFIG_ZLIB
00032 #include <zlib.h>
00033 #endif
00034
00035 #include "id3v2.h"
00036 #include "id3v1.h"
00037 #include "libavutil/avstring.h"
00038 #include "libavutil/intreadwrite.h"
00039 #include "libavutil/dict.h"
00040 #include "avio_internal.h"
00041
00042 const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
00043 { "TALB", "album"},
00044 { "TCOM", "composer"},
00045 { "TCON", "genre"},
00046 { "TCOP", "copyright"},
00047 { "TENC", "encoded_by"},
00048 { "TIT2", "title"},
00049 { "TLAN", "language"},
00050 { "TPE1", "artist"},
00051 { "TPE2", "album_artist"},
00052 { "TPE3", "performer"},
00053 { "TPOS", "disc"},
00054 { "TPUB", "publisher"},
00055 { "TRCK", "track"},
00056 { "TSSE", "encoder"},
00057 { 0 }
00058 };
00059
00060 const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
00061 { "TDRL", "date"},
00062 { "TDRC", "date"},
00063 { "TDEN", "creation_time"},
00064 { "TSOA", "album-sort"},
00065 { "TSOP", "artist-sort"},
00066 { "TSOT", "title-sort"},
00067 { 0 }
00068 };
00069
00070 static const AVMetadataConv id3v2_2_metadata_conv[] = {
00071 { "TAL", "album"},
00072 { "TCO", "genre"},
00073 { "TT2", "title"},
00074 { "TEN", "encoded_by"},
00075 { "TP1", "artist"},
00076 { "TP2", "album_artist"},
00077 { "TP3", "performer"},
00078 { "TRK", "track"},
00079 { 0 }
00080 };
00081
00082
00083 const char ff_id3v2_tags[][4] = {
00084 "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
00085 "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
00086 "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
00087 "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
00088 { 0 },
00089 };
00090
00091 const char ff_id3v2_4_tags[][4] = {
00092 "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
00093 "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
00094 { 0 },
00095 };
00096
00097 const char ff_id3v2_3_tags[][4] = {
00098 "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
00099 { 0 },
00100 };
00101
00102 int ff_id3v2_match(const uint8_t *buf, const char * magic)
00103 {
00104 return buf[0] == magic[0] &&
00105 buf[1] == magic[1] &&
00106 buf[2] == magic[2] &&
00107 buf[3] != 0xff &&
00108 buf[4] != 0xff &&
00109 (buf[6] & 0x80) == 0 &&
00110 (buf[7] & 0x80) == 0 &&
00111 (buf[8] & 0x80) == 0 &&
00112 (buf[9] & 0x80) == 0;
00113 }
00114
00115 int ff_id3v2_tag_len(const uint8_t * buf)
00116 {
00117 int len = ((buf[6] & 0x7f) << 21) +
00118 ((buf[7] & 0x7f) << 14) +
00119 ((buf[8] & 0x7f) << 7) +
00120 (buf[9] & 0x7f) +
00121 ID3v2_HEADER_SIZE;
00122 if (buf[5] & 0x10)
00123 len += ID3v2_HEADER_SIZE;
00124 return len;
00125 }
00126
00127 static unsigned int get_size(AVIOContext *s, int len)
00128 {
00129 int v = 0;
00130 while (len--)
00131 v = (v << 7) + (avio_r8(s) & 0x7F);
00132 return v;
00133 }
00134
00138 static void free_geobtag(void *obj)
00139 {
00140 ID3v2ExtraMetaGEOB *geob = obj;
00141 av_free(geob->mime_type);
00142 av_free(geob->file_name);
00143 av_free(geob->description);
00144 av_free(geob->data);
00145 av_free(geob);
00146 }
00147
00160 static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding,
00161 uint8_t **dst, int *maxread)
00162 {
00163 int ret;
00164 uint8_t tmp;
00165 uint32_t ch = 1;
00166 int left = *maxread;
00167 unsigned int (*get)(AVIOContext*) = avio_rb16;
00168 AVIOContext *dynbuf;
00169
00170 if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) {
00171 av_log(s, AV_LOG_ERROR, "Error opening memory stream\n");
00172 return ret;
00173 }
00174
00175 switch (encoding) {
00176
00177 case ID3v2_ENCODING_ISO8859:
00178 while (left && ch) {
00179 ch = avio_r8(pb);
00180 PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
00181 left--;
00182 }
00183 break;
00184
00185 case ID3v2_ENCODING_UTF16BOM:
00186 if ((left -= 2) < 0) {
00187 av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short\n");
00188 avio_close_dyn_buf(dynbuf, dst);
00189 av_freep(dst);
00190 return AVERROR_INVALIDDATA;
00191 }
00192 switch (avio_rb16(pb)) {
00193 case 0xfffe:
00194 get = avio_rl16;
00195 case 0xfeff:
00196 break;
00197 default:
00198 av_log(s, AV_LOG_ERROR, "Incorrect BOM value\n");
00199 avio_close_dyn_buf(dynbuf, dst);
00200 av_freep(dst);
00201 *maxread = left;
00202 return AVERROR_INVALIDDATA;
00203 }
00204
00205
00206 case ID3v2_ENCODING_UTF16BE:
00207 while ((left > 1) && ch) {
00208 GET_UTF16(ch, ((left -= 2) >= 0 ? get(pb) : 0), break;)
00209 PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
00210 }
00211 if (left < 0)
00212 left += 2;
00213 break;
00214
00215 case ID3v2_ENCODING_UTF8:
00216 while (left && ch) {
00217 ch = avio_r8(pb);
00218 avio_w8(dynbuf, ch);
00219 left--;
00220 }
00221 break;
00222 default:
00223 av_log(s, AV_LOG_WARNING, "Unknown encoding\n");
00224 }
00225
00226 if (ch)
00227 avio_w8(dynbuf, 0);
00228
00229 avio_close_dyn_buf(dynbuf, dst);
00230 *maxread = left;
00231
00232 return 0;
00233 }
00234
00238 static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key)
00239 {
00240 uint8_t *dst;
00241 int encoding, dict_flags = AV_DICT_DONT_OVERWRITE;
00242 unsigned genre;
00243
00244 if (taglen < 1)
00245 return;
00246
00247 encoding = avio_r8(pb);
00248 taglen--;
00249
00250 if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
00251 av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
00252 return;
00253 }
00254
00255 if (!(strcmp(key, "TCON") && strcmp(key, "TCO"))
00256 && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1)
00257 && genre <= ID3v1_GENRE_MAX) {
00258 av_freep(&dst);
00259 dst = ff_id3v1_genre_str[genre];
00260 } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
00261
00262 key = dst;
00263 if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
00264 av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
00265 av_freep(&key);
00266 return;
00267 }
00268 dict_flags |= AV_DICT_DONT_STRDUP_VAL | AV_DICT_DONT_STRDUP_KEY;
00269 }
00270 else if (*dst)
00271 dict_flags |= AV_DICT_DONT_STRDUP_VAL;
00272
00273 if (dst)
00274 av_dict_set(&s->metadata, key, dst, dict_flags);
00275 }
00276
00280 static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta)
00281 {
00282 ID3v2ExtraMetaGEOB *geob_data = NULL;
00283 ID3v2ExtraMeta *new_extra = NULL;
00284 char encoding;
00285 unsigned int len;
00286
00287 if (taglen < 1)
00288 return;
00289
00290 geob_data = av_mallocz(sizeof(ID3v2ExtraMetaGEOB));
00291 if (!geob_data) {
00292 av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMetaGEOB));
00293 return;
00294 }
00295
00296 new_extra = av_mallocz(sizeof(ID3v2ExtraMeta));
00297 if (!new_extra) {
00298 av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMeta));
00299 goto fail;
00300 }
00301
00302
00303 encoding = avio_r8(pb);
00304 taglen--;
00305
00306
00307 if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type, &taglen) < 0
00308 || taglen <= 0)
00309 goto fail;
00310
00311
00312 if (decode_str(s, pb, encoding, &geob_data->file_name, &taglen) < 0
00313 || taglen <= 0)
00314 goto fail;
00315
00316
00317 if (decode_str(s, pb, encoding, &geob_data->description, &taglen) < 0
00318 || taglen < 0)
00319 goto fail;
00320
00321 if (taglen) {
00322
00323 geob_data->data = av_malloc(taglen);
00324 if (!geob_data->data) {
00325 av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", taglen);
00326 goto fail;
00327 }
00328 if ((len = avio_read(pb, geob_data->data, taglen)) < taglen)
00329 av_log(s, AV_LOG_WARNING, "Error reading GEOB frame, data truncated.\n");
00330 geob_data->datasize = len;
00331 } else {
00332 geob_data->data = NULL;
00333 geob_data->datasize = 0;
00334 }
00335
00336
00337 new_extra->tag = "GEOB";
00338 new_extra->data = geob_data;
00339 new_extra->next = *extra_meta;
00340 *extra_meta = new_extra;
00341
00342 return;
00343
00344 fail:
00345 av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", tag);
00346 free_geobtag(geob_data);
00347 av_free(new_extra);
00348 return;
00349 }
00350
00351 static int is_number(const char *str)
00352 {
00353 while (*str >= '0' && *str <= '9') str++;
00354 return !*str;
00355 }
00356
00357 static AVDictionaryEntry* get_date_tag(AVDictionary *m, const char *tag)
00358 {
00359 AVDictionaryEntry *t;
00360 if ((t = av_dict_get(m, tag, NULL, AV_DICT_MATCH_CASE)) &&
00361 strlen(t->value) == 4 && is_number(t->value))
00362 return t;
00363 return NULL;
00364 }
00365
00366 static void merge_date(AVDictionary **m)
00367 {
00368 AVDictionaryEntry *t;
00369 char date[17] = {0};
00370
00371 if (!(t = get_date_tag(*m, "TYER")) &&
00372 !(t = get_date_tag(*m, "TYE")))
00373 return;
00374 av_strlcpy(date, t->value, 5);
00375 av_dict_set(m, "TYER", NULL, 0);
00376 av_dict_set(m, "TYE", NULL, 0);
00377
00378 if (!(t = get_date_tag(*m, "TDAT")) &&
00379 !(t = get_date_tag(*m, "TDA")))
00380 goto finish;
00381 snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value);
00382 av_dict_set(m, "TDAT", NULL, 0);
00383 av_dict_set(m, "TDA", NULL, 0);
00384
00385 if (!(t = get_date_tag(*m, "TIME")) &&
00386 !(t = get_date_tag(*m, "TIM")))
00387 goto finish;
00388 snprintf(date + 10, sizeof(date) - 10, " %.2s:%.2s", t->value, t->value + 2);
00389 av_dict_set(m, "TIME", NULL, 0);
00390 av_dict_set(m, "TIM", NULL, 0);
00391
00392 finish:
00393 if (date[0])
00394 av_dict_set(m, "date", date, 0);
00395 }
00396
00397 typedef struct ID3v2EMFunc {
00398 const char *tag3;
00399 const char *tag4;
00400 void (*read)(AVFormatContext*, AVIOContext*, int, char*, ID3v2ExtraMeta **);
00401 void (*free)(void *obj);
00402 } ID3v2EMFunc;
00403
00404 static const ID3v2EMFunc id3v2_extra_meta_funcs[] = {
00405 { "GEO", "GEOB", read_geobtag, free_geobtag },
00406 { NULL }
00407 };
00408
00414 static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34)
00415 {
00416 int i = 0;
00417 while (id3v2_extra_meta_funcs[i].tag3) {
00418 if (tag && !memcmp(tag,
00419 (isv34 ? id3v2_extra_meta_funcs[i].tag4 :
00420 id3v2_extra_meta_funcs[i].tag3),
00421 (isv34 ? 4 : 3)))
00422 return &id3v2_extra_meta_funcs[i];
00423 i++;
00424 }
00425 return NULL;
00426 }
00427
00428 static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags, ID3v2ExtraMeta **extra_meta)
00429 {
00430 int isv34, unsync;
00431 unsigned tlen;
00432 char tag[5];
00433 int64_t next, end = avio_tell(s->pb) + len;
00434 int taghdrlen;
00435 const char *reason = NULL;
00436 AVIOContext pb;
00437 AVIOContext *pbx;
00438 unsigned char *buffer = NULL;
00439 int buffer_size = 0;
00440 const ID3v2EMFunc *extra_func = NULL;
00441 unsigned char *compressed_buffer = NULL;
00442 int compressed_buffer_size = 0;
00443
00444 switch (version) {
00445 case 2:
00446 if (flags & 0x40) {
00447 reason = "compression";
00448 goto error;
00449 }
00450 isv34 = 0;
00451 taghdrlen = 6;
00452 break;
00453
00454 case 3:
00455 case 4:
00456 isv34 = 1;
00457 taghdrlen = 10;
00458 break;
00459
00460 default:
00461 reason = "version";
00462 goto error;
00463 }
00464
00465 unsync = flags & 0x80;
00466
00467 if (isv34 && flags & 0x40) {
00468 int extlen = get_size(s->pb, 4);
00469 if (version == 4)
00470 extlen -= 4;
00471
00472 if (extlen < 0) {
00473 reason = "invalid extended header length";
00474 goto error;
00475 }
00476 avio_skip(s->pb, extlen);
00477 len -= extlen + 4;
00478 if (len < 0) {
00479 reason = "extended header too long.";
00480 goto error;
00481 }
00482 }
00483
00484 while (len >= taghdrlen) {
00485 unsigned int tflags = 0;
00486 int tunsync = 0;
00487 int tcomp = 0;
00488 int tencr = 0;
00489 unsigned long dlen;
00490
00491 if (isv34) {
00492 avio_read(s->pb, tag, 4);
00493 tag[4] = 0;
00494 if(version==3){
00495 tlen = avio_rb32(s->pb);
00496 }else
00497 tlen = get_size(s->pb, 4);
00498 tflags = avio_rb16(s->pb);
00499 tunsync = tflags & ID3v2_FLAG_UNSYNCH;
00500 } else {
00501 avio_read(s->pb, tag, 3);
00502 tag[3] = 0;
00503 tlen = avio_rb24(s->pb);
00504 }
00505 if (tlen > (1<<28))
00506 break;
00507 len -= taghdrlen + tlen;
00508
00509 if (len < 0)
00510 break;
00511
00512 next = avio_tell(s->pb) + tlen;
00513
00514 if (!tlen) {
00515 if (tag[0])
00516 av_log(s, AV_LOG_DEBUG, "Invalid empty frame %s, skipping.\n", tag);
00517 continue;
00518 }
00519
00520 if (tflags & ID3v2_FLAG_DATALEN) {
00521 if (tlen < 4)
00522 break;
00523 dlen = avio_rb32(s->pb);
00524 tlen -= 4;
00525 } else
00526 dlen = tlen;
00527
00528 tcomp = tflags & ID3v2_FLAG_COMPRESSION;
00529 tencr = tflags & ID3v2_FLAG_ENCRYPTION;
00530
00531
00532 if (tencr || (!CONFIG_ZLIB && tcomp)) {
00533 const char *type;
00534 if (!tcomp)
00535 type = "encrypted";
00536 else if (!tencr)
00537 type = "compressed";
00538 else
00539 type = "encrypted and compressed";
00540
00541 av_log(s, AV_LOG_WARNING, "Skipping %s ID3v2 frame %s.\n", type, tag);
00542 avio_skip(s->pb, tlen);
00543
00544 } else if (tag[0] == 'T' || (extra_meta && (extra_func = get_extra_meta_func(tag, isv34)))) {
00545 if (unsync || tunsync || tcomp) {
00546 int i, j;
00547
00548 av_fast_malloc(&buffer, &buffer_size, dlen);
00549 if (!buffer) {
00550 av_log(s, AV_LOG_ERROR, "Failed to alloc %ld bytes\n", dlen);
00551 goto seek;
00552 }
00553 #if CONFIG_ZLIB
00554 if (tcomp) {
00555 int n, err;
00556
00557 av_log(s, AV_LOG_DEBUG, "Compresssed frame %s tlen=%d dlen=%ld\n", tag, tlen, dlen);
00558
00559 av_fast_malloc(&compressed_buffer, &compressed_buffer_size, tlen);
00560 if (!compressed_buffer) {
00561 av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", tlen);
00562 goto seek;
00563 }
00564
00565 n = avio_read(s->pb, compressed_buffer, tlen);
00566 if (n < 0) {
00567 av_log(s, AV_LOG_ERROR, "Failed to read compressed tag\n");
00568 goto seek;
00569 }
00570
00571 err = uncompress(buffer, &dlen, compressed_buffer, n);
00572 if (err != Z_OK) {
00573 av_log(s, AV_LOG_ERROR, "Failed to uncompress tag: %d\n", err);
00574 goto seek;
00575 }
00576 }
00577 #endif
00578
00579 for (i = 0, j = 0; i < dlen; i++, j++) {
00580 if (!tcomp)
00581 buffer[j] = avio_r8(s->pb);
00582 if (j > 0 && !buffer[j] && buffer[j - 1] == 0xff) {
00583
00584 j--;
00585 }
00586 }
00587 ffio_init_context(&pb, buffer, j, 0, NULL, NULL, NULL, NULL);
00588 tlen = j;
00589 pbx = &pb;
00590 } else {
00591 pbx = s->pb;
00592 }
00593 if (tag[0] == 'T')
00594
00595 read_ttag(s, pbx, tlen, tag);
00596 else
00597
00598 extra_func->read(s, pbx, tlen, tag, extra_meta);
00599 }
00600 else if (!tag[0]) {
00601 if (tag[1])
00602 av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding");
00603 avio_skip(s->pb, tlen);
00604 break;
00605 }
00606
00607 seek:
00608 avio_seek(s->pb, next, SEEK_SET);
00609 }
00610
00611 if (version == 4 && flags & 0x10)
00612 end += 10;
00613
00614 error:
00615 if (reason)
00616 av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
00617 avio_seek(s->pb, end, SEEK_SET);
00618 av_free(buffer);
00619 av_free(compressed_buffer);
00620 return;
00621 }
00622
00623 void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta)
00624 {
00625 int len, ret;
00626 uint8_t buf[ID3v2_HEADER_SIZE];
00627 int found_header;
00628 int64_t off;
00629
00630 do {
00631
00632 off = avio_tell(s->pb);
00633 ret = avio_read(s->pb, buf, ID3v2_HEADER_SIZE);
00634 if (ret != ID3v2_HEADER_SIZE)
00635 break;
00636 found_header = ff_id3v2_match(buf, magic);
00637 if (found_header) {
00638
00639 len = ((buf[6] & 0x7f) << 21) |
00640 ((buf[7] & 0x7f) << 14) |
00641 ((buf[8] & 0x7f) << 7) |
00642 (buf[9] & 0x7f);
00643 ff_id3v2_parse(s, len, buf[3], buf[5], extra_meta);
00644 } else {
00645 avio_seek(s->pb, off, SEEK_SET);
00646 }
00647 } while (found_header);
00648 ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
00649 ff_metadata_conv(&s->metadata, NULL, id3v2_2_metadata_conv);
00650 ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
00651 merge_date(&s->metadata);
00652 }
00653
00654 void ff_id3v2_read(AVFormatContext *s, const char *magic)
00655 {
00656 ff_id3v2_read_all(s, magic, NULL);
00657 }
00658
00659 void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
00660 {
00661 ID3v2ExtraMeta *current = *extra_meta, *next;
00662 const ID3v2EMFunc *extra_func;
00663
00664 while (current) {
00665 if ((extra_func = get_extra_meta_func(current->tag, 1)))
00666 extra_func->free(current->data);
00667 next = current->next;
00668 av_freep(¤t);
00669 current = next;
00670 }
00671 }