This is the bug/patch tracker for Rockbox. Click here for more information.
Quick links: Bugs · Patches · Rockbox frontpage
FS#10240 - Rockbox not handling MP3s with large ID3 frames
Attached to Project:
Rockbox
Opened by Rhino Banga (rhinobanga) - Monday, 25 May 2009, 12:04 GMT+2
Last edited by Andree Buschmann (Buschel) - Sunday, 30 January 2011, 21:52 GMT+2
Opened by Rhino Banga (rhinobanga) - Monday, 25 May 2009, 12:04 GMT+2
Last edited by Andree Buschmann (Buschel) - Sunday, 30 January 2011, 21:52 GMT+2
|
DetailsWhilst RB skips forward past large ID3 frames it doesn't seem to reset it's use of the internal buffer.
This is causing the internal scanning loop to exit early, causing it to miss relevant ID3 tags. In mp3.c:setid3v2title changing this: /* Seek to the next frame */ if(framelen < totframelen) lseek(fd, totframelen - framelen, SEEK_CUR); To this: /* Seek to the next frame */ if(framelen < totframelen) { lseek(fd, totframelen - framelen, SEEK_CUR); bufferpos = 0; } Cured the problem for me and my entire MP3 collection (6000+ tracks) was then catalogued properly on my 80gb iPod. Personally though I think that entire function could do with a re-write to make better use of the buffer. |
This task depends upon
Closed by Andree Buschmann (Buschel)
Sunday, 30 January 2011, 21:52 GMT+2
Reason for closing: Fixed
Additional comments about closing: The underlying issue (incomplete parsing due to early abort when buffer is filled) is fixed with r29174.
Sunday, 30 January 2011, 21:52 GMT+2
Reason for closing: Fixed
Additional comments about closing: The underlying issue (incomplete parsing due to early abort when buffer is filled) is fixed with r29174.
http://forums.rockbox.org/index.php?topic=21757.0
I would suggest you throw a relevant MP3 file at this code, to see it's behaviour and why the above reset worked around the problem.
In the post you said this: "Which got me thinking, if the code seeks to a new position then the internal buffer and buffer position must be invalid but the buffer position is not being reset." If the code seeks to a new position, then the frame was larger than the remaining buffer space, so the frame wasn't fully read. Still, the buffer might not be completely full at this point (e.g., the frame was in Unicode format but didn't contain many non-ASCII chars), so it's worth trying to read more.
A better work-around for you would be to remove the COMM field from the taglist, so it isn't read, filling up the tag buffer (id3v2buf in mp3entry).
Anyway, after the lseek happens the code jumps to the while loop:
while (size >= minframesize && bufferpos < buffersize - 1) {
The code following that doesn't use the buffer as a read-ahead cache, but instead uses it as a temporary buffer, e.g.:
/* found a tag matching one in tagList, and not yet filled */
tag = buffer + bufferpos;
if(global_unsynch && version <= ID3_VER_2_3)
bytesread = read_unsynched(fd, tag, framelen);
else
bytesread = read(fd, tag, framelen);
So can you explain again why is it inappropriate to reset buffer position so a) it gets past the while loop and b) it uses as much of the temp area buffer as possible.
And when I said "remove the COMM field from the taglist" I referred to the "struct tag_resolver taglist" in metadata/mp3.c. No changes to the tags needed. :) Not a good long-term solution perhaps, but it would solve your immediate problem.
As for the code, what you need to remember is that buffer always points to entry->id3v2buf. If a frame is supported (i.e., is in the taglist), the data of the frame is read into (a part of) buffer. If the read data is to be kept, then bufferpos is updated, and a pointer in entry is set to somewhere in id3v2buf. So buffer (id3v2buf) is not a temporary buffer, it is the area used to store the frame data for later use. Therefore you can't reset bufferpos and expect things to work properly. In this case, entry->comment, which fills the entire buffer, would be overwritten by other tags.