forked from len0rd/rockbox
Experimental Xing header generation added. Use with caution
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3418 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
673937d654
commit
6475aa0c85
5 changed files with 148 additions and 59 deletions
46
apps/tree.c
46
apps/tree.c
|
|
@ -653,6 +653,40 @@ void set_current_file(char *path)
|
|||
}
|
||||
|
||||
#ifdef HAVE_LCD_BITMAP
|
||||
extern int d_1;
|
||||
extern int d_2;
|
||||
|
||||
void xingupdate(int percent)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
snprintf(buf, 32, "%d%%", percent);
|
||||
lcd_puts(0, 3, buf);
|
||||
snprintf(buf, 32, "%x", d_1);
|
||||
lcd_puts(0, 4, buf);
|
||||
snprintf(buf, 32, "%x", d_2);
|
||||
lcd_puts(0, 5, buf);
|
||||
lcd_update();
|
||||
}
|
||||
|
||||
void do_xing(char *filename)
|
||||
{
|
||||
char buf2[32];
|
||||
unsigned long dbg_tick;
|
||||
|
||||
lcd_clear_display();
|
||||
lcd_puts(0, 0, filename);
|
||||
lcd_update();
|
||||
dbg_tick = current_tick;
|
||||
mpeg_create_xing_header(filename, xingupdate);
|
||||
dbg_tick = current_tick - dbg_tick;
|
||||
snprintf(buf2, 32, "%d ticks", dbg_tick);
|
||||
lcd_puts(0, 1, buf2);
|
||||
snprintf(buf2, 32, "%d seconds", dbg_tick/HZ);
|
||||
lcd_puts(0, 2, buf2);
|
||||
lcd_update();
|
||||
}
|
||||
|
||||
static int onplay_screen(char* dir, char* file)
|
||||
{
|
||||
bool exit = false;
|
||||
|
|
@ -697,6 +731,12 @@ static int onplay_screen(char* dir, char* file)
|
|||
lcd_putsxy(0, LCD_HEIGHT/2 - h/2, ptr);
|
||||
lcd_bitmap(bitmap_icons_7x8[Icon_FastBackward],
|
||||
LCD_WIDTH/2 - 16, LCD_HEIGHT/2 - 4, 7, 8, true);
|
||||
|
||||
ptr = "VBR Fix";
|
||||
lcd_getstringsize(ptr,&w,&h);
|
||||
lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h, ptr);
|
||||
lcd_bitmap(bitmap_icons_7x8[Icon_DownArrow],
|
||||
LCD_WIDTH/2 - 3, LCD_HEIGHT - h*3, 7, 8, true);
|
||||
}
|
||||
lcd_update();
|
||||
|
||||
|
|
@ -760,6 +800,12 @@ static int onplay_screen(char* dir, char* file)
|
|||
}
|
||||
break;
|
||||
|
||||
case BUTTON_DOWN:
|
||||
case BUTTON_ON | BUTTON_DOWN:
|
||||
do_xing(buf);
|
||||
// exit = true;
|
||||
break;
|
||||
|
||||
case BUTTON_PLAY:
|
||||
case BUTTON_ON | BUTTON_PLAY: {
|
||||
if (playing)
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ struct mp3entry {
|
|||
unsigned int first_frame_offset; /* Byte offset to first real MP3 frame.
|
||||
Used for skipping leading garbage to
|
||||
avoid gaps between tracks. */
|
||||
unsigned int xing_header_pos;
|
||||
unsigned int vbr_header_pos;
|
||||
unsigned int filesize; /* in bytes */
|
||||
unsigned int length; /* song length */
|
||||
unsigned int elapsed; /* ms played */
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ struct mp3info {
|
|||
int frame_count; /* Number of frames in the file (if VBR) */
|
||||
int byte_count; /* File size in bytes */
|
||||
int file_time; /* Length of the whole file in milliseconds */
|
||||
int xing_header_pos;
|
||||
int vbr_header_pos;
|
||||
};
|
||||
|
||||
/* Xing header information */
|
||||
|
|
@ -61,6 +61,6 @@ int count_mp3_frames(int fd, int startpos, int filesize,
|
|||
void (*progressfunc)(int));
|
||||
int create_xing_header(int fd, int startpos, int filesize,
|
||||
unsigned char *buf, int num_frames,
|
||||
void (*progressfunc)(int));
|
||||
void (*progressfunc)(int), bool generate_toc);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -263,9 +263,7 @@ extern unsigned char mp3end[];
|
|||
static int fnf_read_index;
|
||||
static int fnf_buf_len;
|
||||
|
||||
static int fd;
|
||||
|
||||
static int buf_getbyte(unsigned char *c)
|
||||
static int buf_getbyte(int fd, unsigned char *c)
|
||||
{
|
||||
if(fnf_read_index < fnf_buf_len)
|
||||
{
|
||||
|
|
@ -291,7 +289,7 @@ static int buf_getbyte(unsigned char *c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int buf_seek(int len)
|
||||
static int buf_seek(int fd, int len)
|
||||
{
|
||||
fnf_read_index += len;
|
||||
if(fnf_read_index > fnf_buf_len)
|
||||
|
|
@ -320,7 +318,7 @@ static void buf_init(void)
|
|||
fnf_read_index = 0;
|
||||
}
|
||||
|
||||
unsigned long buf_find_next_frame(int *offset, int max_offset,
|
||||
unsigned long buf_find_next_frame(int fd, int *offset, int max_offset,
|
||||
unsigned long last_header)
|
||||
{
|
||||
unsigned long header=0;
|
||||
|
|
@ -336,7 +334,7 @@ unsigned long buf_find_next_frame(int *offset, int max_offset,
|
|||
/* Fill up header with first 24 bits */
|
||||
for(i = 0; i < 3; i++) {
|
||||
header <<= 8;
|
||||
if(!buf_getbyte(&tmp))
|
||||
if(!buf_getbyte(fd, &tmp))
|
||||
return 0;
|
||||
header |= tmp;
|
||||
pos++;
|
||||
|
|
@ -344,7 +342,7 @@ unsigned long buf_find_next_frame(int *offset, int max_offset,
|
|||
|
||||
do {
|
||||
header <<= 8;
|
||||
if(!buf_getbyte(&tmp))
|
||||
if(!buf_getbyte(fd, &tmp))
|
||||
return 0;
|
||||
header |= tmp;
|
||||
pos++;
|
||||
|
|
@ -413,7 +411,7 @@ int get_mp3file_info(int fd, struct mp3info *info)
|
|||
DEBUGF("Xing header\n");
|
||||
|
||||
/* Remember where in the file the Xing header is */
|
||||
info->xing_header_pos = lseek(fd, 0, SEEK_CUR) - info->frame_size;
|
||||
info->vbr_header_pos = lseek(fd, 0, SEEK_CUR) - info->frame_size;
|
||||
|
||||
/* We want to skip the Xing frame when playing the stream */
|
||||
bytecount += info->frame_size;
|
||||
|
|
@ -423,7 +421,7 @@ int get_mp3file_info(int fd, struct mp3info *info)
|
|||
header = find_next_frame(fd, &tmp, 0x20000, 0);
|
||||
if(header == 0)
|
||||
return -4;
|
||||
|
||||
|
||||
if(!mp3headerinfo(info, header))
|
||||
return -5;
|
||||
|
||||
|
|
@ -443,10 +441,14 @@ int get_mp3file_info(int fd, struct mp3info *info)
|
|||
{
|
||||
info->byte_count = BYTES2INT(vbrheader[i], vbrheader[i+1],
|
||||
vbrheader[i+2], vbrheader[i+3]);
|
||||
info->bitrate = info->byte_count * 8 / info->file_time;
|
||||
i += 4;
|
||||
}
|
||||
|
||||
if(info->file_time && info->byte_count)
|
||||
info->bitrate = info->byte_count * 8 / info->file_time;
|
||||
else
|
||||
info->bitrate = 0;
|
||||
|
||||
if(vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */
|
||||
{
|
||||
memcpy( info->toc, vbrheader+i, 100 );
|
||||
|
|
@ -554,6 +556,8 @@ int count_mp3_frames(int fd, int startpos, int filesize,
|
|||
int progress_chunk = filesize / 50; /* Max is 50%, in 1% increments */
|
||||
int progress_cnt = 0;
|
||||
|
||||
/* Nasty stuff to avoid passing the file handle around */
|
||||
|
||||
if(lseek(fd, startpos, SEEK_SET) < 0)
|
||||
return -1;
|
||||
|
||||
|
|
@ -563,9 +567,9 @@ int count_mp3_frames(int fd, int startpos, int filesize,
|
|||
num_frames = 0;
|
||||
cnt = 0;
|
||||
|
||||
while((header = buf_find_next_frame(&bytes, -1, header))) {
|
||||
while((header = buf_find_next_frame(fd, &bytes, -1, header))) {
|
||||
mp3headerinfo(&info, header);
|
||||
buf_seek(info.frame_size-4);
|
||||
buf_seek(fd, info.frame_size-4);
|
||||
num_frames++;
|
||||
if(progressfunc)
|
||||
{
|
||||
|
|
@ -585,7 +589,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
|
|||
|
||||
int create_xing_header(int fd, int startpos, int filesize,
|
||||
unsigned char *buf, int num_frames,
|
||||
void (*progressfunc)(int))
|
||||
void (*progressfunc)(int), bool generate_toc)
|
||||
{
|
||||
unsigned long header = 0;
|
||||
struct mp3info info;
|
||||
|
|
@ -595,6 +599,7 @@ int create_xing_header(int fd, int startpos, int filesize,
|
|||
int filepos;
|
||||
int tocentry;
|
||||
int x;
|
||||
int index;
|
||||
|
||||
DEBUGF("create_xing_header()\n");
|
||||
|
||||
|
|
@ -609,46 +614,61 @@ int create_xing_header(int fd, int startpos, int filesize,
|
|||
buf[36+1] = 'i';
|
||||
buf[36+2] = 'n';
|
||||
buf[36+3] = 'g';
|
||||
int2bytes(&buf[36+4], (VBR_FRAMES_FLAG | VBR_BYTES_FLAG | VBR_TOC_FLAG));
|
||||
int2bytes(&buf[36+8], num_frames);
|
||||
int2bytes(&buf[36+12], filesize - startpos);
|
||||
|
||||
/* Generate filepos table */
|
||||
last_pos = 0;
|
||||
filepos = 0;
|
||||
header = 0;
|
||||
x = 0;
|
||||
for(i = 0;i < 100;i++) {
|
||||
/* Calculate the absolute frame number for this seek point */
|
||||
pos = i * num_frames / 100;
|
||||
|
||||
/* Advance from the last seek point to this one */
|
||||
for(j = 0;j < pos - last_pos;j++)
|
||||
{
|
||||
DEBUGF("fpos: %x frame no: %x ", filepos, x++);
|
||||
header = buf_find_next_frame(&bytes, -1, header);
|
||||
mp3headerinfo(&info, header);
|
||||
buf_seek(info.frame_size-4);
|
||||
filepos += info.frame_size;
|
||||
}
|
||||
|
||||
if(progressfunc)
|
||||
{
|
||||
progressfunc(50 + i/2);
|
||||
}
|
||||
|
||||
tocentry = filepos * 256 / filesize;
|
||||
|
||||
DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n",
|
||||
i, pos, pos-last_pos, filepos, tocentry);
|
||||
|
||||
/* Fill in the TOC entry */
|
||||
buf[36+16+i] = tocentry;
|
||||
|
||||
last_pos = pos;
|
||||
int2bytes(&buf[36+4], (num_frames?VBR_FRAMES_FLAG:0 |
|
||||
filesize?VBR_BYTES_FLAG:0 |
|
||||
generate_toc?VBR_TOC_FLAG:0));
|
||||
index = 36+8;
|
||||
if(num_frames)
|
||||
{
|
||||
int2bytes(&buf[index], num_frames);
|
||||
index += 4;
|
||||
}
|
||||
|
||||
memcpy(buf+152, cooltext, sizeof(cooltext));
|
||||
if(filesize)
|
||||
{
|
||||
int2bytes(&buf[index], filesize - startpos);
|
||||
index += 4;
|
||||
}
|
||||
|
||||
if(generate_toc)
|
||||
{
|
||||
/* Generate filepos table */
|
||||
last_pos = 0;
|
||||
filepos = 0;
|
||||
header = 0;
|
||||
x = 0;
|
||||
for(i = 0;i < 100;i++) {
|
||||
/* Calculate the absolute frame number for this seek point */
|
||||
pos = i * num_frames / 100;
|
||||
|
||||
/* Advance from the last seek point to this one */
|
||||
for(j = 0;j < pos - last_pos;j++)
|
||||
{
|
||||
DEBUGF("fpos: %x frame no: %x ", filepos, x++);
|
||||
header = buf_find_next_frame(fd, &bytes, -1, header);
|
||||
mp3headerinfo(&info, header);
|
||||
buf_seek(fd, info.frame_size-4);
|
||||
filepos += info.frame_size;
|
||||
}
|
||||
|
||||
if(progressfunc)
|
||||
{
|
||||
progressfunc(50 + i/2);
|
||||
}
|
||||
|
||||
tocentry = filepos * 256 / filesize;
|
||||
|
||||
DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n",
|
||||
i, pos, pos-last_pos, filepos, tocentry);
|
||||
|
||||
/* Fill in the TOC entry */
|
||||
buf[index + i] = tocentry;
|
||||
|
||||
last_pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(buf + index + 100, cooltext, sizeof(cooltext));
|
||||
|
||||
#ifdef DEBUG
|
||||
for(i = 0;i < 417;i++)
|
||||
|
|
|
|||
|
|
@ -353,6 +353,9 @@ static void set_elapsed(struct mp3entry* id3)
|
|||
}
|
||||
|
||||
static bool paused; /* playback is paused */
|
||||
|
||||
static unsigned char xingbuf[417];
|
||||
|
||||
#ifdef SIMULATOR
|
||||
static bool is_playing = false;
|
||||
static bool playing = false;
|
||||
|
|
@ -500,9 +503,16 @@ static bool mpeg_stop_done;
|
|||
|
||||
static void recalculate_watermark(int bitrate)
|
||||
{
|
||||
int bytes_per_sec = bitrate * 1000 / 8;
|
||||
int bytes_per_sec;
|
||||
int time = ata_spinup_time;
|
||||
|
||||
/* A bitrate of 0 probably means empty VBR header. We play safe
|
||||
and set a high threshold */
|
||||
if(bitrate == 0)
|
||||
bitrate = 320000;
|
||||
|
||||
bytes_per_sec = bitrate * 1000 / 8;
|
||||
|
||||
if(time)
|
||||
{
|
||||
/* No drive spins up faster than 3.5s */
|
||||
|
|
@ -1857,6 +1867,18 @@ static void mpeg_thread(void)
|
|||
|
||||
if(mpeg_file >= 0)
|
||||
close(mpeg_file);
|
||||
|
||||
mpeg_file = open(recording_filename, O_RDWR);
|
||||
if(mpeg_file < 0)
|
||||
panicf("rec upd: %d", mpeg_file);
|
||||
|
||||
create_xing_header(mpeg_file, 0, mpeg_num_recorded_bytes(),
|
||||
xingbuf, 0, NULL, false);
|
||||
|
||||
lseek(mpeg_file, 4096, SEEK_SET);
|
||||
write(mpeg_file, xingbuf, 417);
|
||||
close(mpeg_file);
|
||||
|
||||
mpeg_file = -1;
|
||||
|
||||
#ifdef DEBUG1
|
||||
|
|
@ -2982,7 +3004,6 @@ int d_2;
|
|||
int mpeg_create_xing_header(char *filename, void (*progressfunc)(int))
|
||||
{
|
||||
struct mp3entry entry;
|
||||
char xingbuf[417];
|
||||
int fd;
|
||||
int rc;
|
||||
int flen;
|
||||
|
|
@ -3013,15 +3034,17 @@ int mpeg_create_xing_header(char *filename, void (*progressfunc)(int))
|
|||
progressfunc);
|
||||
|
||||
create_xing_header(fd, entry.first_frame_offset,
|
||||
flen, xingbuf, num_frames, progressfunc);
|
||||
flen, xingbuf, num_frames, progressfunc, true);
|
||||
|
||||
/* Try to fit the Xing header first in the stream. Replace the existing
|
||||
Xing header if there is one, else see if there is room between the
|
||||
ID3 tag and the first MP3 frame. */
|
||||
if(entry.xing_header_pos)
|
||||
if(entry.vbr_header_pos)
|
||||
{
|
||||
/* Reuse existing Xing header */
|
||||
fpos = entry.xing_header_pos;
|
||||
fpos = entry.vbr_header_pos;
|
||||
|
||||
DEBUGF("Reusing Xing header at %d\n", fpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue