summaryrefslogtreecommitdiff
path: root/firmware/mpeg.c
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-03-10 14:55:31 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-03-10 14:55:31 +0000
commita039091187f40d018b6353b8c13de7a01d3a6fe0 (patch)
tree08f7eb86e86e2c61f4d36f9c91731cb93252ba84 /firmware/mpeg.c
parent22cbe938feb48895d7488449835d3ee577399057 (diff)
New ID3 and MP3 stream parser, plus not-yet-ready Xing header generation code
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3410 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/mpeg.c')
-rw-r--r--firmware/mpeg.c320
1 files changed, 198 insertions, 122 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 9470e7d84b..92f11e1b84 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -26,6 +26,7 @@
#include "string.h"
#include <kernel.h>
#include "thread.h"
+#include "mp3data.h"
#ifndef SIMULATOR
#include "i2c.h"
#include "mas.h"
@@ -302,7 +303,7 @@ static void remove_all_tags(void)
static void set_elapsed(struct mp3entry* id3)
{
if ( id3->vbr ) {
- if ( id3->vbrflags & VBR_TOC_FLAG ) {
+ if ( id3->has_toc ) {
/* calculate elapsed time using TOC */
int i;
unsigned int remainder, plen, relpos, nextpos;
@@ -1482,7 +1483,7 @@ static void mpeg_thread(void)
if (id3->vbr)
{
- if (id3->vbrflags & VBR_TOC_FLAG)
+ if (id3->has_toc)
{
/* Use the TOC to find the new position */
unsigned int percent, remainder;
@@ -1528,10 +1529,10 @@ static void mpeg_thread(void)
transition properly to the next song */
newpos = id3->filesize - id3->id3v1len - 1;
}
- else if (newpos < (int)id3->id3v2len)
+ else if (newpos < (int)id3->first_frame_offset)
{
- /* skip past id3v2 tag */
- newpos = id3->id3v2len;
+ /* skip past id3v2 tag and other leading garbage */
+ newpos = id3->first_frame_offset;
}
if (mpeg_file >= 0)
@@ -1720,7 +1721,7 @@ static void mpeg_thread(void)
t2 = current_tick;
DEBUGF("time: %d\n", t2 - t1);
DEBUGF("R: %x\n", len);
-
+
/* Now make sure that we don't feed the MAS with ID3V1
data */
if (len < amount_to_read)
@@ -1734,19 +1735,19 @@ static void mpeg_thread(void)
{
if(tagptr >= mp3buflen)
tagptr -= mp3buflen;
-
+
if(mp3buf[tagptr] != tag[i])
taglen = 0;
-
+
tagptr++;
}
-
+
if(taglen)
{
/* Skip id3v1 tag */
DEBUGF("Skipping ID3v1 tag\n");
len -= taglen;
-
+
/* The very rare case when the entire tag
wasn't read in this read() call must be
taken care of */
@@ -1819,131 +1820,135 @@ static void mpeg_thread(void)
}
else
{
- /* This doesn't look neccessary...
- yield();
- if(!queue_empty(&mpeg_queue))
- {*/
- queue_wait(&mpeg_queue, &ev);
- switch(ev.id)
- {
- case MPEG_RECORD:
- DEBUGF("Recording...\n");
- reset_mp3_buffer();
- start_recording();
- demand_irq_enable(true);
- mpeg_file = creat(recording_filename, O_WRONLY);
-
- if(mpeg_file < 0)
- panicf("recfile: %d", mpeg_file);
-
- close(mpeg_file);
- mpeg_file = -1;
- break;
-
- case MPEG_STOP:
- DEBUGF("MPEG_STOP\n");
- demand_irq_enable(false);
- stop_recording();
-
- /* Save the remaining data in the buffer */
- stop_pending = true;
- queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
- break;
+ queue_wait(&mpeg_queue, &ev);
+ switch(ev.id)
+ {
+ case MPEG_RECORD:
+ DEBUGF("Recording...\n");
+ reset_mp3_buffer();
- case MPEG_STOP_DONE:
- DEBUGF("MPEG_STOP_DONE\n");
+ /* Advance the write pointer 4096+417 bytes to make
+ room for an ID3 tag plus a VBR header */
+ mp3buf_write = 4096+417;
+ memset(mp3buf, 0, 4096+417);
- if(mpeg_file >= 0)
- close(mpeg_file);
- mpeg_file = -1;
+ start_recording();
+ demand_irq_enable(true);
+
+ mpeg_file = creat(recording_filename, O_WRONLY);
+
+ if(mpeg_file < 0)
+ panicf("recfile: %d", mpeg_file);
+
+ close(mpeg_file);
+
+ mpeg_file = -1;
+ break;
+
+ case MPEG_STOP:
+ DEBUGF("MPEG_STOP\n");
+ demand_irq_enable(false);
+ stop_recording();
+
+ /* Save the remaining data in the buffer */
+ stop_pending = true;
+ queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
+ break;
+
+ case MPEG_STOP_DONE:
+ DEBUGF("MPEG_STOP_DONE\n");
+
+ if(mpeg_file >= 0)
+ close(mpeg_file);
+ mpeg_file = -1;
+
#ifdef DEBUG1
+ {
+ int i;
+ for(i = 0;i < 512;i++)
{
- int i;
- for(i = 0;i < 512;i++)
- {
- DEBUGF("%d - %d us (%d bytes)\n",
- timing_info[i*2],
- (timing_info[i*2+1] & 0xffff) *
- 10000 / 13824,
- timing_info[i*2+1] >> 16);
- }
+ DEBUGF("%d - %d us (%d bytes)\n",
+ timing_info[i*2],
+ (timing_info[i*2+1] & 0xffff) *
+ 10000 / 13824,
+ timing_info[i*2+1] >> 16);
}
+ }
#endif
- mpeg_stop_done = true;
- break;
-
- case MPEG_SAVE_DATA:
- amount_to_save = mp3buf_write - mp3buf_read;
-
- /* If the result is negative, the write index has
- wrapped */
- if(amount_to_save < 0)
- {
- amount_to_save += mp3buflen;
- }
-
- DEBUGF("r: %x w: %x\n", mp3buf_read, mp3buf_write);
- DEBUGF("ats: %x\n", amount_to_save);
- /* Save data only if the buffer is getting full,
- or if we should stop recording */
- if(amount_to_save)
+ mpeg_stop_done = true;
+ break;
+
+ case MPEG_SAVE_DATA:
+ amount_to_save = mp3buf_write - mp3buf_read;
+
+ /* If the result is negative, the write index has
+ wrapped */
+ if(amount_to_save < 0)
+ {
+ amount_to_save += mp3buflen;
+ }
+
+ DEBUGF("r: %x w: %x\n", mp3buf_read, mp3buf_write);
+ DEBUGF("ats: %x\n", amount_to_save);
+ /* Save data only if the buffer is getting full,
+ or if we should stop recording */
+ if(amount_to_save)
+ {
+ if(mp3buflen - amount_to_save < MPEG_LOW_WATER ||
+ stop_pending)
{
- if(mp3buflen - amount_to_save < MPEG_LOW_WATER ||
- stop_pending)
- {
- int rc;
-
- /* Only save up to the end of the buffer */
- writelen = MIN(amount_to_save,
- mp3buflen - mp3buf_read);
-
- DEBUGF("wrl: %x\n", writelen);
- mpeg_file = open(recording_filename,
- O_WRONLY| O_APPEND);
- if(mpeg_file < 0)
- panicf("rec open: %d", mpeg_file);
-
- rc = write(mpeg_file, mp3buf + mp3buf_read,
- writelen);
-
- if(rc < 0)
- panicf("rec wrt: %d", rc);
-
- rc = close(mpeg_file);
- if(rc < 0)
- panicf("rec cls: %d", rc);
-
- mpeg_file = -1;
- DEBUGF("rc: %x\n", rc);
-
- mp3buf_read += amount_to_save;
- if(mp3buf_read >= mp3buflen)
- mp3buf_read = 0;
-
- queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
- }
- else
- {
- saving = false;
- }
+ int rc;
+
+ /* Only save up to the end of the buffer */
+ writelen = MIN(amount_to_save,
+ mp3buflen - mp3buf_read);
+
+ DEBUGF("wrl: %x\n", writelen);
+ mpeg_file = open(recording_filename,
+ O_WRONLY| O_APPEND);
+ if(mpeg_file < 0)
+ panicf("rec open: %d", mpeg_file);
+
+ rc = write(mpeg_file, mp3buf + mp3buf_read,
+ writelen);
+
+ if(rc < 0)
+ panicf("rec wrt: %d", rc);
+
+ rc = close(mpeg_file);
+ if(rc < 0)
+ panicf("rec cls: %d", rc);
+
+ mpeg_file = -1;
+ DEBUGF("rc: %x\n", rc);
+
+ mp3buf_read += amount_to_save;
+ if(mp3buf_read >= mp3buflen)
+ mp3buf_read = 0;
+
+ queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
}
else
{
- /* We have saved all data,
- time to stop for real */
- if(stop_pending)
- queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
saving = false;
}
- break;
-
- case MPEG_INIT_PLAYBACK:
- init_playback();
- init_playback_done = true;
- break;
- }
- /*}*/
+ }
+ else
+ {
+ /* We have saved all data,
+ time to stop for real */
+ if(stop_pending)
+ queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
+ saving = false;
+ }
+ break;
+
+ case MPEG_INIT_PLAYBACK:
+ init_playback();
+ init_playback_done = true;
+ break;
+ }
}
#endif
}
@@ -2981,3 +2986,74 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness,
dbg_cnt2us(0);
#endif
}
+
+int d_1;
+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;
+ int num_frames;
+ int fpos;
+
+ if(progressfunc)
+ progressfunc(0);
+
+ rc = mp3info(&entry, filename);
+ if(rc < 0)
+ return rc * 10 - 1;
+
+ fd = open(filename, O_RDWR);
+ if(fd < 0)
+ return fd * 10 - 2;
+
+ flen = lseek(fd, 0, SEEK_END);
+
+ d_1 = entry.first_frame_offset;
+ d_2 = entry.filesize;
+
+ if(progressfunc)
+ progressfunc(0);
+
+ num_frames = count_mp3_frames(fd, entry.first_frame_offset,
+ flen,
+ progressfunc);
+
+ create_xing_header(fd, entry.first_frame_offset,
+ flen, xingbuf, num_frames, progressfunc);
+
+ /* 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)
+ {
+ /* Reuse existing Xing header */
+ fpos = entry.xing_header_pos;
+ }
+ else
+ {
+ /* Any room between ID3 tag and first MP3 frame? */
+ if(entry.first_frame_offset - entry.id3v2len > 417)
+ {
+ fpos = entry.first_frame_offset - 417;
+ }
+ else
+ {
+ close(fd);
+ return -3;
+ }
+ }
+
+ lseek(fd, fpos, SEEK_SET);
+ write(fd, xingbuf, 417);
+ close(fd);
+
+ if(progressfunc)
+ progressfunc(100);
+
+ return 0;
+}