Commit 18bbe9df authored by Alexander Kojevnikov's avatar Alexander Kojevnikov Committed by Carl Eugen Hoyos

Support unsynchronisation for id3v2 tags.

Patch by Alexander Kojevnikov, alexander kojevnikov com

Originally committed as revision 24824 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 8b839ec7
......@@ -77,7 +77,7 @@ static unsigned int get_size(ByteIOContext *s, int len)
return v;
}
static void read_ttag(AVFormatContext *s, int taglen, const char *key)
static void read_ttag(AVFormatContext *s, ByteIOContext *pb, int taglen, const char *key)
{
char *q, dst[512];
const char *val = NULL;
......@@ -91,20 +91,20 @@ static void read_ttag(AVFormatContext *s, int taglen, const char *key)
taglen--; /* account for encoding type byte */
switch (get_byte(s->pb)) { /* encoding type */
switch (get_byte(pb)) { /* encoding type */
case 0: /* ISO-8859-1 (0 - 255 maps directly into unicode) */
q = dst;
while (taglen-- && q - dst < dstlen - 7) {
uint8_t tmp;
PUT_UTF8(get_byte(s->pb), tmp, *q++ = tmp;)
PUT_UTF8(get_byte(pb), tmp, *q++ = tmp;)
}
*q = 0;
break;
case 1: /* UTF-16 with BOM */
taglen -= 2;
switch (get_be16(s->pb)) {
switch (get_be16(pb)) {
case 0xfffe:
get = get_le16;
case 0xfeff:
......@@ -121,7 +121,7 @@ static void read_ttag(AVFormatContext *s, int taglen, const char *key)
uint32_t ch;
uint8_t tmp;
GET_UTF16(ch, ((taglen -= 2) >= 0 ? get(s->pb) : 0), break;)
GET_UTF16(ch, ((taglen -= 2) >= 0 ? get(pb) : 0), break;)
PUT_UTF8(ch, tmp, *q++ = tmp;)
}
*q = 0;
......@@ -129,7 +129,7 @@ static void read_ttag(AVFormatContext *s, int taglen, const char *key)
case 3: /* UTF-8 */
len = FFMIN(taglen, dstlen);
get_buffer(s->pb, dst, len);
get_buffer(pb, dst, len);
dst[len] = 0;
break;
default:
......@@ -156,11 +156,14 @@ static void read_ttag(AVFormatContext *s, int taglen, const char *key)
void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
{
int isv34, tlen;
int isv34, tlen, unsync;
char tag[5];
int64_t next;
int taghdrlen;
const char *reason;
ByteIOContext pb;
unsigned char *buffer = NULL;
int buffer_size = 0;
switch (version) {
case 2:
......@@ -183,15 +186,15 @@ void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
goto error;
}
if (flags & 0x80) {
reason = "unsynchronization";
goto error;
}
unsync = flags & 0x80;
if (isv34 && flags & 0x40) /* Extended header present, just skip over it */
url_fskip(s->pb, get_size(s->pb, 4));
while (len >= taghdrlen) {
unsigned int tflags;
int tunsync = 0;
if (isv34) {
get_buffer(s->pb, tag, 4);
tag[4] = 0;
......@@ -199,7 +202,8 @@ void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
tlen = get_be32(s->pb);
}else
tlen = get_size(s->pb, 4);
get_be16(s->pb); /* flags */
tflags = get_be16(s->pb);
tunsync = tflags & 0x02;
} else {
get_buffer(s->pb, tag, 3);
tag[3] = 0;
......@@ -212,8 +216,23 @@ void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
next = url_ftell(s->pb) + tlen;
if (tag[0] == 'T')
read_ttag(s, tlen, tag);
if (tag[0] == 'T') {
if (unsync || tunsync) {
int i, j;
av_fast_malloc(&buffer, &buffer_size, tlen);
for (i = 0, j = 0; i < tlen; i++, j++) {
buffer[j] = get_byte(s->pb);
if (j > 0 && !buffer[j] && buffer[j - 1] == 0xff) {
/* Unsynchronised byte, skip it */
j--;
}
}
init_put_byte(&pb, buffer, j, 0, NULL, NULL, NULL, NULL);
read_ttag(s, &pb, j, tag);
} else {
read_ttag(s, s->pb, tlen, tag);
}
}
else if (!tag[0]) {
if (tag[1])
av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding");
......@@ -230,11 +249,14 @@ void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags)
}
if (version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */
url_fskip(s->pb, 10);
av_free(buffer);
return;
error:
av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason);
url_fskip(s->pb, len);
av_free(buffer);
}
const AVMetadataConv ff_id3v2_metadata_conv[] = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment