1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Linus Nielsen Feltzing 2003-11-02 11:24:38 +00:00
parent 1694847103
commit 24a8b6ad09
5 changed files with 210 additions and 71 deletions

View file

@ -221,6 +221,11 @@ bool recording_screen(void)
update_countdown = 1; /* Update immediately */ update_countdown = 1; /* Update immediately */
last_seconds = 0; last_seconds = 0;
} }
else
{
mpeg_new_file(create_filename());
update_countdown = 1; /* Update immediately */
}
break; break;
case BUTTON_UP: case BUTTON_UP:
@ -389,10 +394,7 @@ bool recording_screen(void)
if (mpeg_status() && (seconds >= dseconds)) if (mpeg_status() && (seconds >= dseconds))
{ {
/* stop and restart recording */ mpeg_new_file(create_filename());
mpeg_stop();
have_recorded = true;
mpeg_record(create_filename());
update_countdown = 1; update_countdown = 1;
last_seconds = 0; last_seconds = 0;
} }

View file

@ -56,6 +56,8 @@ struct mp3info {
unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header); 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 get_mp3file_info(int fd, struct mp3info *info);
int count_mp3_frames(int fd, int startpos, int filesize, int count_mp3_frames(int fd, int startpos, int filesize,
void (*progressfunc)(int)); void (*progressfunc)(int));

View file

@ -86,6 +86,7 @@ void mpeg_set_pitch(int percent);
void mpeg_init_recording(void); void mpeg_init_recording(void);
void mpeg_init_playback(void); void mpeg_init_playback(void);
void mpeg_record(char *filename); void mpeg_record(char *filename);
void mpeg_new_file(char *filename);
void mpeg_set_recording_options(int frequency, int quality, void mpeg_set_recording_options(int frequency, int quality,
int source, int channel_mode, int source, int channel_mode,
bool editable); bool editable);

View file

@ -212,7 +212,7 @@ static bool mp3headerinfo(struct mp3info *info, unsigned long header)
return true; 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 long header=0;
unsigned char tmp; 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 */ /* Fill up header with first 24 bits */
for(i = 0; i < 3; i++) { for(i = 0; i < 3; i++) {
header <<= 8; header <<= 8;
if(!read(fd, &tmp, 1)) if(!getfunc(fd, &tmp))
return 0; return 0;
header |= tmp; header |= tmp;
pos++; pos++;
@ -235,7 +235,7 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
do { do {
header <<= 8; header <<= 8;
if(!read(fd, &tmp, 1)) if(!getfunc(fd, &tmp))
return 0; return 0;
header |= tmp; header |= tmp;
pos++; pos++;
@ -254,6 +254,16 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
return header; 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_read_index;
static int fnf_buf_len; 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 buf_find_next_frame(int fd, int *offset, int max_offset,
unsigned long last_header) unsigned long last_header)
{ {
unsigned long header=0; return __find_next_frame(fd, offset, max_offset, last_header, buf_getbyte);
unsigned char tmp; }
int i;
int pos = 0; static int mp3buflen;
static int mem_pos;
static int mem_cnt;
static int mem_maxlen;
/* We remember the last header we found, to use as a template to see if static int mem_getbyte(int dummy, unsigned char *c)
the header we find has the same frequency, layer etc */ {
last_header &= 0xffff0c00; dummy = dummy;
/* 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++;
}
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));
*offset = pos - 4;
#ifdef DEBUG
if(*offset)
DEBUGF("Warning: skipping %d bytes of garbage\n", *offset);
#endif
return header; *c = mp3buf[mem_pos++];
if(mem_pos >= mp3buflen)
mem_pos = 0;
if(mem_cnt++ >= mem_maxlen)
return 0;
else
return 1;
}
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;
return __find_next_frame(0, offset, max_offset, last_header, mem_getbyte);
} }
int get_mp3file_info(int fd, struct mp3info *info) int get_mp3file_info(int fd, struct mp3info *info)

View file

@ -52,6 +52,7 @@ static void stop_recording(void);
static int get_unplayed_space(void); static int get_unplayed_space(void);
static int get_playable_space(void); static int get_playable_space(void);
static int get_unswapped_space(void); static int get_unswapped_space(void);
static int get_unsaved_space(void);
#endif #endif
#define MPEG_PLAY 1 #define MPEG_PLAY 1
@ -65,6 +66,7 @@ static int get_unswapped_space(void);
#define MPEG_RECORD 9 #define MPEG_RECORD 9
#define MPEG_INIT_RECORDING 10 #define MPEG_INIT_RECORDING 10
#define MPEG_INIT_PLAYBACK 11 #define MPEG_INIT_PLAYBACK 11
#define MPEG_NEW_FILE 12
#define MPEG_NEED_DATA 100 #define MPEG_NEED_DATA 100
#define MPEG_TRACK_CHANGE 101 #define MPEG_TRACK_CHANGE 101
#define MPEG_SAVE_DATA 102 #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 char recording_filename[MAX_PATH];
static int rec_frequency_index; /* For create_xing_header() calls */ static int rec_frequency_index; /* For create_xing_header() calls */
static int rec_version_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 #endif
static int mpeg_file; static int mpeg_file;
@ -687,6 +690,16 @@ static int get_unswapped_space(void)
return space; 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) static void init_dma(void)
{ {
SAR3 = (unsigned int) mp3buf + mp3buf_read; SAR3 = (unsigned int) mp3buf + mp3buf_read;
@ -1270,6 +1283,9 @@ static void mpeg_thread(void)
int writelen; int writelen;
int framelen; int framelen;
unsigned long saved_header; unsigned long saved_header;
int startpos;
int rc;
int offset;
#endif #endif
is_playing = false; is_playing = false;
@ -1893,29 +1909,34 @@ static void mpeg_thread(void)
if(mpeg_file >= 0) if(mpeg_file >= 0)
close(mpeg_file); close(mpeg_file);
/* Create the Xing header */ if(!disable_xing_header)
mpeg_file = open(recording_filename, O_RDWR); {
if(mpeg_file < 0) /* Create the Xing header */
panicf("rec upd: %d (%s)", mpeg_file, recording_filename); 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, /* If the number of recorded frames have
we can no longer trust it */ reached 0x7ffff, we can no longer trust it */
if(num_recorded_frames == 0x7ffff) if(num_recorded_frames == 0x7ffff)
num_recorded_frames = 0; num_recorded_frames = 0;
/* Read the first MP3 frame from the recorded stream */ /* Read the first MP3 frame from the recorded stream */
lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET); lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET);
read(mpeg_file, &saved_header, 4); read(mpeg_file, &saved_header, 4);
framelen = create_xing_header(mpeg_file, 0, num_rec_bytes, framelen = create_xing_header(mpeg_file, 0,
mp3buf, num_recorded_frames, num_rec_bytes, mp3buf,
saved_header, NULL, false); num_recorded_frames,
saved_header, NULL,
lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen, false);
SEEK_SET);
write(mpeg_file, mp3buf, framelen); lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen,
close(mpeg_file); SEEK_SET);
write(mpeg_file, mp3buf, framelen);
close(mpeg_file);
}
mpeg_file = -1; mpeg_file = -1;
#ifdef DEBUG1 #ifdef DEBUG1
@ -1933,9 +1954,105 @@ static void mpeg_thread(void)
#endif #endif
mpeg_stop_done = true; mpeg_stop_done = true;
break; 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: 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 /* If the result is negative, the write index has
wrapped */ wrapped */
@ -1954,8 +2071,6 @@ static void mpeg_thread(void)
amount_to_save < MPEG_RECORDING_LOW_WATER || amount_to_save < MPEG_RECORDING_LOW_WATER ||
stop_pending) stop_pending)
{ {
int rc;
/* Only save up to the end of the buffer */ /* Only save up to the end of the buffer */
writelen = MIN(amount_to_save, writelen = MIN(amount_to_save,
mp3buflen - mp3buf_read); 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; mp3buf_read += amount_to_save;
if(mp3buf_read >= mp3buflen) if(mp3buf_read >= mp3buflen)
mp3buf_read = 0; mp3buf_read = 0;
rc = fsync(mpeg_file);
if(rc < 0)
panicf("rec fls: %d", rc);
queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
} }
else else
@ -2257,6 +2372,7 @@ void mpeg_record(char *filename)
recording_filename[MAX_PATH - 1] = 0; recording_filename[MAX_PATH - 1] = 0;
num_rec_bytes = 0; num_rec_bytes = 0;
disable_xing_header = false;
queue_post(&mpeg_queue, MPEG_RECORD, NULL); queue_post(&mpeg_queue, MPEG_RECORD, NULL);
} }
@ -2311,6 +2427,21 @@ static void stop_recording(void)
drain_dma_buffer(); 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) unsigned long mpeg_recorded_time(void)
{ {
if(is_recording) if(is_recording)