summaryrefslogtreecommitdiff
path: root/libavformat/id3v2.c
diff options
context:
space:
mode:
authorPatrick Dehne <patrick@mysonicweb.com>2009-06-11 15:26:57 +0000
committerDiego Biurrun <diego@biurrun.de>2009-06-11 15:26:57 +0000
commit7541118286470038b97edd0070f3712d98397065 (patch)
treea78f0088450ceec260f10aede6c7fb09efcea098 /libavformat/id3v2.c
parentdc8229015c18d391797529ab84a8d11446fd94d0 (diff)
Move id3v2 parsing code from mp3.c to id3v2.h and id3v2.c.
patch by Patrick Dehne, patrick mysonicweb com Originally committed as revision 19155 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/id3v2.c')
-rw-r--r--libavformat/id3v2.c147
1 files changed, 147 insertions, 0 deletions
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 018fd51dc8..a0581e6149 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -20,6 +20,8 @@
*/
#include "id3v2.h"
+#include "id3v1.h"
+#include "libavutil/avstring.h"
int ff_id3v2_match(const uint8_t *buf)
{
@@ -45,3 +47,148 @@ int ff_id3v2_tag_len(const uint8_t * buf)
len += ID3v2_HEADER_SIZE;
return len;
}
+
+static unsigned int get_size(ByteIOContext *s, int len)
+{
+ int v=0;
+ while(len--)
+ v= (v<<7) + (get_byte(s)&0x7F);
+ return v;
+}
+
+static void read_ttag(AVFormatContext *s, int taglen, const char *key)
+{
+ char *q, dst[512];
+ int len, dstlen = sizeof(dst) - 1;
+ unsigned genre;
+
+ dst[0]= 0;
+ if(taglen < 1)
+ return;
+
+ taglen--; /* account for encoding type byte */
+
+ switch(get_byte(s->pb)) { /* encoding type */
+
+ case 0: /* ISO-8859-1 (0 - 255 maps directly into unicode) */
+ q = dst;
+ while(taglen--) {
+ uint8_t tmp;
+ PUT_UTF8(get_byte(s->pb), tmp, if (q - dst < dstlen - 1) *q++ = tmp;)
+ }
+ *q = '\0';
+ break;
+
+ case 3: /* UTF-8 */
+ len = FFMIN(taglen, dstlen-1);
+ get_buffer(s->pb, dst, len);
+ dst[len] = 0;
+ break;
+ }
+
+ if (!strcmp(key, "genre")
+ && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1)
+ && genre <= ID3v1_GENRE_MAX)
+ av_strlcpy(dst, ff_id3v1_genre_str[genre], sizeof(dst));
+
+ if (*dst)
+ av_metadata_set(&s->metadata, key, dst);
+}
+
+void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
+{
+ int isv34, tlen;
+ uint32_t tag;
+ int64_t next;
+ int taghdrlen;
+ const char *reason;
+
+ switch(version) {
+ case 2:
+ if(flags & 0x40) {
+ reason = "compression";
+ goto error;
+ }
+ isv34 = 0;
+ taghdrlen = 6;
+ break;
+
+ case 3:
+ case 4:
+ isv34 = 1;
+ taghdrlen = 10;
+ break;
+
+ default:
+ reason = "version";
+ goto error;
+ }
+
+ if(flags & 0x80) {
+ reason = "unsynchronization";
+ goto error;
+ }
+
+ if(isv34 && flags & 0x40) /* Extended header present, just skip over it */
+ url_fskip(s->pb, get_size(s->pb, 4));
+
+ while(len >= taghdrlen) {
+ if(isv34) {
+ tag = get_be32(s->pb);
+ tlen = get_size(s->pb, 4);
+ get_be16(s->pb); /* flags */
+ } else {
+ tag = get_be24(s->pb);
+ tlen = get_size(s->pb, 3);
+ }
+ len -= taghdrlen + tlen;
+
+ if(len < 0)
+ break;
+
+ next = url_ftell(s->pb) + tlen;
+
+ switch(tag) {
+ case MKBETAG('T', 'I', 'T', '2'):
+ case MKBETAG(0, 'T', 'T', '2'):
+ read_ttag(s, tlen, "title");
+ break;
+ case MKBETAG('T', 'P', 'E', '1'):
+ case MKBETAG(0, 'T', 'P', '1'):
+ read_ttag(s, tlen, "author");
+ break;
+ case MKBETAG('T', 'A', 'L', 'B'):
+ case MKBETAG(0, 'T', 'A', 'L'):
+ read_ttag(s, tlen, "album");
+ break;
+ case MKBETAG('T', 'C', 'O', 'N'):
+ case MKBETAG(0, 'T', 'C', 'O'):
+ read_ttag(s, tlen, "genre");
+ break;
+ case MKBETAG('T', 'C', 'O', 'P'):
+ case MKBETAG(0, 'T', 'C', 'R'):
+ read_ttag(s, tlen, "copyright");
+ break;
+ case MKBETAG('T', 'R', 'C', 'K'):
+ case MKBETAG(0, 'T', 'R', 'K'):
+ read_ttag(s, tlen, "track");
+ break;
+ case 0:
+ /* padding, skip to end */
+ url_fskip(s->pb, len);
+ len = 0;
+ continue;
+ }
+ /* Skip to end of tag */
+ url_fseek(s->pb, next, SEEK_SET);
+ }
+
+ if(version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
+ url_fskip(s->pb, 10);
+ return;
+
+ error:
+ av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
+ url_fskip(s->pb, len);
+}
+