Index: apps/mp3data.h =================================================================== --- apps/mp3data.h (revision 29537) +++ apps/mp3data.h (working copy) @@ -57,10 +57,8 @@ #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); +unsigned long find_next_frame(int fd, long *offset, long max_offset); +unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset); int get_mp3file_info(int fd, struct mp3info *info); int count_mp3_frames(int fd, int startpos, int filesize, void (*progressfunc)(int)); Index: apps/mpeg.c =================================================================== --- apps/mpeg.c (revision 29537) +++ apps/mpeg.c (working copy) @@ -217,9 +217,8 @@ static unsigned long last_rec_bytes; static unsigned long frame_count_start; static unsigned long frame_count_end; -static unsigned long saved_header = 0; -/* Shadow MAS registers */ +/* Shadow MAS registers */ unsigned long shadow_encoder_control = 0; #endif /* CONFIG_CODEC == MAS3587F */ @@ -476,20 +475,6 @@ return pos; } -unsigned long mpeg_get_last_header(void) -{ -#ifdef SIMULATOR - return 0; -#else /* !SIMULATOR */ - unsigned long tmp[2]; - - /* Read the frame data from the MAS and reconstruct it with the - frame sync and all */ - mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_STATUS_1, tmp, 2); - return 0xffe00000 | ((tmp[0] & 0x7c00) << 6) | (tmp[1] & 0xffff); -#endif /* !SIMULATOR */ -} - #ifndef SIMULATOR /* Send callback events to notify about removing old tracks. */ static void generate_unbuffer_events(void) @@ -1774,11 +1759,8 @@ DEBUGF("Start looking at address %x (%x)\n", audiobuf+startpos, startpos); - - saved_header = mpeg_get_last_header(); - mem_find_next_frame(startpos, &offset, 1800, - saved_header); + mem_find_next_frame(startpos, &offset, 1800); audiobuf_read = startpos + offset; if(audiobuf_read >= audiobuflen) @@ -1803,12 +1785,6 @@ DEBUGF("Recording...\n"); start_recording(); - /* Wait until at least one frame is encoded and get the - frame header, for later use by the Xing header - generation */ - sleep(HZ/5); - saved_header = mpeg_get_last_header(); - /* delayed until buffer is saved, don't open yet */ strcpy(delayed_filename, recording_filename); mpeg_file = -1; @@ -1893,8 +1869,7 @@ if (save_endpos < 0) save_endpos += audiobuflen; - rc = mem_find_next_frame(save_endpos, &offset, 1800, - saved_header); + rc = mem_find_next_frame(save_endpos, &offset, 1800); if (!rc) /* No header found, save whole buffer */ offset = 1800; Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 29537) +++ apps/plugin.h (working copy) @@ -145,7 +145,7 @@ #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 201 +#define PLUGIN_API_VERSION 202 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any @@ -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); #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,69 @@ 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)) + int(*getfunc)(int fd, unsigned char *c), + bool single_header) { - unsigned long header=0; + unsigned long last_header, 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 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 (single_header) { + /* We only search for a single valid header. We are finished. */ + 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. */ + last_header = 0; + read_uint32be(fd, (uint32_t*)&last_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(last_header, header)) + break; + } + } + + } while (true); *offset = pos - 4; @@ -248,9 +279,9 @@ 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) { - return __find_next_frame(fd, offset, max_offset, last_header, fileread); + return __find_next_frame(fd, offset, max_offset, fileread, true); } #ifndef __PCTOOL__ @@ -312,10 +343,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, buf_getbyte, true); } static int audiobuflen; @@ -337,15 +367,14 @@ 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) { 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, mem_getbyte, true); } #endif @@ -446,17 +475,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, 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 +510,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 +546,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 +560,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 +569,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 +613,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 +688,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);