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.tar.gz
rockbox-24a8b6ad09dc3ba357543c36ca17880d09461022.zip
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 868f45f07c..0f095bef48 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -221,6 +221,11 @@ bool recording_screen(void)
221 update_countdown = 1; /* Update immediately */ 221 update_countdown = 1; /* Update immediately */
222 last_seconds = 0; 222 last_seconds = 0;
223 } 223 }
224 else
225 {
226 mpeg_new_file(create_filename());
227 update_countdown = 1; /* Update immediately */
228 }
224 break; 229 break;
225 230
226 case BUTTON_UP: 231 case BUTTON_UP:
@@ -389,10 +394,7 @@ bool recording_screen(void)
389 394
390 if (mpeg_status() && (seconds >= dseconds)) 395 if (mpeg_status() && (seconds >= dseconds))
391 { 396 {
392 /* stop and restart recording */ 397 mpeg_new_file(create_filename());
393 mpeg_stop();
394 have_recorded = true;
395 mpeg_record(create_filename());
396 update_countdown = 1; 398 update_countdown = 1;
397 last_seconds = 0; 399 last_seconds = 0;
398 } 400 }
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index 6b3ff83b1a..833a4c9dfa 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -56,6 +56,8 @@ struct mp3info {
56 56
57 57
58unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header); 58unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header);
59unsigned long mem_find_next_frame(int startpos, int *offset, int max_offset,
60 unsigned long last_header);
59int get_mp3file_info(int fd, struct mp3info *info); 61int get_mp3file_info(int fd, struct mp3info *info);
60int count_mp3_frames(int fd, int startpos, int filesize, 62int count_mp3_frames(int fd, int startpos, int filesize,
61 void (*progressfunc)(int)); 63 void (*progressfunc)(int));
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index bdf65dd7a8..63eecf51db 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -86,6 +86,7 @@ void mpeg_set_pitch(int percent);
86void mpeg_init_recording(void); 86void mpeg_init_recording(void);
87void mpeg_init_playback(void); 87void mpeg_init_playback(void);
88void mpeg_record(char *filename); 88void mpeg_record(char *filename);
89void mpeg_new_file(char *filename);
89void mpeg_set_recording_options(int frequency, int quality, 90void mpeg_set_recording_options(int frequency, int quality,
90 int source, int channel_mode, 91 int source, int channel_mode,
91 bool editable); 92 bool editable);
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 670934d38d..83d916ff9f 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -212,7 +212,7 @@ static bool mp3headerinfo(struct mp3info *info, unsigned long header)
212 return true; 212 return true;
213} 213}
214 214
215unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header) 215static unsigned long __find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header, int(*getfunc)(int fd, unsigned char *c))
216{ 216{
217 unsigned long header=0; 217 unsigned long header=0;
218 unsigned char tmp; 218 unsigned char tmp;
@@ -227,7 +227,7 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
227 /* Fill up header with first 24 bits */ 227 /* Fill up header with first 24 bits */
228 for(i = 0; i < 3; i++) { 228 for(i = 0; i < 3; i++) {
229 header <<= 8; 229 header <<= 8;
230 if(!read(fd, &tmp, 1)) 230 if(!getfunc(fd, &tmp))
231 return 0; 231 return 0;
232 header |= tmp; 232 header |= tmp;
233 pos++; 233 pos++;
@@ -235,7 +235,7 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
235 235
236 do { 236 do {
237 header <<= 8; 237 header <<= 8;
238 if(!read(fd, &tmp, 1)) 238 if(!getfunc(fd, &tmp))
239 return 0; 239 return 0;
240 header |= tmp; 240 header |= tmp;
241 pos++; 241 pos++;
@@ -254,6 +254,16 @@ unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long
254 return header; 254 return header;
255} 255}
256 256
257static int fileread(int fd, unsigned char *c)
258{
259 return read(fd, c, 1);
260}
261
262unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header)
263{
264 return __find_next_frame(fd, offset, max_offset, last_header, fileread);
265}
266
257static int fnf_read_index; 267static int fnf_read_index;
258static int fnf_buf_len; 268static int fnf_buf_len;
259 269
@@ -315,44 +325,37 @@ static void buf_init(void)
315unsigned long buf_find_next_frame(int fd, int *offset, int max_offset, 325unsigned long buf_find_next_frame(int fd, int *offset, int max_offset,
316 unsigned long last_header) 326 unsigned long last_header)
317{ 327{
318 unsigned long header=0; 328 return __find_next_frame(fd, offset, max_offset, last_header, buf_getbyte);
319 unsigned char tmp; 329}
320 int i;
321
322 int pos = 0;
323 330
324 /* We remember the last header we found, to use as a template to see if 331static int mp3buflen;
325 the header we find has the same frequency, layer etc */ 332static int mem_pos;
326 last_header &= 0xffff0c00; 333static int mem_cnt;
334static int mem_maxlen;
327 335
328 /* Fill up header with first 24 bits */ 336static int mem_getbyte(int dummy, unsigned char *c)
329 for(i = 0; i < 3; i++) { 337{
330 header <<= 8; 338 dummy = dummy;
331 if(!buf_getbyte(fd, &tmp)) 339
332 return 0; 340 *c = mp3buf[mem_pos++];
333 header |= tmp; 341 if(mem_pos >= mp3buflen)
334 pos++; 342 mem_pos = 0;
335 }
336 343
337 do { 344 if(mem_cnt++ >= mem_maxlen)
338 header <<= 8; 345 return 0;
339 if(!buf_getbyte(fd, &tmp)) 346 else
340 return 0; 347 return 1;
341 header |= tmp; 348}
342 pos++;
343 if(max_offset > 0 && pos > max_offset)
344 return 0;
345 } while(!is_mp3frameheader(header) ||
346 (last_header?((header & 0xffff0c00) != last_header):false));
347 349
348 *offset = pos - 4; 350unsigned long mem_find_next_frame(int startpos, int *offset, int max_offset,
351 unsigned long last_header)
352{
353 mp3buflen = mp3end - mp3buf;
354 mem_pos = startpos;
355 mem_cnt = 0;
356 mem_maxlen = max_offset;
349 357
350#ifdef DEBUG 358 return __find_next_frame(0, offset, max_offset, last_header, mem_getbyte);
351 if(*offset)
352 DEBUGF("Warning: skipping %d bytes of garbage\n", *offset);
353#endif
354
355 return header;
356} 359}
357 360
358int get_mp3file_info(int fd, struct mp3info *info) 361int get_mp3file_info(int fd, struct mp3info *info)
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 9d6718dc42..5a6fae4316 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -52,6 +52,7 @@ static void stop_recording(void);
52static int get_unplayed_space(void); 52static int get_unplayed_space(void);
53static int get_playable_space(void); 53static int get_playable_space(void);
54static int get_unswapped_space(void); 54static int get_unswapped_space(void);
55static int get_unsaved_space(void);
55#endif 56#endif
56 57
57#define MPEG_PLAY 1 58#define MPEG_PLAY 1
@@ -65,6 +66,7 @@ static int get_unswapped_space(void);
65#define MPEG_RECORD 9 66#define MPEG_RECORD 9
66#define MPEG_INIT_RECORDING 10 67#define MPEG_INIT_RECORDING 10
67#define MPEG_INIT_PLAYBACK 11 68#define MPEG_INIT_PLAYBACK 11
69#define MPEG_NEW_FILE 12
68#define MPEG_NEED_DATA 100 70#define MPEG_NEED_DATA 100
69#define MPEG_TRACK_CHANGE 101 71#define MPEG_TRACK_CHANGE 101
70#define MPEG_SAVE_DATA 102 72#define MPEG_SAVE_DATA 102
@@ -494,6 +496,7 @@ static bool saving; /* We are saving the buffer to disk */
494static char recording_filename[MAX_PATH]; 496static char recording_filename[MAX_PATH];
495static int rec_frequency_index; /* For create_xing_header() calls */ 497static int rec_frequency_index; /* For create_xing_header() calls */
496static int rec_version_index; /* For create_xing_header() calls */ 498static int rec_version_index; /* For create_xing_header() calls */
499static bool disable_xing_header; /* When splitting files */
497#endif 500#endif
498 501
499static int mpeg_file; 502static int mpeg_file;
@@ -687,6 +690,16 @@ static int get_unswapped_space(void)
687 return space; 690 return space;
688} 691}
689 692
693#ifdef HAVE_MAS3587F
694static int get_unsaved_space(void)
695{
696 int space = mp3buf_write - mp3buf_read;
697 if (space < 0)
698 space += mp3buflen;
699 return space;
700}
701#endif
702
690static void init_dma(void) 703static void init_dma(void)
691{ 704{
692 SAR3 = (unsigned int) mp3buf + mp3buf_read; 705 SAR3 = (unsigned int) mp3buf + mp3buf_read;
@@ -1270,6 +1283,9 @@ static void mpeg_thread(void)
1270 int writelen; 1283 int writelen;
1271 int framelen; 1284 int framelen;
1272 unsigned long saved_header; 1285 unsigned long saved_header;
1286 int startpos;
1287 int rc;
1288 int offset;
1273#endif 1289#endif
1274 1290
1275 is_playing = false; 1291 is_playing = false;
@@ -1893,29 +1909,34 @@ static void mpeg_thread(void)
1893 if(mpeg_file >= 0) 1909 if(mpeg_file >= 0)
1894 close(mpeg_file); 1910 close(mpeg_file);
1895 1911
1896 /* Create the Xing header */ 1912 if(!disable_xing_header)
1897 mpeg_file = open(recording_filename, O_RDWR); 1913 {
1898 if(mpeg_file < 0) 1914 /* Create the Xing header */
1899 panicf("rec upd: %d (%s)", mpeg_file, recording_filename); 1915 mpeg_file = open(recording_filename, O_RDWR);
1900 1916 if(mpeg_file < 0)
1901 /* If the number of recorded frames have reached 0x7ffff, 1917 panicf("rec upd: %d (%s)", mpeg_file,
1902 we can no longer trust it */ 1918 recording_filename);
1903 if(num_recorded_frames == 0x7ffff) 1919
1904 num_recorded_frames = 0; 1920 /* If the number of recorded frames have
1905 1921 reached 0x7ffff, we can no longer trust it */
1906 /* Read the first MP3 frame from the recorded stream */ 1922 if(num_recorded_frames == 0x7ffff)
1907 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET); 1923 num_recorded_frames = 0;
1908 read(mpeg_file, &saved_header, 4); 1924
1909 1925 /* Read the first MP3 frame from the recorded stream */
1910 framelen = create_xing_header(mpeg_file, 0, num_rec_bytes, 1926 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET);
1911 mp3buf, num_recorded_frames, 1927 read(mpeg_file, &saved_header, 4);
1912 saved_header, NULL, false); 1928
1913 1929 framelen = create_xing_header(mpeg_file, 0,
1914 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen, 1930 num_rec_bytes, mp3buf,
1915 SEEK_SET); 1931 num_recorded_frames,
1916 write(mpeg_file, mp3buf, framelen); 1932 saved_header, NULL,
1917 close(mpeg_file); 1933 false);
1918 1934
1935 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen,
1936 SEEK_SET);
1937 write(mpeg_file, mp3buf, framelen);
1938 close(mpeg_file);
1939 }
1919 mpeg_file = -1; 1940 mpeg_file = -1;
1920 1941
1921#ifdef DEBUG1 1942#ifdef DEBUG1
@@ -1933,9 +1954,105 @@ static void mpeg_thread(void)
1933#endif 1954#endif
1934 mpeg_stop_done = true; 1955 mpeg_stop_done = true;
1935 break; 1956 break;
1957
1958 case MPEG_NEW_FILE:
1959 /* Make sure we have at least one complete frame
1960 in the buffer */
1961 amount_to_save = get_unsaved_space();
1962 while(amount_to_save < 1800)
1963 {
1964 sleep(HZ/10);
1965 amount_to_save = get_unsaved_space();
1966 }
1967
1968 /* Now find a frame boundary to split at */
1969 startpos = mp3buf_write - 1800;
1970 if(startpos < 0)
1971 startpos += mp3buflen;
1972
1973 {
1974 unsigned long tmp[2];
1975 /* Find out how the mp3 header should look like */
1976 mas_readmem(MAS_BANK_D0, 0xfd1, tmp, 2);
1977 saved_header = 0xffe00000 |
1978 ((tmp[0] & 0x7c00) << 6) |
1979 (tmp[1] & 0xffff);
1980 DEBUGF("Header: %08x\n", saved_header);
1981 }
1982
1983 mem_find_next_frame(startpos, &offset, 1800, saved_header);
1984
1985 /* offset will now contain the number of bytes to
1986 add to startpos to find the frame boundary */
1987 startpos += offset;
1988 if(startpos >= mp3buflen)
1989 startpos -= mp3buflen;
1990
1991 amount_to_save = startpos - mp3buf_read;
1992 if(amount_to_save < 0)
1993 amount_to_save += mp3buflen;
1994
1995 /* First save up to the end of the buffer */
1996 writelen = MIN(amount_to_save,
1997 mp3buflen - mp3buf_read);
1998
1999 rc = write(mpeg_file, mp3buf + mp3buf_read, writelen);
2000 if(rc < 0)
2001 {
2002 if(errno == ENOSPC)
2003 {
2004 mpeg_errno = MPEGERR_DISK_FULL;
2005 demand_irq_enable(false);
2006 stop_recording();
2007 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
2008 break;
2009 }
2010 else
2011 {
2012 panicf("rec wrt: %d", rc);
2013 }
2014 }
2015
2016 /* Then save the rest */
2017 writelen = amount_to_save - writelen;
2018 if(writelen)
2019 {
2020 rc = write(mpeg_file, mp3buf, writelen);
2021 if(rc < 0)
2022 {
2023 if(errno == ENOSPC)
2024 {
2025 mpeg_errno = MPEGERR_DISK_FULL;
2026 demand_irq_enable(false);
2027 stop_recording();
2028 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
2029 break;
2030 }
2031 else
2032 {
2033 panicf("spt wrt: %d", rc);
2034 }
2035 }
2036 }
2037
2038 /* Advance the buffer pointers */
2039 mp3buf_read += amount_to_save;
2040 if(mp3buf_read >= mp3buflen)
2041 mp3buf_read -= mp3buflen;
2042
2043 /* Close the current file */
2044 rc = close(mpeg_file);
2045 if(rc < 0)
2046 panicf("spt cls: %d", rc);
2047
2048 /* Open the new file */
2049 mpeg_file = open(recording_filename, O_WRONLY|O_CREAT);
2050 if(mpeg_file < 0)
2051 panicf("sptfile: %d", mpeg_file);
2052 break;
1936 2053
1937 case MPEG_SAVE_DATA: 2054 case MPEG_SAVE_DATA:
1938 amount_to_save = mp3buf_write - mp3buf_read; 2055 amount_to_save = get_unsaved_space();
1939 2056
1940 /* If the result is negative, the write index has 2057 /* If the result is negative, the write index has
1941 wrapped */ 2058 wrapped */
@@ -1954,8 +2071,6 @@ static void mpeg_thread(void)
1954 amount_to_save < MPEG_RECORDING_LOW_WATER || 2071 amount_to_save < MPEG_RECORDING_LOW_WATER ||
1955 stop_pending) 2072 stop_pending)
1956 { 2073 {
1957 int rc;
1958
1959 /* Only save up to the end of the buffer */ 2074 /* Only save up to the end of the buffer */
1960 writelen = MIN(amount_to_save, 2075 writelen = MIN(amount_to_save,
1961 mp3buflen - mp3buf_read); 2076 mp3buflen - mp3buf_read);
@@ -1981,14 +2096,14 @@ static void mpeg_thread(void)
1981 } 2096 }
1982 } 2097 }
1983 2098
1984 rc = fsync(mpeg_file);
1985 if(rc < 0)
1986 panicf("rec fls: %d", rc);
1987
1988 mp3buf_read += amount_to_save; 2099 mp3buf_read += amount_to_save;
1989 if(mp3buf_read >= mp3buflen) 2100 if(mp3buf_read >= mp3buflen)
1990 mp3buf_read = 0; 2101 mp3buf_read = 0;
1991 2102
2103 rc = fsync(mpeg_file);
2104 if(rc < 0)
2105 panicf("rec fls: %d", rc);
2106
1992 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0); 2107 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1993 } 2108 }
1994 else 2109 else
@@ -2257,6 +2372,7 @@ void mpeg_record(char *filename)
2257 recording_filename[MAX_PATH - 1] = 0; 2372 recording_filename[MAX_PATH - 1] = 0;
2258 2373
2259 num_rec_bytes = 0; 2374 num_rec_bytes = 0;
2375 disable_xing_header = false;
2260 queue_post(&mpeg_queue, MPEG_RECORD, NULL); 2376 queue_post(&mpeg_queue, MPEG_RECORD, NULL);
2261} 2377}
2262 2378
@@ -2311,6 +2427,21 @@ static void stop_recording(void)
2311 drain_dma_buffer(); 2427 drain_dma_buffer();
2312} 2428}
2313 2429
2430void mpeg_new_file(char *filename)
2431{
2432 mpeg_errno = 0;
2433
2434 strncpy(recording_filename, filename, MAX_PATH - 1);
2435 recording_filename[MAX_PATH - 1] = 0;
2436
2437 disable_xing_header = true;
2438
2439 /* Store the current time */
2440 record_start_time = current_tick;
2441
2442 queue_post(&mpeg_queue, MPEG_NEW_FILE, NULL);
2443}
2444
2314unsigned long mpeg_recorded_time(void) 2445unsigned long mpeg_recorded_time(void)
2315{ 2446{
2316 if(is_recording) 2447 if(is_recording)