Index: apps/mp3data.h
===================================================================
--- apps/mp3data.h (revision 29537)
+++ apps/mp3data.h (working copy)
@@ -57,17 +57,29 @@

#define MAX_XING_HEADER_SIZE 576

-unsigned long find_next_frame(int fd, long *offset, long max_offset,
- unsigned long last_header);
-unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset,
- unsigned long last_header);
-int get_mp3file_info(int fd, struct mp3info *info);
-int count_mp3_frames(int fd, int startpos, int filesize,
+unsigned long find_next_frame(int fd,
+ long *offset,
+ long max_offset,
+ unsigned long reference_header);
+unsigned long mem_find_next_frame(int startpos,
+ long *offset,
+ long max_offset,
+ unsigned long reference_header);
+int get_mp3file_info(int fd,
+ struct mp3info *info);
+int count_mp3_frames(int fd,
+ int startpos,
+ int filesize,
void (*progressfunc)(int));
-int create_xing_header(int fd, long startpos, long filesize,
- unsigned char *buf, unsigned long num_frames,
- unsigned long rec_time, unsigned long header_template,
- void (*progressfunc)(int), bool generate_toc);
+int create_xing_header(int fd,
+ long startpos,
+ long filesize,
+ unsigned char *buf,
+ unsigned long num_frames,
+ unsigned long rec_time,
+ unsigned long header_template,
+ void (*progressfunc)(int),
+ bool generate_toc);

extern unsigned long bytes2int(unsigned long b0,
unsigned long b1,
Index: apps/plugin.h
===================================================================
--- apps/plugin.h (revision 29537)
+++ apps/plugin.h (working copy)
@@ -818,7 +818,7 @@
unsigned long rec_time, unsigned long header_template,
void (*progressfunc)(int), bool generate_toc);
unsigned long (*find_next_frame)(int fd, long *offset,
- long max_offset, unsigned long last_header);
+ long max_offset, unsigned long reference_header);

#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
unsigned short (*peak_meter_scale_value)(unsigned short val,
Index: apps/mp3data.c
===================================================================
--- apps/mp3data.c (revision 29583)
+++ apps/mp3data.c (working copy)
@@ -39,6 +39,7 @@
#include "mp3data.h"
#include "file.h"
#include "buffer.h"
+#include "metadata/metadata_common.h"

// #define DEBUG_VERBOSE

@@ -201,39 +202,73 @@
return true;
}

+static bool headers_have_same_type(unsigned long header1,
+ unsigned long header2)
+{
+ /* Compare MPEG version, layer and sampling frequency. If header1 is zero
+ * it is assumed the headers are of same type. */
+ unsigned int mask = 0xfffe0c00;
+ header1 &= mask;
+ header2 &= mask;
+ return header1 ? (header1 == header2) : true;
+}
+
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 reference_header,
+ int(*getfunc)(int fd, unsigned char *c),
+ bool single_header)
{
unsigned long header=0;
unsigned char tmp;
- int i;
+ long pos = 0;

- 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;
-
- /* Fill up header with first 24 bits */
- for(i = 0; i < 3; i++) {
- header <<= 8;
- if(!getfunc(fd, &tmp))
- return 0;
- header |= tmp;
- pos++;
- }
-
+ /* 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 stream. */
do {
+ /* Read 1 new 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 (single_header) {
+ /* We only search for a single valid header that has the same
+ * type as the reference_header. We are finished. */
+ if (headers_have_same_type(reference_header, header))
+ break;
+ } else {
+ /* The current header is valid. Now gather the frame size,
+ * seek to this byte position and check if there is another
+ * valid MPEG frame header of the same type. */
+ struct mp3info info;
+
+ /* Gather frame size from given header and seek to next
+ * frame header. */
+ mp3headerinfo(&info, header);
+ lseek(fd, info.frame_size-4, SEEK_CUR);
+
+ /* Read possible next frame header and seek back to last frame
+ * headers byte position. */
+ reference_header = 0;
+ read_uint32be(fd, (uint32_t*)&reference_header);
+ lseek(fd, -info.frame_size, SEEK_CUR);
+
+ /* The current header is valid and is of the same type as the
+ * previous one. We are finished. */
+ if (headers_have_same_type(header, reference_header))
+ break;
+ }
+ }
+
+ } while (true);

*offset = pos - 4;

@@ -248,9 +283,13 @@
return read(fd, c, 1);
}

-unsigned long find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header)
+unsigned long find_next_frame(int fd,
+ long *offset,
+ long max_offset,
+ unsigned long reference_header)
{
- return __find_next_frame(fd, offset, max_offset, last_header, fileread);
+ return __find_next_frame(fd, offset, max_offset, reference_header,
+ fileread, true);
}

#ifndef __PCTOOL__
@@ -312,10 +351,9 @@
fnf_read_index = 0;
}

-static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset,
- unsigned long last_header)
+static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset)
{
- return __find_next_frame(fd, offset, max_offset, last_header, buf_getbyte);
+ return __find_next_frame(fd, offset, max_offset, 0, buf_getbyte, true);
}

static int audiobuflen;
@@ -337,15 +375,18 @@
return 1;
}

-unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset,
- unsigned long last_header)
+unsigned long mem_find_next_frame(int startpos,
+ long *offset,
+ long max_offset,
+ unsigned long reference_header)
{
audiobuflen = audiobufend - audiobuf;
mem_pos = startpos;
mem_cnt = 0;
mem_maxlen = max_offset;

- return __find_next_frame(0, offset, max_offset, last_header, mem_getbyte);
+ return __find_next_frame(0, offset, max_offset, reference_header,
+ mem_getbyte, true);
}
#endif

@@ -446,17 +487,20 @@
}

/* Seek to next mpeg header and extract relevant information. */
-static int get_next_header_info(int fd, long *bytecount, struct mp3info *info)
+static int get_next_header_info(int fd, long *bytecount, struct mp3info *info,
+ bool single_header)
{
long tmp;
- unsigned long header = find_next_frame(fd, &tmp, 0x20000, 0);
+ unsigned long header = 0;
+
+ header = __find_next_frame(fd, &tmp, 0x20000, 0, fileread, single_header);
if(header == 0)
return -1;

if(!mp3headerinfo(info, header))
return -2;

- /* Next header is tmp bytes away. */
+ /* Next frame header is tmp bytes away. */
*bytecount += tmp;

return 0;
@@ -478,8 +522,8 @@
info->enc_padding = -1;
#endif

- /* Get the very first MPEG frame. */
- result = get_next_header_info(fd, &bytecount, info);
+ /* Get the very first single MPEG frame. */
+ result = get_next_header_info(fd, &bytecount, info, true);
if(result)
return result;

@@ -514,7 +558,7 @@
bytecount += info->frame_size;

/* Now get the next frame to read the real info about the mp3 stream */
- result = get_next_header_info(fd, &bytecount, info);
+ result = get_next_header_info(fd, &bytecount, info, false);
if(result)
return result;

@@ -528,7 +572,7 @@
bytecount += info->frame_size;

/* Now get the next frame to read the real info about the mp3 stream */
- result = get_next_header_info(fd, &bytecount, info);
+ result = get_next_header_info(fd, &bytecount, info, false);
if(result)
return result;

@@ -537,6 +581,13 @@
else
{
VDEBUGF("-- No VBR header --\n");
+
+ /* There was no VBR header found. So, we seek back to beginning and
+ * search for the first MPEG frame header of the mp3 stream. */
+ lseek(fd, -info->frame_size, SEEK_CUR);
+ result = get_next_header_info(fd, &bytecount, info, false);
+ if(result)
+ return result;
}

return bytecount;
@@ -574,7 +625,7 @@
num_frames = 0;
cnt = 0;

- while((header = buf_find_next_frame(fd, &bytes, -1, header_template))) {
+ while((header = buf_find_next_frame(fd, &bytes, header_template))) {
mp3headerinfo(&info, header);

if(!header_template)
@@ -649,7 +700,7 @@
/* Advance from the last seek point to this one */
for(j = 0;j < pos - last_pos;j++)
{
- header = buf_find_next_frame(fd, &bytes, -1, header_template);
+ header = buf_find_next_frame(fd, &bytes, header_template);
filepos += bytes;
mp3headerinfo(&info, header);
buf_seek(fd, info.frame_size-4);