summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-11-02 11:24:38 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-11-02 11:24:38 +0000
commit24a8b6ad09dc3ba357543c36ca17880d09461022 (patch)
tree573345cbb4f23bbc799ae9e7219835cc93bbff34
parent1694847103c777bb93db7e342911f78d0ab05a4c (diff)
downloadrockbox-24a8b6ad09dc3ba357543c36ca17880d09461022.zip
rockbox-24a8b6ad09dc3ba357543c36ca17880d09461022.tar.gz
rockbox-24a8b6ad09dc3ba357543c36ca17880d09461022.tar.bz2
rockbox-24a8b6ad09dc3ba357543c36ca17880d09461022.tar.xz
Frame-accurate file splits when recording. Now the PLAY button closes the current file and opens a new one.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3998 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/recorder/recording.c10
-rw-r--r--firmware/export/mp3data.h2
-rw-r--r--firmware/export/mpeg.h1
-rw-r--r--firmware/mp3data.c75
-rw-r--r--firmware/mpeg.c191
5 files changed, 209 insertions, 70 deletions
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index 868f45f..0f095be 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -221,6 +221,11 @@ bool recording_screen(void)
update_countdown = 1; /* Update immediately */
last_seconds = 0;
}
+ else
+ {
+ mpeg_new_file(create_filename());
+ update_countdown = 1; /* Update immediately */
+ }
break;
case BUTTON_UP:
@@ -389,10 +394,7 @@ bool recording_screen(void)
if (mpeg_status() && (seconds >= dseconds))
{
- /* stop and restart recording */
- mpeg_stop();
- have_recorded = true;
- mpeg_record(create_filename());
+ mpeg_new_file(create_filename());
update_countdown = 1;
last_seconds = 0;
}
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index 6b3ff83..833a4c9 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -56,6 +56,8 @@ struct mp3info {
unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header);
+unsigned long mem_find_next_frame(int startpos, int *offset, int 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,
void (*progressfunc)(int));
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index bdf65dd..63eecf5 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -86,6 +86,7 @@ void mpeg_set_pitch(int percent);
void mpeg_init_recording(void);
void mpeg_init_playback(void);
void mpeg_record(char *filename);
+void mpeg_new_file(char *filename);
void mpeg_set_recording_options(int frequency, int quality,
int source, int channel_mode,
bool editable);
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 670934d..83d916f 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -212,7 +212,7 @@ static bool mp3headerinfo(struct mp3info *info, unsigned long header)
return true;
}
-unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header)
+static unsigned long __find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header, int(*getfunc)(int fd, unsigned char *c))
{
unsigned long header=0;
unsigned char tmp;
@@ -227,7 +227,7 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
/* Fill up header with first 24 bits */
for(i = 0; i < 3; i++) {
header <<= 8;
- if(!read(fd, &tmp, 1))
+ if(!getfunc(fd, &tmp))
return 0;
header |= tmp;
pos++;
@@ -235,7 +235,7 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
do {
header <<= 8;
- if(!read(fd, &tmp, 1))
+ if(!getfunc(fd, &tmp))
return 0;
header |= tmp;
pos++;
@@ -254,6 +254,16 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
return header;
}
+static int fileread(int fd, unsigned char *c)
+{
+ return read(fd, c, 1);
+}
+
+unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header)
+{
+ return __find_next_frame(fd, offset, max_offset, last_header, fileread);
+}
+
static int fnf_read_index;
static int fnf_buf_len;
@@ -315,44 +325,37 @@ static void buf_init(void)
unsigned long buf_find_next_frame(int fd, int *offset, int max_offset,
unsigned long last_header)
{
- unsigned long header=0;
- unsigned char tmp;
- int i;
-
- int pos = 0;
+ return __find_next_frame(fd, offset, max_offset, last_header, buf_getbyte);
+}
- /* 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;
+static int mp3buflen;
+static int mem_pos;
+static int mem_cnt;
+static int mem_maxlen;
- /* Fill up header with first 24 bits */
- for(i = 0; i < 3; i++) {
- header <<= 8;
- if(!buf_getbyte(fd, &tmp))
- return 0;
- header |= tmp;
- pos++;
- }
+static int mem_getbyte(int dummy, unsigned char *c)
+{
+ dummy = dummy;
+
+ *c = mp3buf[mem_pos++];
+ if(mem_pos >= mp3buflen)
+ mem_pos = 0;
- do {
- header <<= 8;
- if(!buf_getbyte(fd, &tmp))
- return 0;
- header |= tmp;
- pos++;
- if(max_offset > 0 && pos > max_offset)
- return 0;
- } while(!is_mp3frameheader(header) ||
- (last_header?((header & 0xffff0c00) != last_header):false));
+ if(mem_cnt++ >= mem_maxlen)
+ return 0;
+ else
+ return 1;
+}
- *offset = pos - 4;
+unsigned long mem_find_next_frame(int startpos, int *offset, int max_offset,
+ unsigned long last_header)
+{
+ mp3buflen = mp3end - mp3buf;
+ mem_pos = startpos;
+ mem_cnt = 0;
+ mem_maxlen = max_offset;
-#ifdef DEBUG
- if(*offset)
- DEBUGF("Warning: skipping %d bytes of garbage\n", *offset);
-#endif
-
- return header;
+ return __find_next_frame(0, offset, max_offset, last_header, mem_getbyte);
}
int get_mp3file_info(int fd, struct mp3info *info)
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 9d6718d..5a6fae4 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -52,6 +52,7 @@ static void stop_recording(void);
static int get_unplayed_space(void);
static int get_playable_space(void);
static int get_unswapped_space(void);
+static int get_unsaved_space(void);
#endif
#define MPEG_PLAY 1
@@ -65,6 +66,7 @@ static int get_unswapped_space(void);
#define MPEG_RECORD 9
#define MPEG_INIT_RECORDING 10
#define MPEG_INIT_PLAYBACK 11
+#define MPEG_NEW_FILE 12
#define MPEG_NEED_DATA 100
#define MPEG_TRACK_CHANGE 101
#define MPEG_SAVE_DATA 102
@@ -494,6 +496,7 @@ static bool saving; /* We are saving the buffer to disk */
static char recording_filename[MAX_PATH];
static int rec_frequency_index; /* For create_xing_header() calls */
static int rec_version_index; /* For create_xing_header() calls */
+static bool disable_xing_header; /* When splitting files */
#endif
static int mpeg_file;
@@ -687,6 +690,16 @@ static int get_unswapped_space(void)
return space;
}
+#ifdef HAVE_MAS3587F
+static int get_unsaved_space(void)
+{
+ int space = mp3buf_write - mp3buf_read;
+ if (space < 0)
+ space += mp3buflen;
+ return space;
+}
+#endif
+
static void init_dma(void)
{
SAR3 = (unsigned int) mp3buf + mp3buf_read;
@@ -1270,6 +1283,9 @@ static void mpeg_thread(void)
int writelen;
int framelen;
unsigned long saved_header;
+ int startpos;
+ int rc;
+ int offset;
#endif
is_playing = false;
@@ -1893,29 +1909,34 @@ static void mpeg_thread(void)
if(mpeg_file >= 0)
close(mpeg_file);
- /* Create the Xing header */
- mpeg_file = open(recording_filename, O_RDWR);
- if(mpeg_file < 0)
- panicf("rec upd: %d (%s)", mpeg_file, recording_filename);
-
- /* If the number of recorded frames have reached 0x7ffff,
- we can no longer trust it */
- if(num_recorded_frames == 0x7ffff)
- num_recorded_frames = 0;
-
- /* Read the first MP3 frame from the recorded stream */
- lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET);
- read(mpeg_file, &saved_header, 4);
-
- framelen = create_xing_header(mpeg_file, 0, num_rec_bytes,
- mp3buf, num_recorded_frames,
- saved_header, NULL, false);
-
- lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen,
- SEEK_SET);
- write(mpeg_file, mp3buf, framelen);
- close(mpeg_file);
-
+ if(!disable_xing_header)
+ {
+ /* Create the Xing header */
+ mpeg_file = open(recording_filename, O_RDWR);
+ if(mpeg_file < 0)
+ panicf("rec upd: %d (%s)", mpeg_file,
+ recording_filename);
+
+ /* If the number of recorded frames have
+ reached 0x7ffff, we can no longer trust it */
+ if(num_recorded_frames == 0x7ffff)
+ num_recorded_frames = 0;
+
+ /* Read the first MP3 frame from the recorded stream */
+ lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET);
+ read(mpeg_file, &saved_header, 4);
+
+ framelen = create_xing_header(mpeg_file, 0,
+ num_rec_bytes, mp3buf,
+ num_recorded_frames,
+ saved_header, NULL,
+ false);
+
+ lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen,
+ SEEK_SET);
+ write(mpeg_file, mp3buf, framelen);
+ close(mpeg_file);
+ }
mpeg_file = -1;
#ifdef DEBUG1
@@ -1933,9 +1954,105 @@ static void mpeg_thread(void)
#endif
mpeg_stop_done = true;
break;
+
+ case MPEG_NEW_FILE:
+ /* Make sure we have at least one complete frame
+ in the buffer */
+ amount_to_save = get_unsaved_space();
+ while(amount_to_save < 1800)
+ {
+ sleep(HZ/10);
+ amount_to_save = get_unsaved_space();
+ }
+
+ /* Now find a frame boundary to split at */
+ startpos = mp3buf_write - 1800;
+ if(startpos < 0)
+ startpos += mp3buflen;
+
+ {
+ unsigned long tmp[2];
+ /* Find out how the mp3 header should look like */
+ mas_readmem(MAS_BANK_D0, 0xfd1, tmp, 2);
+ saved_header = 0xffe00000 |
+ ((tmp[0] & 0x7c00) << 6) |
+ (tmp[1] & 0xffff);
+ DEBUGF("Header: %08x\n", saved_header);
+ }
+
+ mem_find_next_frame(startpos, &offset, 1800, saved_header);
+
+ /* offset will now contain the number of bytes to
+ add to startpos to find the frame boundary */
+ startpos += offset;
+ if(startpos >= mp3buflen)
+ startpos -= mp3buflen;
+
+ amount_to_save = startpos - mp3buf_read;
+ if(amount_to_save < 0)
+ amount_to_save += mp3buflen;
+
+ /* First save up to the end of the buffer */
+ writelen = MIN(amount_to_save,
+ mp3buflen - mp3buf_read);
+
+ rc = write(mpeg_file, mp3buf + mp3buf_read, writelen);
+ if(rc < 0)
+ {
+ if(errno == ENOSPC)
+ {
+ mpeg_errno = MPEGERR_DISK_FULL;
+ demand_irq_enable(false);
+ stop_recording();
+ queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
+ break;
+ }
+ else
+ {
+ panicf("rec wrt: %d", rc);
+ }
+ }
+
+ /* Then save the rest */
+ writelen = amount_to_save - writelen;
+ if(writelen)
+ {
+ rc = write(mpeg_file, mp3buf, writelen);
+ if(rc < 0)
+ {
+ if(errno == ENOSPC)
+ {
+ mpeg_errno = MPEGERR_DISK_FULL;
+ demand_irq_enable(false);
+ stop_recording();
+ queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
+ break;
+ }
+ else
+ {
+ panicf("spt wrt: %d", rc);
+ }
+ }
+ }
+
+ /* Advance the buffer pointers */
+ mp3buf_read += amount_to_save;
+ if(mp3buf_read >= mp3buflen)
+ mp3buf_read -= mp3buflen;
+
+ /* Close the current file */
+ rc = close(mpeg_file);
+ if(rc < 0)
+ panicf("spt cls: %d", rc);
+
+ /* Open the new file */
+ mpeg_file = open(recording_filename, O_WRONLY|O_CREAT);
+ if(mpeg_file < 0)
+ panicf("sptfile: %d", mpeg_file);
+ break;
case MPEG_SAVE_DATA:
- amount_to_save = mp3buf_write - mp3buf_read;
+ amount_to_save = get_unsaved_space();
/* If the result is negative, the write index has
wrapped */
@@ -1954,8 +2071,6 @@ static void mpeg_thread(void)
amount_to_save < MPEG_RECORDING_LOW_WATER ||
stop_pending)
{
- int rc;
-
/* Only save up to the end of the buffer */
writelen = MIN(amount_to_save,
mp3buflen - mp3buf_read);
@@ -1981,14 +2096,14 @@ static void mpeg_thread(void)
}
}
- rc = fsync(mpeg_file);
- if(rc < 0)
- panicf("rec fls: %d", rc);
-
mp3buf_read += amount_to_save;
if(mp3buf_read >= mp3buflen)
mp3buf_read = 0;
+ rc = fsync(mpeg_file);
+ if(rc < 0)
+ panicf("rec fls: %d", rc);
+
queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
}
else
@@ -2257,6 +2372,7 @@ void mpeg_record(char *filename)
recording_filename[MAX_PATH - 1] = 0;
num_rec_bytes = 0;
+ disable_xing_header = false;
queue_post(&mpeg_queue, MPEG_RECORD, NULL);
}
@@ -2311,6 +2427,21 @@ static void stop_recording(void)
drain_dma_buffer();
}
+void mpeg_new_file(char *filename)
+{
+ mpeg_errno = 0;
+
+ strncpy(recording_filename, filename, MAX_PATH - 1);
+ recording_filename[MAX_PATH - 1] = 0;
+
+ disable_xing_header = true;
+
+ /* Store the current time */
+ record_start_time = current_tick;
+
+ queue_post(&mpeg_queue, MPEG_NEW_FILE, NULL);
+}
+
unsigned long mpeg_recorded_time(void)
{
if(is_recording)