summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-10-22 13:06:31 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-10-22 13:06:31 +0000
commit5557fe3259b1e0c5fb6c7527456b6cbca9da9208 (patch)
tree00e0afc4cac36570c23eb43bd917d8e8c5b73fc6
parent9ace15871d1d087d23a55ac5f48a887aa87872ba (diff)
downloadrockbox-5557fe3259b1e0c5fb6c7527456b6cbca9da9208.zip
rockbox-5557fe3259b1e0c5fb6c7527456b6cbca9da9208.tar.gz
rockbox-5557fe3259b1e0c5fb6c7527456b6cbca9da9208.tar.bz2
rockbox-5557fe3259b1e0c5fb6c7527456b6cbca9da9208.tar.xz
Added unsynchronization
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3983 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/id3.c105
1 files changed, 88 insertions, 17 deletions
diff --git a/firmware/id3.c b/firmware/id3.c
index d059841..a76cd2b 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -108,6 +108,35 @@ struct tag_resolver {
int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
};
+static int unsynchronize(char* tag, int len)
+{
+ int i;
+ unsigned char c;
+ unsigned char *rp, *wp;
+ bool ff_found = false;
+
+ wp = rp = tag;
+
+ rp = (unsigned char *)tag;
+ for(i = 0;i < len;i++) {
+ /* Read the next byte and write it back, but don't increment the
+ write pointer */
+ c = *rp++;
+ *wp = c;
+ if(ff_found) {
+ /* Increment the write pointer if it isn't an unsynch pattern */
+ if(c != 0)
+ wp++;
+ ff_found = false;
+ } else {
+ if(c == 0xff)
+ ff_found = true;
+ wp++;
+ }
+ }
+ return (int)wp - (int)tag;
+}
+
/* parse numeric value from string */
static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
{
@@ -326,12 +355,17 @@ static void setid3v2title(int fd, struct mp3entry *entry)
int size;
int bufferpos = 0, totframelen, framelen;
char header[10];
+ char tmp[4];
unsigned char version;
char *buffer = entry->id3v2buf;
int bytesread = 0;
int buffersize = sizeof(entry->id3v2buf);
+ unsigned char global_flags;
int flags;
int skip;
+ bool global_unsynch = false;
+ bool unsynch = false;
+ int data_length_ind;
int i;
/* Bail out if the tag is shorter than 10 bytes */
@@ -372,9 +406,11 @@ static void setid3v2title(int fd, struct mp3entry *entry)
entry->genre = 0xff;
entry->title = entry->artist = entry->album = NULL;
+ global_flags = header[5];
+
/* Skip the extended header if it is present */
if(version >= ID3_VER_2_4) {
- if(header[5] & 0x40) {
+ if(global_flags & 0x40) {
if(4 != read(fd, header, 4))
return;
@@ -384,6 +420,11 @@ static void setid3v2title(int fd, struct mp3entry *entry)
lseek(fd, framelen - 4, SEEK_CUR);
}
}
+
+ /* Is unsynchronization applied? */
+ if(global_flags & 0x80) {
+ global_unsynch = true;
+ }
/*
* We must have at least minframesize bytes left for the
@@ -425,13 +466,18 @@ static void setid3v2title(int fd, struct mp3entry *entry)
if(framelen == 0)
return;
+ unsynch = false;
+ data_length_ind = 0;
+
if(flags)
{
skip = 0;
- if(flags & 0x0040) /* Grouping identity */
- skip++;
-
+ if(flags & 0x0040) { /* Grouping identity */
+ lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
+ framelen--;
+ }
+
if(flags & 0x000c) /* Compression or encryption */
{
/* Skip it using the total size in case
@@ -441,19 +487,18 @@ static void setid3v2title(int fd, struct mp3entry *entry)
continue;
}
- /* The Unsynchronization flag can't be trusted, so we
- don't check it for now... */
-
- if(flags & 0x0001) /* Data length indicator */
- skip += 4;
+ if(flags & 0x0002) /* Unsynchronization */
+ unsynch = true;
- if(skip)
- {
- lseek(fd, skip, SEEK_CUR);
- framelen -= skip;
+ if(flags & 0x0001) { /* Data length indicator */
+ if(4 != read(fd, tmp, 4))
+ return;
+
+ data_length_ind = UNSYNC(tmp[0], tmp[1], tmp[2], tmp[3]);
+ framelen -= 4;
}
}
-
+
/* If the frame is larger than the remaining buffer space we try
to read as much as would fit in the buffer */
if(framelen >= buffersize - bufferpos)
@@ -494,6 +539,10 @@ static void setid3v2title(int fd, struct mp3entry *entry)
size -= bytesread;
*ptag = buffer + bufferpos;
+
+ if(global_unsynch || unsynch)
+ bytesread = unsynchronize(*ptag, bytesread);
+
unicode_munge( ptag, &bytesread );
tag = *ptag;
tag[bytesread + 1] = 0;
@@ -508,9 +557,31 @@ static void setid3v2title(int fd, struct mp3entry *entry)
/* no tag in tagList was found, or it was a repeat.
skip it using the total size */
- size -= totframelen;
- if( lseek(fd, totframelen, SEEK_CUR) == -1 )
- return;
+ /* We may need to compensate for the unsynchronization scheme */
+ if(global_unsynch && !data_length_ind) {
+ bool ff_found = false;
+
+ for(i = 0;i < totframelen;i++) {
+ unsigned char c;
+ bytesread = read(fd, &c, 1);
+ if(ff_found) {
+ if(c == 0)
+ /* Found an unsynch pattern, counting it */
+ totframelen++;
+ ff_found = false;
+ } else {
+ if(c == 0xff)
+ ff_found = true;
+ }
+ }
+ } else {
+ if(data_length_ind)
+ totframelen = data_length_ind;
+
+ size -= totframelen;
+ if( lseek(fd, totframelen, SEEK_CUR) == -1 )
+ return;
+ }
}
}
}