annotate ffmpeg/libavformat/id3v2.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents f445c3017523
children
rev   line source
yading@11 1 /*
yading@11 2 * Copyright (c) 2003 Fabrice Bellard
yading@11 3 *
yading@11 4 * This file is part of FFmpeg.
yading@11 5 *
yading@11 6 * FFmpeg is free software; you can redistribute it and/or
yading@11 7 * modify it under the terms of the GNU Lesser General Public
yading@11 8 * License as published by the Free Software Foundation; either
yading@11 9 * version 2.1 of the License, or (at your option) any later version.
yading@11 10 *
yading@11 11 * FFmpeg is distributed in the hope that it will be useful,
yading@11 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@11 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@11 14 * Lesser General Public License for more details.
yading@11 15 *
yading@11 16 * You should have received a copy of the GNU Lesser General Public
yading@11 17 * License along with FFmpeg; if not, write to the Free Software
yading@11 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@11 19 */
yading@11 20
yading@11 21 /**
yading@11 22 * @file
yading@11 23 * ID3v2 header parser
yading@11 24 *
yading@11 25 * Specifications available at:
yading@11 26 * http://id3.org/Developer_Information
yading@11 27 */
yading@11 28
yading@11 29 #include "config.h"
yading@11 30
yading@11 31 #if CONFIG_ZLIB
yading@11 32 #include <zlib.h>
yading@11 33 #endif
yading@11 34
yading@11 35 #include "id3v2.h"
yading@11 36 #include "id3v1.h"
yading@11 37 #include "libavutil/avstring.h"
yading@11 38 #include "libavutil/intreadwrite.h"
yading@11 39 #include "libavutil/dict.h"
yading@11 40 #include "avio_internal.h"
yading@11 41 #include "internal.h"
yading@11 42
yading@11 43 const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
yading@11 44 { "TALB", "album"},
yading@11 45 { "TCOM", "composer"},
yading@11 46 { "TCON", "genre"},
yading@11 47 { "TCOP", "copyright"},
yading@11 48 { "TENC", "encoded_by"},
yading@11 49 { "TIT2", "title"},
yading@11 50 { "TLAN", "language"},
yading@11 51 { "TPE1", "artist"},
yading@11 52 { "TPE2", "album_artist"},
yading@11 53 { "TPE3", "performer"},
yading@11 54 { "TPOS", "disc"},
yading@11 55 { "TPUB", "publisher"},
yading@11 56 { "TRCK", "track"},
yading@11 57 { "TSSE", "encoder"},
yading@11 58 { 0 }
yading@11 59 };
yading@11 60
yading@11 61 const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
yading@11 62 { "TDRL", "date"},
yading@11 63 { "TDRC", "date"},
yading@11 64 { "TDEN", "creation_time"},
yading@11 65 { "TSOA", "album-sort"},
yading@11 66 { "TSOP", "artist-sort"},
yading@11 67 { "TSOT", "title-sort"},
yading@11 68 { 0 }
yading@11 69 };
yading@11 70
yading@11 71 static const AVMetadataConv id3v2_2_metadata_conv[] = {
yading@11 72 { "TAL", "album"},
yading@11 73 { "TCO", "genre"},
yading@11 74 { "TT2", "title"},
yading@11 75 { "TEN", "encoded_by"},
yading@11 76 { "TP1", "artist"},
yading@11 77 { "TP2", "album_artist"},
yading@11 78 { "TP3", "performer"},
yading@11 79 { "TRK", "track"},
yading@11 80 { 0 }
yading@11 81 };
yading@11 82
yading@11 83
yading@11 84 const char ff_id3v2_tags[][4] = {
yading@11 85 "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
yading@11 86 "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
yading@11 87 "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
yading@11 88 "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
yading@11 89 { 0 },
yading@11 90 };
yading@11 91
yading@11 92 const char ff_id3v2_4_tags[][4] = {
yading@11 93 "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
yading@11 94 "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
yading@11 95 { 0 },
yading@11 96 };
yading@11 97
yading@11 98 const char ff_id3v2_3_tags[][4] = {
yading@11 99 "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
yading@11 100 { 0 },
yading@11 101 };
yading@11 102
yading@11 103 const char *ff_id3v2_picture_types[21] = {
yading@11 104 "Other",
yading@11 105 "32x32 pixels 'file icon'",
yading@11 106 "Other file icon",
yading@11 107 "Cover (front)",
yading@11 108 "Cover (back)",
yading@11 109 "Leaflet page",
yading@11 110 "Media (e.g. label side of CD)",
yading@11 111 "Lead artist/lead performer/soloist",
yading@11 112 "Artist/performer",
yading@11 113 "Conductor",
yading@11 114 "Band/Orchestra",
yading@11 115 "Composer",
yading@11 116 "Lyricist/text writer",
yading@11 117 "Recording Location",
yading@11 118 "During recording",
yading@11 119 "During performance",
yading@11 120 "Movie/video screen capture",
yading@11 121 "A bright coloured fish",
yading@11 122 "Illustration",
yading@11 123 "Band/artist logotype",
yading@11 124 "Publisher/Studio logotype",
yading@11 125 };
yading@11 126
yading@11 127 const CodecMime ff_id3v2_mime_tags[] = {
yading@11 128 {"image/gif" , AV_CODEC_ID_GIF},
yading@11 129 {"image/jpeg", AV_CODEC_ID_MJPEG},
yading@11 130 {"image/jpg", AV_CODEC_ID_MJPEG},
yading@11 131 {"image/png" , AV_CODEC_ID_PNG},
yading@11 132 {"image/tiff", AV_CODEC_ID_TIFF},
yading@11 133 {"image/bmp", AV_CODEC_ID_BMP},
yading@11 134 {"JPG", AV_CODEC_ID_MJPEG}, /* ID3v2.2 */
yading@11 135 {"PNG" , AV_CODEC_ID_PNG}, /* ID3v2.2 */
yading@11 136 {"", AV_CODEC_ID_NONE},
yading@11 137 };
yading@11 138
yading@11 139 int ff_id3v2_match(const uint8_t *buf, const char * magic)
yading@11 140 {
yading@11 141 return buf[0] == magic[0] &&
yading@11 142 buf[1] == magic[1] &&
yading@11 143 buf[2] == magic[2] &&
yading@11 144 buf[3] != 0xff &&
yading@11 145 buf[4] != 0xff &&
yading@11 146 (buf[6] & 0x80) == 0 &&
yading@11 147 (buf[7] & 0x80) == 0 &&
yading@11 148 (buf[8] & 0x80) == 0 &&
yading@11 149 (buf[9] & 0x80) == 0;
yading@11 150 }
yading@11 151
yading@11 152 int ff_id3v2_tag_len(const uint8_t * buf)
yading@11 153 {
yading@11 154 int len = ((buf[6] & 0x7f) << 21) +
yading@11 155 ((buf[7] & 0x7f) << 14) +
yading@11 156 ((buf[8] & 0x7f) << 7) +
yading@11 157 (buf[9] & 0x7f) +
yading@11 158 ID3v2_HEADER_SIZE;
yading@11 159 if (buf[5] & 0x10)
yading@11 160 len += ID3v2_HEADER_SIZE;
yading@11 161 return len;
yading@11 162 }
yading@11 163
yading@11 164 static unsigned int get_size(AVIOContext *s, int len)
yading@11 165 {
yading@11 166 int v = 0;
yading@11 167 while (len--)
yading@11 168 v = (v << 7) + (avio_r8(s) & 0x7F);
yading@11 169 return v;
yading@11 170 }
yading@11 171
yading@11 172 /**
yading@11 173 * Free GEOB type extra metadata.
yading@11 174 */
yading@11 175 static void free_geobtag(void *obj)
yading@11 176 {
yading@11 177 ID3v2ExtraMetaGEOB *geob = obj;
yading@11 178 av_free(geob->mime_type);
yading@11 179 av_free(geob->file_name);
yading@11 180 av_free(geob->description);
yading@11 181 av_free(geob->data);
yading@11 182 av_free(geob);
yading@11 183 }
yading@11 184
yading@11 185 /**
yading@11 186 * Decode characters to UTF-8 according to encoding type. The decoded buffer is
yading@11 187 * always null terminated. Stop reading when either *maxread bytes are read from
yading@11 188 * pb or U+0000 character is found.
yading@11 189 *
yading@11 190 * @param dst Pointer where the address of the buffer with the decoded bytes is
yading@11 191 * stored. Buffer must be freed by caller.
yading@11 192 * @param maxread Pointer to maximum number of characters to read from the
yading@11 193 * AVIOContext. After execution the value is decremented by the number of bytes
yading@11 194 * actually read.
yading@11 195 * @returns 0 if no error occurred, dst is uninitialized on error
yading@11 196 */
yading@11 197 static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding,
yading@11 198 uint8_t **dst, int *maxread)
yading@11 199 {
yading@11 200 int ret;
yading@11 201 uint8_t tmp;
yading@11 202 uint32_t ch = 1;
yading@11 203 int left = *maxread;
yading@11 204 unsigned int (*get)(AVIOContext*) = avio_rb16;
yading@11 205 AVIOContext *dynbuf;
yading@11 206
yading@11 207 if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) {
yading@11 208 av_log(s, AV_LOG_ERROR, "Error opening memory stream\n");
yading@11 209 return ret;
yading@11 210 }
yading@11 211
yading@11 212 switch (encoding) {
yading@11 213
yading@11 214 case ID3v2_ENCODING_ISO8859:
yading@11 215 while (left && ch) {
yading@11 216 ch = avio_r8(pb);
yading@11 217 PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
yading@11 218 left--;
yading@11 219 }
yading@11 220 break;
yading@11 221
yading@11 222 case ID3v2_ENCODING_UTF16BOM:
yading@11 223 if ((left -= 2) < 0) {
yading@11 224 av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short\n");
yading@11 225 avio_close_dyn_buf(dynbuf, dst);
yading@11 226 av_freep(dst);
yading@11 227 return AVERROR_INVALIDDATA;
yading@11 228 }
yading@11 229 switch (avio_rb16(pb)) {
yading@11 230 case 0xfffe:
yading@11 231 get = avio_rl16;
yading@11 232 case 0xfeff:
yading@11 233 break;
yading@11 234 default:
yading@11 235 av_log(s, AV_LOG_ERROR, "Incorrect BOM value\n");
yading@11 236 avio_close_dyn_buf(dynbuf, dst);
yading@11 237 av_freep(dst);
yading@11 238 *maxread = left;
yading@11 239 return AVERROR_INVALIDDATA;
yading@11 240 }
yading@11 241 // fall-through
yading@11 242
yading@11 243 case ID3v2_ENCODING_UTF16BE:
yading@11 244 while ((left > 1) && ch) {
yading@11 245 GET_UTF16(ch, ((left -= 2) >= 0 ? get(pb) : 0), break;)
yading@11 246 PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
yading@11 247 }
yading@11 248 if (left < 0)
yading@11 249 left += 2; /* did not read last char from pb */
yading@11 250 break;
yading@11 251
yading@11 252 case ID3v2_ENCODING_UTF8:
yading@11 253 while (left && ch) {
yading@11 254 ch = avio_r8(pb);
yading@11 255 avio_w8(dynbuf, ch);
yading@11 256 left--;
yading@11 257 }
yading@11 258 break;
yading@11 259 default:
yading@11 260 av_log(s, AV_LOG_WARNING, "Unknown encoding\n");
yading@11 261 }
yading@11 262
yading@11 263 if (ch)
yading@11 264 avio_w8(dynbuf, 0);
yading@11 265
yading@11 266 avio_close_dyn_buf(dynbuf, dst);
yading@11 267 *maxread = left;
yading@11 268
yading@11 269 return 0;
yading@11 270 }
yading@11 271
yading@11 272 /**
yading@11 273 * Parse a text tag.
yading@11 274 */
yading@11 275 static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key)
yading@11 276 {
yading@11 277 uint8_t *dst;
yading@11 278 int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_VAL;
yading@11 279 unsigned genre;
yading@11 280
yading@11 281 if (taglen < 1)
yading@11 282 return;
yading@11 283
yading@11 284 encoding = avio_r8(pb);
yading@11 285 taglen--; /* account for encoding type byte */
yading@11 286
yading@11 287 if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
yading@11 288 av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
yading@11 289 return;
yading@11 290 }
yading@11 291
yading@11 292 if (!(strcmp(key, "TCON") && strcmp(key, "TCO"))
yading@11 293 && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1)
yading@11 294 && genre <= ID3v1_GENRE_MAX) {
yading@11 295 av_freep(&dst);
yading@11 296 dst = av_strdup(ff_id3v1_genre_str[genre]);
yading@11 297 } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
yading@11 298 /* dst now contains the key, need to get value */
yading@11 299 key = dst;
yading@11 300 if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
yading@11 301 av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
yading@11 302 av_freep(&key);
yading@11 303 return;
yading@11 304 }
yading@11 305 dict_flags |= AV_DICT_DONT_STRDUP_KEY;
yading@11 306 } else if (!*dst)
yading@11 307 av_freep(&dst);
yading@11 308
yading@11 309 if (dst)
yading@11 310 av_dict_set(&s->metadata, key, dst, dict_flags);
yading@11 311 }
yading@11 312
yading@11 313 /**
yading@11 314 * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
yading@11 315 */
yading@11 316 static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta)
yading@11 317 {
yading@11 318 ID3v2ExtraMetaGEOB *geob_data = NULL;
yading@11 319 ID3v2ExtraMeta *new_extra = NULL;
yading@11 320 char encoding;
yading@11 321 unsigned int len;
yading@11 322
yading@11 323 if (taglen < 1)
yading@11 324 return;
yading@11 325
yading@11 326 geob_data = av_mallocz(sizeof(ID3v2ExtraMetaGEOB));
yading@11 327 if (!geob_data) {
yading@11 328 av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMetaGEOB));
yading@11 329 return;
yading@11 330 }
yading@11 331
yading@11 332 new_extra = av_mallocz(sizeof(ID3v2ExtraMeta));
yading@11 333 if (!new_extra) {
yading@11 334 av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMeta));
yading@11 335 goto fail;
yading@11 336 }
yading@11 337
yading@11 338 /* read encoding type byte */
yading@11 339 encoding = avio_r8(pb);
yading@11 340 taglen--;
yading@11 341
yading@11 342 /* read MIME type (always ISO-8859) */
yading@11 343 if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type, &taglen) < 0
yading@11 344 || taglen <= 0)
yading@11 345 goto fail;
yading@11 346
yading@11 347 /* read file name */
yading@11 348 if (decode_str(s, pb, encoding, &geob_data->file_name, &taglen) < 0
yading@11 349 || taglen <= 0)
yading@11 350 goto fail;
yading@11 351
yading@11 352 /* read content description */
yading@11 353 if (decode_str(s, pb, encoding, &geob_data->description, &taglen) < 0
yading@11 354 || taglen < 0)
yading@11 355 goto fail;
yading@11 356
yading@11 357 if (taglen) {
yading@11 358 /* save encapsulated binary data */
yading@11 359 geob_data->data = av_malloc(taglen);
yading@11 360 if (!geob_data->data) {
yading@11 361 av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", taglen);
yading@11 362 goto fail;
yading@11 363 }
yading@11 364 if ((len = avio_read(pb, geob_data->data, taglen)) < taglen)
yading@11 365 av_log(s, AV_LOG_WARNING, "Error reading GEOB frame, data truncated.\n");
yading@11 366 geob_data->datasize = len;
yading@11 367 } else {
yading@11 368 geob_data->data = NULL;
yading@11 369 geob_data->datasize = 0;
yading@11 370 }
yading@11 371
yading@11 372 /* add data to the list */
yading@11 373 new_extra->tag = "GEOB";
yading@11 374 new_extra->data = geob_data;
yading@11 375 new_extra->next = *extra_meta;
yading@11 376 *extra_meta = new_extra;
yading@11 377
yading@11 378 return;
yading@11 379
yading@11 380 fail:
yading@11 381 av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", tag);
yading@11 382 free_geobtag(geob_data);
yading@11 383 av_free(new_extra);
yading@11 384 return;
yading@11 385 }
yading@11 386
yading@11 387 static int is_number(const char *str)
yading@11 388 {
yading@11 389 while (*str >= '0' && *str <= '9') str++;
yading@11 390 return !*str;
yading@11 391 }
yading@11 392
yading@11 393 static AVDictionaryEntry* get_date_tag(AVDictionary *m, const char *tag)
yading@11 394 {
yading@11 395 AVDictionaryEntry *t;
yading@11 396 if ((t = av_dict_get(m, tag, NULL, AV_DICT_MATCH_CASE)) &&
yading@11 397 strlen(t->value) == 4 && is_number(t->value))
yading@11 398 return t;
yading@11 399 return NULL;
yading@11 400 }
yading@11 401
yading@11 402 static void merge_date(AVDictionary **m)
yading@11 403 {
yading@11 404 AVDictionaryEntry *t;
yading@11 405 char date[17] = {0}; // YYYY-MM-DD hh:mm
yading@11 406
yading@11 407 if (!(t = get_date_tag(*m, "TYER")) &&
yading@11 408 !(t = get_date_tag(*m, "TYE")))
yading@11 409 return;
yading@11 410 av_strlcpy(date, t->value, 5);
yading@11 411 av_dict_set(m, "TYER", NULL, 0);
yading@11 412 av_dict_set(m, "TYE", NULL, 0);
yading@11 413
yading@11 414 if (!(t = get_date_tag(*m, "TDAT")) &&
yading@11 415 !(t = get_date_tag(*m, "TDA")))
yading@11 416 goto finish;
yading@11 417 snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value);
yading@11 418 av_dict_set(m, "TDAT", NULL, 0);
yading@11 419 av_dict_set(m, "TDA", NULL, 0);
yading@11 420
yading@11 421 if (!(t = get_date_tag(*m, "TIME")) &&
yading@11 422 !(t = get_date_tag(*m, "TIM")))
yading@11 423 goto finish;
yading@11 424 snprintf(date + 10, sizeof(date) - 10, " %.2s:%.2s", t->value, t->value + 2);
yading@11 425 av_dict_set(m, "TIME", NULL, 0);
yading@11 426 av_dict_set(m, "TIM", NULL, 0);
yading@11 427
yading@11 428 finish:
yading@11 429 if (date[0])
yading@11 430 av_dict_set(m, "date", date, 0);
yading@11 431 }
yading@11 432
yading@11 433 static void free_apic(void *obj)
yading@11 434 {
yading@11 435 ID3v2ExtraMetaAPIC *apic = obj;
yading@11 436 av_buffer_unref(&apic->buf);
yading@11 437 av_freep(&apic->description);
yading@11 438 av_freep(&apic);
yading@11 439 }
yading@11 440
yading@11 441 static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta)
yading@11 442 {
yading@11 443 int enc, pic_type;
yading@11 444 char mimetype[64];
yading@11 445 const CodecMime *mime = ff_id3v2_mime_tags;
yading@11 446 enum AVCodecID id = AV_CODEC_ID_NONE;
yading@11 447 ID3v2ExtraMetaAPIC *apic = NULL;
yading@11 448 ID3v2ExtraMeta *new_extra = NULL;
yading@11 449 int64_t end = avio_tell(pb) + taglen;
yading@11 450
yading@11 451 if (taglen <= 4)
yading@11 452 goto fail;
yading@11 453
yading@11 454 new_extra = av_mallocz(sizeof(*new_extra));
yading@11 455 apic = av_mallocz(sizeof(*apic));
yading@11 456 if (!new_extra || !apic)
yading@11 457 goto fail;
yading@11 458
yading@11 459 enc = avio_r8(pb);
yading@11 460 taglen--;
yading@11 461
yading@11 462 /* mimetype */
yading@11 463 taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype));
yading@11 464 while (mime->id != AV_CODEC_ID_NONE) {
yading@11 465 if (!av_strncasecmp(mime->str, mimetype, sizeof(mimetype))) {
yading@11 466 id = mime->id;
yading@11 467 break;
yading@11 468 }
yading@11 469 mime++;
yading@11 470 }
yading@11 471 if (id == AV_CODEC_ID_NONE) {
yading@11 472 av_log(s, AV_LOG_WARNING, "Unknown attached picture mimetype: %s, skipping.\n", mimetype);
yading@11 473 goto fail;
yading@11 474 }
yading@11 475 apic->id = id;
yading@11 476
yading@11 477 /* picture type */
yading@11 478 pic_type = avio_r8(pb);
yading@11 479 taglen--;
yading@11 480 if (pic_type < 0 || pic_type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) {
yading@11 481 av_log(s, AV_LOG_WARNING, "Unknown attached picture type %d.\n", pic_type);
yading@11 482 pic_type = 0;
yading@11 483 }
yading@11 484 apic->type = ff_id3v2_picture_types[pic_type];
yading@11 485
yading@11 486 /* description and picture data */
yading@11 487 if (decode_str(s, pb, enc, &apic->description, &taglen) < 0) {
yading@11 488 av_log(s, AV_LOG_ERROR, "Error decoding attached picture description.\n");
yading@11 489 goto fail;
yading@11 490 }
yading@11 491
yading@11 492 apic->buf = av_buffer_alloc(taglen + FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 493 if (!apic->buf || !taglen || avio_read(pb, apic->buf->data, taglen) != taglen)
yading@11 494 goto fail;
yading@11 495 memset(apic->buf->data + taglen, 0, FF_INPUT_BUFFER_PADDING_SIZE);
yading@11 496
yading@11 497 new_extra->tag = "APIC";
yading@11 498 new_extra->data = apic;
yading@11 499 new_extra->next = *extra_meta;
yading@11 500 *extra_meta = new_extra;
yading@11 501
yading@11 502 return;
yading@11 503
yading@11 504 fail:
yading@11 505 if (apic)
yading@11 506 free_apic(apic);
yading@11 507 av_freep(&new_extra);
yading@11 508 avio_seek(pb, end, SEEK_SET);
yading@11 509 }
yading@11 510
yading@11 511 static void read_chapter(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta)
yading@11 512 {
yading@11 513 AVRational time_base = {1, 1000};
yading@11 514 char title[1024];
yading@11 515 uint32_t start, end;
yading@11 516
yading@11 517 taglen -= avio_get_str(pb, taglen, title, sizeof(title));
yading@11 518 if (taglen < 16)
yading@11 519 return;
yading@11 520
yading@11 521 start = avio_rb32(pb);
yading@11 522 end = avio_rb32(pb);
yading@11 523 taglen -= 27;
yading@11 524 if (taglen > 0) {
yading@11 525 char tag[4];
yading@11 526
yading@11 527 avio_skip(pb, 8);
yading@11 528 avio_read(pb, tag, 4);
yading@11 529 if (!memcmp(tag, "TIT2", 4)) {
yading@11 530 taglen = FFMIN(taglen, avio_rb32(pb));
yading@11 531 if (taglen < 0)
yading@11 532 return;
yading@11 533 avio_skip(pb, 3);
yading@11 534 avio_get_str(pb, taglen, title, sizeof(title));
yading@11 535 }
yading@11 536 }
yading@11 537
yading@11 538 avpriv_new_chapter(s, s->nb_chapters + 1, time_base, start, end, title);
yading@11 539 }
yading@11 540
yading@11 541 typedef struct ID3v2EMFunc {
yading@11 542 const char *tag3;
yading@11 543 const char *tag4;
yading@11 544 void (*read)(AVFormatContext*, AVIOContext*, int, char*, ID3v2ExtraMeta **);
yading@11 545 void (*free)(void *obj);
yading@11 546 } ID3v2EMFunc;
yading@11 547
yading@11 548 static const ID3v2EMFunc id3v2_extra_meta_funcs[] = {
yading@11 549 { "GEO", "GEOB", read_geobtag, free_geobtag },
yading@11 550 { "PIC", "APIC", read_apic, free_apic },
yading@11 551 { "CHAP","CHAP", read_chapter, NULL },
yading@11 552 { NULL }
yading@11 553 };
yading@11 554
yading@11 555 /**
yading@11 556 * Get the corresponding ID3v2EMFunc struct for a tag.
yading@11 557 * @param isv34 Determines if v2.2 or v2.3/4 strings are used
yading@11 558 * @return A pointer to the ID3v2EMFunc struct if found, NULL otherwise.
yading@11 559 */
yading@11 560 static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34)
yading@11 561 {
yading@11 562 int i = 0;
yading@11 563 while (id3v2_extra_meta_funcs[i].tag3) {
yading@11 564 if (tag && !memcmp(tag,
yading@11 565 (isv34 ? id3v2_extra_meta_funcs[i].tag4 :
yading@11 566 id3v2_extra_meta_funcs[i].tag3),
yading@11 567 (isv34 ? 4 : 3)))
yading@11 568 return &id3v2_extra_meta_funcs[i];
yading@11 569 i++;
yading@11 570 }
yading@11 571 return NULL;
yading@11 572 }
yading@11 573
yading@11 574 static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags, ID3v2ExtraMeta **extra_meta)
yading@11 575 {
yading@11 576 int isv34, unsync;
yading@11 577 unsigned tlen;
yading@11 578 char tag[5];
yading@11 579 int64_t next, end = avio_tell(s->pb) + len;
yading@11 580 int taghdrlen;
yading@11 581 const char *reason = NULL;
yading@11 582 AVIOContext pb;
yading@11 583 AVIOContext *pbx;
yading@11 584 unsigned char *buffer = NULL;
yading@11 585 int buffer_size = 0;
yading@11 586 const ID3v2EMFunc *extra_func = NULL;
yading@11 587 unsigned char *uncompressed_buffer = NULL;
yading@11 588 int uncompressed_buffer_size = 0;
yading@11 589
yading@11 590 av_log(s, AV_LOG_DEBUG, "id3v2 ver:%d flags:%02X len:%d\n", version, flags, len);
yading@11 591
yading@11 592 switch (version) {
yading@11 593 case 2:
yading@11 594 if (flags & 0x40) {
yading@11 595 reason = "compression";
yading@11 596 goto error;
yading@11 597 }
yading@11 598 isv34 = 0;
yading@11 599 taghdrlen = 6;
yading@11 600 break;
yading@11 601
yading@11 602 case 3:
yading@11 603 case 4:
yading@11 604 isv34 = 1;
yading@11 605 taghdrlen = 10;
yading@11 606 break;
yading@11 607
yading@11 608 default:
yading@11 609 reason = "version";
yading@11 610 goto error;
yading@11 611 }
yading@11 612
yading@11 613 unsync = flags & 0x80;
yading@11 614
yading@11 615 if (isv34 && flags & 0x40) { /* Extended header present, just skip over it */
yading@11 616 int extlen = get_size(s->pb, 4);
yading@11 617 if (version == 4)
yading@11 618 extlen -= 4; // in v2.4 the length includes the length field we just read
yading@11 619
yading@11 620 if (extlen < 0) {
yading@11 621 reason = "invalid extended header length";
yading@11 622 goto error;
yading@11 623 }
yading@11 624 avio_skip(s->pb, extlen);
yading@11 625 len -= extlen + 4;
yading@11 626 if (len < 0) {
yading@11 627 reason = "extended header too long.";
yading@11 628 goto error;
yading@11 629 }
yading@11 630 }
yading@11 631
yading@11 632 while (len >= taghdrlen) {
yading@11 633 unsigned int tflags = 0;
yading@11 634 int tunsync = 0;
yading@11 635 int tcomp = 0;
yading@11 636 int tencr = 0;
yading@11 637 unsigned long dlen;
yading@11 638
yading@11 639 if (isv34) {
yading@11 640 avio_read(s->pb, tag, 4);
yading@11 641 tag[4] = 0;
yading@11 642 if(version==3){
yading@11 643 tlen = avio_rb32(s->pb);
yading@11 644 }else
yading@11 645 tlen = get_size(s->pb, 4);
yading@11 646 tflags = avio_rb16(s->pb);
yading@11 647 tunsync = tflags & ID3v2_FLAG_UNSYNCH;
yading@11 648 } else {
yading@11 649 avio_read(s->pb, tag, 3);
yading@11 650 tag[3] = 0;
yading@11 651 tlen = avio_rb24(s->pb);
yading@11 652 }
yading@11 653 if (tlen > (1<<28))
yading@11 654 break;
yading@11 655 len -= taghdrlen + tlen;
yading@11 656
yading@11 657 if (len < 0)
yading@11 658 break;
yading@11 659
yading@11 660 next = avio_tell(s->pb) + tlen;
yading@11 661
yading@11 662 if (!tlen) {
yading@11 663 if (tag[0])
yading@11 664 av_log(s, AV_LOG_DEBUG, "Invalid empty frame %s, skipping.\n", tag);
yading@11 665 continue;
yading@11 666 }
yading@11 667
yading@11 668 if (tflags & ID3v2_FLAG_DATALEN) {
yading@11 669 if (tlen < 4)
yading@11 670 break;
yading@11 671 dlen = avio_rb32(s->pb);
yading@11 672 tlen -= 4;
yading@11 673 } else
yading@11 674 dlen = tlen;
yading@11 675
yading@11 676 tcomp = tflags & ID3v2_FLAG_COMPRESSION;
yading@11 677 tencr = tflags & ID3v2_FLAG_ENCRYPTION;
yading@11 678
yading@11 679 /* skip encrypted tags and, if no zlib, compressed tags */
yading@11 680 if (tencr || (!CONFIG_ZLIB && tcomp)) {
yading@11 681 const char *type;
yading@11 682 if (!tcomp)
yading@11 683 type = "encrypted";
yading@11 684 else if (!tencr)
yading@11 685 type = "compressed";
yading@11 686 else
yading@11 687 type = "encrypted and compressed";
yading@11 688
yading@11 689 av_log(s, AV_LOG_WARNING, "Skipping %s ID3v2 frame %s.\n", type, tag);
yading@11 690 avio_skip(s->pb, tlen);
yading@11 691 /* check for text tag or supported special meta tag */
yading@11 692 } else if (tag[0] == 'T' || (extra_meta && (extra_func = get_extra_meta_func(tag, isv34)))) {
yading@11 693 pbx = s->pb;
yading@11 694
yading@11 695 if (unsync || tunsync || tcomp) {
yading@11 696 av_fast_malloc(&buffer, &buffer_size, tlen);
yading@11 697 if (!buffer) {
yading@11 698 av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", tlen);
yading@11 699 goto seek;
yading@11 700 }
yading@11 701 }
yading@11 702 if (unsync || tunsync) {
yading@11 703 int64_t end = avio_tell(s->pb) + tlen;
yading@11 704 uint8_t *b;
yading@11 705
yading@11 706 b = buffer;
yading@11 707 while (avio_tell(s->pb) < end && b - buffer < tlen) {
yading@11 708 *b++ = avio_r8(s->pb);
yading@11 709 if (*(b - 1) == 0xff && avio_tell(s->pb) < end - 1 && b - buffer < tlen) {
yading@11 710 uint8_t val = avio_r8(s->pb);
yading@11 711 *b++ = val ? val : avio_r8(s->pb);
yading@11 712 }
yading@11 713 }
yading@11 714 ffio_init_context(&pb, buffer, b - buffer, 0, NULL, NULL, NULL, NULL);
yading@11 715 tlen = b - buffer;
yading@11 716 pbx = &pb; // read from sync buffer
yading@11 717 }
yading@11 718
yading@11 719 #if CONFIG_ZLIB
yading@11 720 if (tcomp) {
yading@11 721 int err;
yading@11 722
yading@11 723 av_log(s, AV_LOG_DEBUG, "Compresssed frame %s tlen=%d dlen=%ld\n", tag, tlen, dlen);
yading@11 724
yading@11 725 av_fast_malloc(&uncompressed_buffer, &uncompressed_buffer_size, dlen);
yading@11 726 if (!uncompressed_buffer) {
yading@11 727 av_log(s, AV_LOG_ERROR, "Failed to alloc %ld bytes\n", dlen);
yading@11 728 goto seek;
yading@11 729 }
yading@11 730
yading@11 731 if (!(unsync || tunsync)) {
yading@11 732 err = avio_read(s->pb, buffer, tlen);
yading@11 733 if (err < 0) {
yading@11 734 av_log(s, AV_LOG_ERROR, "Failed to read compressed tag\n");
yading@11 735 goto seek;
yading@11 736 }
yading@11 737 tlen = err;
yading@11 738 }
yading@11 739
yading@11 740 err = uncompress(uncompressed_buffer, &dlen, buffer, tlen);
yading@11 741 if (err != Z_OK) {
yading@11 742 av_log(s, AV_LOG_ERROR, "Failed to uncompress tag: %d\n", err);
yading@11 743 goto seek;
yading@11 744 }
yading@11 745 ffio_init_context(&pb, uncompressed_buffer, dlen, 0, NULL, NULL, NULL, NULL);
yading@11 746 tlen = dlen;
yading@11 747 pbx = &pb; // read from sync buffer
yading@11 748 }
yading@11 749 #endif
yading@11 750 if (tag[0] == 'T')
yading@11 751 /* parse text tag */
yading@11 752 read_ttag(s, pbx, tlen, tag);
yading@11 753 else
yading@11 754 /* parse special meta tag */
yading@11 755 extra_func->read(s, pbx, tlen, tag, extra_meta);
yading@11 756 }
yading@11 757 else if (!tag[0]) {
yading@11 758 if (tag[1])
yading@11 759 av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding\n");
yading@11 760 avio_skip(s->pb, tlen);
yading@11 761 break;
yading@11 762 }
yading@11 763 /* Skip to end of tag */
yading@11 764 seek:
yading@11 765 avio_seek(s->pb, next, SEEK_SET);
yading@11 766 }
yading@11 767
yading@11 768 if (version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
yading@11 769 end += 10;
yading@11 770
yading@11 771 error:
yading@11 772 if (reason)
yading@11 773 av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
yading@11 774 avio_seek(s->pb, end, SEEK_SET);
yading@11 775 av_free(buffer);
yading@11 776 av_free(uncompressed_buffer);
yading@11 777 return;
yading@11 778 }
yading@11 779
yading@11 780 void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta)
yading@11 781 {
yading@11 782 int len, ret;
yading@11 783 uint8_t buf[ID3v2_HEADER_SIZE];
yading@11 784 int found_header;
yading@11 785 int64_t off;
yading@11 786
yading@11 787 do {
yading@11 788 /* save the current offset in case there's nothing to read/skip */
yading@11 789 off = avio_tell(s->pb);
yading@11 790 ret = avio_read(s->pb, buf, ID3v2_HEADER_SIZE);
yading@11 791 if (ret != ID3v2_HEADER_SIZE) {
yading@11 792 avio_seek(s->pb, off, SEEK_SET);
yading@11 793 break;
yading@11 794 }
yading@11 795 found_header = ff_id3v2_match(buf, magic);
yading@11 796 if (found_header) {
yading@11 797 /* parse ID3v2 header */
yading@11 798 len = ((buf[6] & 0x7f) << 21) |
yading@11 799 ((buf[7] & 0x7f) << 14) |
yading@11 800 ((buf[8] & 0x7f) << 7) |
yading@11 801 (buf[9] & 0x7f);
yading@11 802 ff_id3v2_parse(s, len, buf[3], buf[5], extra_meta);
yading@11 803 } else {
yading@11 804 avio_seek(s->pb, off, SEEK_SET);
yading@11 805 }
yading@11 806 } while (found_header);
yading@11 807 ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv);
yading@11 808 ff_metadata_conv(&s->metadata, NULL, id3v2_2_metadata_conv);
yading@11 809 ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv);
yading@11 810 merge_date(&s->metadata);
yading@11 811 }
yading@11 812
yading@11 813 void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
yading@11 814 {
yading@11 815 ID3v2ExtraMeta *current = *extra_meta, *next;
yading@11 816 const ID3v2EMFunc *extra_func;
yading@11 817
yading@11 818 while (current) {
yading@11 819 if ((extra_func = get_extra_meta_func(current->tag, 1)))
yading@11 820 extra_func->free(current->data);
yading@11 821 next = current->next;
yading@11 822 av_freep(&current);
yading@11 823 current = next;
yading@11 824 }
yading@11 825 }
yading@11 826
yading@11 827 int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
yading@11 828 {
yading@11 829 ID3v2ExtraMeta *cur;
yading@11 830
yading@11 831 for (cur = *extra_meta; cur; cur = cur->next) {
yading@11 832 ID3v2ExtraMetaAPIC *apic;
yading@11 833 AVStream *st;
yading@11 834
yading@11 835 if (strcmp(cur->tag, "APIC"))
yading@11 836 continue;
yading@11 837 apic = cur->data;
yading@11 838
yading@11 839 if (!(st = avformat_new_stream(s, NULL)))
yading@11 840 return AVERROR(ENOMEM);
yading@11 841
yading@11 842 st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
yading@11 843 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@11 844 st->codec->codec_id = apic->id;
yading@11 845 av_dict_set(&st->metadata, "title", apic->description, 0);
yading@11 846 av_dict_set(&st->metadata, "comment", apic->type, 0);
yading@11 847
yading@11 848 av_init_packet(&st->attached_pic);
yading@11 849 st->attached_pic.buf = apic->buf;
yading@11 850 st->attached_pic.data = apic->buf->data;
yading@11 851 st->attached_pic.size = apic->buf->size - FF_INPUT_BUFFER_PADDING_SIZE;
yading@11 852 st->attached_pic.stream_index = st->index;
yading@11 853 st->attached_pic.flags |= AV_PKT_FLAG_KEY;
yading@11 854
yading@11 855 apic->buf = NULL;
yading@11 856 }
yading@11 857
yading@11 858 return 0;
yading@11 859 }