From 50fcd5be36d04a7674f5eef267ef71117efa3796 Mon Sep 17 00:00:00 2001 From: Patrick Dehne Date: Fri, 19 Jun 2009 14:03:35 +0000 Subject: [PATCH] Move id3v1/id3v2 handling code from mp3.c to id3v[12].c. patch by Patrick Dehne, patrick mysonicweb com Originally committed as revision 19224 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/id3v1.c | 70 ++++++++++++++++++++++++++++++++++++++++ libavformat/id3v1.h | 7 ++++ libavformat/id3v2.c | 20 ++++++++++++ libavformat/id3v2.h | 5 +++ libavformat/mp3.c | 78 ++------------------------------------------- 5 files changed, 104 insertions(+), 76 deletions(-) diff --git a/libavformat/id3v1.c b/libavformat/id3v1.c index f7712875b2..7281974182 100644 --- a/libavformat/id3v1.c +++ b/libavformat/id3v1.c @@ -20,6 +20,7 @@ */ #include "id3v1.h" +#include "libavcodec/avcodec.h" const char *ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] = { [0] = "Blues", @@ -149,3 +150,72 @@ const char *ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1] = { [124] = "Euro-House", [125] = "Dance Hall", }; + +static void get_string(AVFormatContext *s, const char *key, + const uint8_t *buf, int buf_size) +{ + int i, c; + char *q, str[512]; + + q = str; + for(i = 0; i < buf_size; i++) { + c = buf[i]; + if (c == '\0') + break; + if ((q - str) >= sizeof(str) - 1) + break; + *q++ = c; + } + *q = '\0'; + + if (*str) + av_metadata_set(&s->metadata, key, str); +} + +/** + * Parse an ID3v1 tag + * + * @param buf ID3v1_TAG_SIZE long buffer containing the tag + */ +static int parse_tag(AVFormatContext *s, const uint8_t *buf) +{ + char str[5]; + int genre; + + if (!(buf[0] == 'T' && + buf[1] == 'A' && + buf[2] == 'G')) + return -1; + get_string(s, "title", buf + 3, 30); + get_string(s, "author", buf + 33, 30); + get_string(s, "album", buf + 63, 30); + get_string(s, "year", buf + 93, 4); + get_string(s, "comment", buf + 97, 30); + if (buf[125] == 0 && buf[126] != 0) { + snprintf(str, sizeof(str), "%d", buf[126]); + av_metadata_set(&s->metadata, "track", str); + } + genre = buf[127]; + if (genre <= ID3v1_GENRE_MAX) + av_metadata_set(&s->metadata, "genre", ff_id3v1_genre_str[genre]); + return 0; +} + +void ff_id3v1_read(AVFormatContext *s) +{ + int ret, filesize; + uint8_t buf[ID3v1_TAG_SIZE]; + + if (!url_is_streamed(s->pb)) { + /* XXX: change that */ + filesize = url_fsize(s->pb); + if (filesize > 128) { + url_fseek(s->pb, filesize - 128, SEEK_SET); + ret = get_buffer(s->pb, buf, ID3v1_TAG_SIZE); + if (ret == ID3v1_TAG_SIZE) { + parse_tag(s, buf); + } + url_fseek(s->pb, 0, SEEK_SET); + } + } +} diff --git a/libavformat/id3v1.h b/libavformat/id3v1.h index 02333a1601..b5dcedc551 100644 --- a/libavformat/id3v1.h +++ b/libavformat/id3v1.h @@ -22,6 +22,8 @@ #ifndef AVFORMAT_ID3V1_H #define AVFORMAT_ID3V1_H +#include "avformat.h" + #define ID3v1_TAG_SIZE 128 #define ID3v1_GENRE_MAX 125 @@ -31,5 +33,10 @@ */ extern const char *ff_id3v1_genre_str[ID3v1_GENRE_MAX + 1]; +/** + * Read an ID3v1 tag + */ +void ff_id3v1_read(AVFormatContext *s); + #endif /* AVFORMAT_ID3V1_H */ diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 6a3ecb9e75..9bf9f1aea6 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -48,6 +48,26 @@ int ff_id3v2_tag_len(const uint8_t * buf) return len; } +void ff_id3v2_read(AVFormatContext *s) +{ + int len, ret; + uint8_t buf[ID3v2_HEADER_SIZE]; + + ret = get_buffer(s->pb, buf, ID3v2_HEADER_SIZE); + if (ret != ID3v2_HEADER_SIZE) + return; + if (ff_id3v2_match(buf)) { + /* parse ID3v2 header */ + len = ((buf[6] & 0x7f) << 21) | + ((buf[7] & 0x7f) << 14) | + ((buf[8] & 0x7f) << 7) | + (buf[9] & 0x7f); + ff_id3v2_parse(s, len, buf[3], buf[5]); + } else { + url_fseek(s->pb, 0, SEEK_SET); + } +} + static unsigned int get_size(ByteIOContext *s, int len) { int v = 0; diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h index f7b8627593..791c00c595 100644 --- a/libavformat/id3v2.h +++ b/libavformat/id3v2.h @@ -46,4 +46,9 @@ int ff_id3v2_tag_len(const uint8_t *buf); */ void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags); +/** + * Read an ID3v2 tag + */ +void ff_id3v2_read(AVFormatContext *s); + #endif /* AVFORMAT_ID3V2_H */ diff --git a/libavformat/mp3.c b/libavformat/mp3.c index 691d496726..c80b5d44f5 100644 --- a/libavformat/mp3.c +++ b/libavformat/mp3.c @@ -27,52 +27,6 @@ #include "id3v2.h" #include "id3v1.h" -static void id3v1_get_string(AVFormatContext *s, const char *key, - const uint8_t *buf, int buf_size) -{ - int i, c; - char *q, str[512]; - - q = str; - for(i = 0; i < buf_size; i++) { - c = buf[i]; - if (c == '\0') - break; - if ((q - str) >= sizeof(str) - 1) - break; - *q++ = c; - } - *q = '\0'; - - if (*str) - av_metadata_set(&s->metadata, key, str); -} - -/* 'buf' must be ID3v1_TAG_SIZE byte long */ -static int id3v1_parse_tag(AVFormatContext *s, const uint8_t *buf) -{ - char str[5]; - int genre; - - if (!(buf[0] == 'T' && - buf[1] == 'A' && - buf[2] == 'G')) - return -1; - id3v1_get_string(s, "title", buf + 3, 30); - id3v1_get_string(s, "author", buf + 33, 30); - id3v1_get_string(s, "album", buf + 63, 30); - id3v1_get_string(s, "year", buf + 93, 4); - id3v1_get_string(s, "comment", buf + 97, 30); - if (buf[125] == 0 && buf[126] != 0) { - snprintf(str, sizeof(str), "%d", buf[126]); - av_metadata_set(&s->metadata, "track", str); - } - genre = buf[127]; - if (genre <= ID3v1_GENRE_MAX) - av_metadata_set(&s->metadata, "genre", ff_id3v1_genre_str[genre]); - return 0; -} - /* mp3 read */ static int mp3_read_probe(AVProbeData *p) @@ -172,8 +126,6 @@ static int mp3_read_header(AVFormatContext *s, AVFormatParameters *ap) { AVStream *st; - uint8_t buf[ID3v1_TAG_SIZE]; - int len, ret, filesize; int64_t off; st = av_new_stream(s, 0); @@ -185,34 +137,8 @@ static int mp3_read_header(AVFormatContext *s, st->need_parsing = AVSTREAM_PARSE_FULL; st->start_time = 0; - /* try to get the TAG */ - if (!url_is_streamed(s->pb)) { - /* XXX: change that */ - filesize = url_fsize(s->pb); - if (filesize > 128) { - url_fseek(s->pb, filesize - 128, SEEK_SET); - ret = get_buffer(s->pb, buf, ID3v1_TAG_SIZE); - if (ret == ID3v1_TAG_SIZE) { - id3v1_parse_tag(s, buf); - } - url_fseek(s->pb, 0, SEEK_SET); - } - } - - /* if ID3v2 header found, skip it */ - ret = get_buffer(s->pb, buf, ID3v2_HEADER_SIZE); - if (ret != ID3v2_HEADER_SIZE) - return -1; - if (ff_id3v2_match(buf)) { - /* parse ID3v2 header */ - len = ((buf[6] & 0x7f) << 21) | - ((buf[7] & 0x7f) << 14) | - ((buf[8] & 0x7f) << 7) | - (buf[9] & 0x7f); - ff_id3v2_parse(s, len, buf[3], buf[5]); - } else { - url_fseek(s->pb, 0, SEEK_SET); - } + ff_id3v1_read(s); + ff_id3v2_read(s); off = url_ftell(s->pb); if (mp3_parse_vbr_tags(s, st, off) < 0)