id3v2: fix unsynchronization

The ID3v2 "unsynchronization scheme" requires replacing any 0xFF 0x00
sequences with 0xFF. This has to be done on every byte of the source
data, while the current code skipped a byte after a replacement. This
meant 0xFF 0x00 0xFF 00 was translated to 0xFF 0xFF 0x00 instead of 0xFF
0xFF. It feels a bit messy to do this correctly with the avio use. But
fortunately, this translation can be done in-place, so we can just do it
in memory.

Inspired by what taglib does.

Also see 9ae80e6a9c. (The sample file for
that commit is gone, so it could not be retested.)
This commit is contained in:
wm4 2018-01-30 13:22:53 +01:00
parent ff46124b0d
commit 48bc9fffd1
1 changed files with 13 additions and 11 deletions

View File

@ -976,19 +976,21 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
}
}
if (unsync || tunsync) {
int64_t end = avio_tell(pb) + tlen;
uint8_t *b;
uint8_t *b = buffer;
uint8_t *t = buffer;
uint8_t *end = t + tlen;
b = buffer;
while (avio_tell(pb) < end && b - buffer < tlen && !pb->eof_reached) {
*b++ = avio_r8(pb);
if (*(b - 1) == 0xff && avio_tell(pb) < end - 1 &&
b - buffer < tlen &&
!pb->eof_reached ) {
uint8_t val = avio_r8(pb);
*b++ = val ? val : avio_r8(pb);
}
if (avio_read(pb, buffer, tlen) != tlen) {
av_log(s, AV_LOG_ERROR, "Failed to read tag data\n");
goto seek;
}
while (t != end) {
*b++ = *t++;
if (t != end && t[-1] == 0xff && !t[0])
t++;
}
ffio_init_context(&pb_local, buffer, b - buffer, 0, NULL, NULL, NULL,
NULL);
tlen = b - buffer;