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