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