Index: apps/mp3data.c =================================================================== --- apps/mp3data.c (revision 29537) +++ apps/mp3data.c (working copy) @@ -201,41 +201,60 @@ return true; } +static bool headers_have_same_type(unsigned long header1, + unsigned long header2) +{ + /* Compare MPEG version, layer and sampling frequency. */ + unsigned int mask = 0xfffe0c00; + header1 &= mask; + header2 &= mask; + return header1 ? (header1 == header2) : false; +} + static unsigned long __find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header, int(*getfunc)(int fd, unsigned char *c)) { unsigned long header=0; unsigned char tmp; - int i; - - long pos = 0; - - /* We remember the last header we found, to use as a template to see if - the header we find has the same frequency, layer etc */ - last_header &= 0xffff0c00; + long pos = 0; + long last_pos = 0; - /* Fill up header with first 24 bits */ - for(i = 0; i < 3; i++) { - header <<= 8; - if(!getfunc(fd, &tmp)) - return 0; - header |= tmp; - pos++; - } + /* Only keep last_header if it is a valid mp3 frame header. */ + last_header = is_mp3frameheader(last_header) ? last_header : 0; + /* We will search until we find two consecutive mpeg frame headers with + * the same MPEG version, layer and sampling frequency. The first header + * of this pair is assumed to be the first valid mpeg frame header of the + * whole file. */ do { + /* Shift by 1 byte. */ header <<= 8; - if(!getfunc(fd, &tmp)) + if (!getfunc(fd, &tmp)) return 0; header |= tmp; pos++; - if(max_offset > 0 && pos > max_offset) + + /* Abort if max_offset is reached. Stop parsing. */ + if (max_offset > 0 && pos > max_offset) return 0; - } while(!is_mp3frameheader(header) || - (last_header?((header & 0xffff0c00) != last_header):false)); + + if (is_mp3frameheader(header)) { + if (headers_have_same_type(last_header, header)) { + /* The current header is valid and is of the same type as the + * saved one. We are finished. */ + break; + } else { + /* The current header is valid, but different to the saved one. + * Take this header as reference for further parsing. */ + last_header = header; + last_pos = pos; + } + } + + } while (true); - *offset = pos - 4; + *offset = last_pos - 4; if(*offset) VDEBUGF("Warning: skipping %ld bytes of garbage\n", *offset);