summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-03-10 18:05:01 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-03-10 18:05:01 +0000
commit6475aa0c85fcca7a37a7aa4316173270fcb6d038 (patch)
treee6dbe18217113212a9b8e713d3325c5803b3f4a6 /firmware
parent673937d65402b058b5b5bfa5a1bf990c2d218dba (diff)
downloadrockbox-6475aa0c85fcca7a37a7aa4316173270fcb6d038.tar.gz
rockbox-6475aa0c85fcca7a37a7aa4316173270fcb6d038.zip
Experimental Xing header generation added. Use with caution
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3418 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/id3.h2
-rw-r--r--firmware/export/mp3data.h4
-rw-r--r--firmware/mp3data.c118
-rw-r--r--firmware/mpeg.c33
4 files changed, 100 insertions, 57 deletions
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 30be4bf883..a9ab9ef36f 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -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 */
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index a1018ebaa2..54a6899a78 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -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
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 8d925041ce..21f01ea19e 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -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;
- }
+ 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;
+ }
- 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);
+ if(filesize)
+ {
+ int2bytes(&buf[index], filesize - startpos);
+ index += 4;
+ }
- /* Fill in the TOC entry */
- buf[36+16+i] = tocentry;
-
- last_pos = pos;
+ 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+152, cooltext, sizeof(cooltext));
+ memcpy(buf + index + 100, cooltext, sizeof(cooltext));
#ifdef DEBUG
for(i = 0;i < 417;i++)
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index c3288dfdac..13c4b01b8a 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -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
{