diff options
-rw-r--r-- | apps/playback.c | 67 | ||||
-rw-r--r-- | apps/playback.h | 9 | ||||
-rw-r--r-- | apps/plugins/codecflac.c | 3 | ||||
-rw-r--r-- | apps/plugins/codecmpa.c | 3 | ||||
-rw-r--r-- | apps/plugins/codecvorbis.c | 2 |
5 files changed, 62 insertions, 22 deletions
diff --git a/apps/playback.c b/apps/playback.c index 43e45ca3cf..71cb479059 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -67,9 +67,8 @@ static volatile bool paused; | |||
67 | #define CODEC_FLAC "/.rockbox/codecs/codecflac.rock"; | 67 | #define CODEC_FLAC "/.rockbox/codecs/codecflac.rock"; |
68 | #define CODEC_WAV "/.rockbox/codecs/codecwav.rock"; | 68 | #define CODEC_WAV "/.rockbox/codecs/codecwav.rock"; |
69 | 69 | ||
70 | #define AUDIO_WATERMARK (1024*256) | 70 | #define AUDIO_DEFAULT_WATERMARK (1024*256) |
71 | #define AUDIO_FILE_CHUNK (1024*32) | 71 | #define AUDIO_DEFAULT_FILECHUNK (1024*32) |
72 | #define AUDIO_INITIAL_CHUNK (1024*1024*2) | ||
73 | 72 | ||
74 | #define AUDIO_PLAY 1 | 73 | #define AUDIO_PLAY 1 |
75 | #define AUDIO_STOP 2 | 74 | #define AUDIO_STOP 2 |
@@ -165,8 +164,10 @@ static struct codec_api ci; | |||
165 | variable keeps information about whether to go a next/previous track. */ | 164 | variable keeps information about whether to go a next/previous track. */ |
166 | static int new_track; | 165 | static int new_track; |
167 | 166 | ||
168 | /* If we have just started playing, don't fill the whole file buffer. */ | 167 | /* Configuration */ |
169 | static unsigned int first_bufferfill; | 168 | static int conf_bufferlimit; |
169 | static int conf_watermark; | ||
170 | static int conf_filechunk; | ||
170 | 171 | ||
171 | static bool v1first = false; | 172 | static bool v1first = false; |
172 | 173 | ||
@@ -359,6 +360,26 @@ bool codec_seek_buffer_callback(off_t newpos) | |||
359 | return true; | 360 | return true; |
360 | } | 361 | } |
361 | 362 | ||
363 | void codec_configure_callback(int setting, void *value) | ||
364 | { | ||
365 | switch (setting) { | ||
366 | case CODEC_SET_FILEBUF_WATERMARK: | ||
367 | conf_watermark = (unsigned int)value; | ||
368 | break; | ||
369 | |||
370 | case CODEC_SET_FILEBUF_CHUNKSIZE: | ||
371 | conf_filechunk = (unsigned int)value; | ||
372 | break; | ||
373 | |||
374 | case CODEC_SET_FILEBUF_LIMIT: | ||
375 | conf_bufferlimit = (unsigned int)value; | ||
376 | break; | ||
377 | |||
378 | default: | ||
379 | logf("Illegal key: %d", setting); | ||
380 | } | ||
381 | } | ||
382 | |||
362 | /* Simple file type probing by looking filename extension. */ | 383 | /* Simple file type probing by looking filename extension. */ |
363 | int probe_file_format(const char *filename) | 384 | int probe_file_format(const char *filename) |
364 | { | 385 | { |
@@ -431,10 +452,10 @@ void audio_fill_file_buffer(void) | |||
431 | return ; | 452 | return ; |
432 | } | 453 | } |
433 | 454 | ||
434 | if (fill_bytesleft < MIN(AUDIO_FILE_CHUNK, | 455 | if (fill_bytesleft < MIN((unsigned int)conf_filechunk, |
435 | tracks[track_widx].filerem - i)) | 456 | tracks[track_widx].filerem - i)) |
436 | break ; | 457 | break ; |
437 | rc = MIN(AUDIO_FILE_CHUNK, codecbuflen - buf_widx); | 458 | rc = MIN(conf_filechunk, codecbuflen - buf_widx); |
438 | rc = read(current_fd, &codecbuf[buf_widx], rc); | 459 | rc = read(current_fd, &codecbuf[buf_widx], rc); |
439 | if (rc <= 0) { | 460 | if (rc <= 0) { |
440 | tracks[track_widx].filerem = 0; | 461 | tracks[track_widx].filerem = 0; |
@@ -535,7 +556,7 @@ bool loadcodec(const char *trackname, bool start_play) | |||
535 | } | 556 | } |
536 | 557 | ||
537 | size = filesize(fd); | 558 | size = filesize(fd); |
538 | if ((off_t)fill_bytesleft < size + AUDIO_WATERMARK) { | 559 | if ((off_t)fill_bytesleft < size + conf_watermark) { |
539 | logf("Not enough space"); | 560 | logf("Not enough space"); |
540 | close(fd); | 561 | close(fd); |
541 | return false; | 562 | return false; |
@@ -550,7 +571,7 @@ bool loadcodec(const char *trackname, bool start_play) | |||
550 | return false; | 571 | return false; |
551 | } | 572 | } |
552 | 573 | ||
553 | copy_n = MIN(AUDIO_FILE_CHUNK, codecbuflen - buf_widx); | 574 | copy_n = MIN(conf_filechunk, codecbuflen - buf_widx); |
554 | rc = read(fd, &codecbuf[buf_widx], copy_n); | 575 | rc = read(fd, &codecbuf[buf_widx], copy_n); |
555 | if (rc < 0) | 576 | if (rc < 0) |
556 | return false; | 577 | return false; |
@@ -603,7 +624,14 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
603 | /* Load the codec */ | 624 | /* Load the codec */ |
604 | if (buf_widx >= codecbuflen) | 625 | if (buf_widx >= codecbuflen) |
605 | buf_widx -= codecbuflen; | 626 | buf_widx -= codecbuflen; |
606 | 627 | ||
628 | /* Set default values */ | ||
629 | if (start_play) { | ||
630 | conf_bufferlimit = 0; | ||
631 | conf_watermark = AUDIO_DEFAULT_WATERMARK; | ||
632 | conf_filechunk = AUDIO_DEFAULT_FILECHUNK; | ||
633 | } | ||
634 | |||
607 | tracks[track_widx].codecbuf = &codecbuf[buf_widx]; | 635 | tracks[track_widx].codecbuf = &codecbuf[buf_widx]; |
608 | if (!loadcodec(trackname, start_play)) { | 636 | if (!loadcodec(trackname, start_play)) { |
609 | close(fd); | 637 | close(fd); |
@@ -720,18 +748,19 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
720 | break; | 748 | break; |
721 | } | 749 | } |
722 | 750 | ||
723 | /* Limit buffering size at first run. */ | ||
724 | if (first_bufferfill && fill_bytesleft >= first_bufferfill) { | ||
725 | fill_bytesleft = first_bufferfill; | ||
726 | first_bufferfill = 0; | ||
727 | } | ||
728 | |||
729 | track_changed = true; | 751 | track_changed = true; |
730 | track_count++; | 752 | track_count++; |
731 | i = tracks[track_widx].filepos; | 753 | i = tracks[track_widx].filepos; |
732 | while (i < size) { | 754 | while (i < size) { |
733 | /* Give codecs some processing time to prevent glitches. */ | 755 | /* Give codecs some processing time to prevent glitches. */ |
734 | yield_codecs(); | 756 | yield_codecs(); |
757 | |||
758 | /* Limit buffering size at first run. */ | ||
759 | if (conf_bufferlimit && (int)fill_bytesleft >= conf_bufferlimit) { | ||
760 | fill_bytesleft = conf_bufferlimit; | ||
761 | conf_bufferlimit = 0; | ||
762 | } | ||
763 | |||
735 | if (!queue_empty(&audio_queue)) { | 764 | if (!queue_empty(&audio_queue)) { |
736 | logf("Buffering interrupted"); | 765 | logf("Buffering interrupted"); |
737 | close(fd); | 766 | close(fd); |
@@ -741,7 +770,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
741 | if (fill_bytesleft == 0) | 770 | if (fill_bytesleft == 0) |
742 | break ; | 771 | break ; |
743 | 772 | ||
744 | copy_n = MIN(AUDIO_FILE_CHUNK, codecbuflen - buf_widx); | 773 | copy_n = MIN(conf_filechunk, codecbuflen - buf_widx); |
745 | copy_n = MIN(size - i, copy_n); | 774 | copy_n = MIN(size - i, copy_n); |
746 | copy_n = MIN((int)fill_bytesleft, copy_n); | 775 | copy_n = MIN((int)fill_bytesleft, copy_n); |
747 | rc = read(fd, &codecbuf[buf_widx], copy_n); | 776 | rc = read(fd, &codecbuf[buf_widx], copy_n); |
@@ -825,7 +854,7 @@ void audio_check_buffer(void) | |||
825 | #endif | 854 | #endif |
826 | 855 | ||
827 | /* Start buffer filling as necessary. */ | 856 | /* Start buffer filling as necessary. */ |
828 | if (codecbufused > AUDIO_WATERMARK || !queue_empty(&audio_queue) | 857 | if (codecbufused > conf_watermark || !queue_empty(&audio_queue) |
829 | || !playing || ci.stop_codec || ci.reload_codec) | 858 | || !playing || ci.stop_codec || ci.reload_codec) |
830 | return ; | 859 | return ; |
831 | 860 | ||
@@ -1163,7 +1192,6 @@ void audio_play(int offset) | |||
1163 | #endif | 1192 | #endif |
1164 | paused = false; | 1193 | paused = false; |
1165 | playing = true; | 1194 | playing = true; |
1166 | first_bufferfill = AUDIO_INITIAL_CHUNK; | ||
1167 | queue_post(&audio_queue, AUDIO_PLAY, (void *)offset); | 1195 | queue_post(&audio_queue, AUDIO_PLAY, (void *)offset); |
1168 | } | 1196 | } |
1169 | 1197 | ||
@@ -1435,6 +1463,7 @@ void audio_init(void) | |||
1435 | ci.mp3_get_filepos = codec_mp3_get_filepos_callback; | 1463 | ci.mp3_get_filepos = codec_mp3_get_filepos_callback; |
1436 | ci.seek_buffer = codec_seek_buffer_callback; | 1464 | ci.seek_buffer = codec_seek_buffer_callback; |
1437 | ci.set_elapsed = codec_set_elapsed_callback; | 1465 | ci.set_elapsed = codec_set_elapsed_callback; |
1466 | ci.configure = codec_configure_callback; | ||
1438 | 1467 | ||
1439 | queue_init(&audio_queue); | 1468 | queue_init(&audio_queue); |
1440 | queue_init(&codec_queue); | 1469 | queue_init(&codec_queue); |
diff --git a/apps/playback.h b/apps/playback.h index 6f3c4214a2..c9668bd9a2 100644 --- a/apps/playback.h +++ b/apps/playback.h | |||
@@ -35,6 +35,13 @@ | |||
35 | #define AFMT_REAL 0x0800 // Realaudio | 35 | #define AFMT_REAL 0x0800 // Realaudio |
36 | #define AFMT_UNKNOWN 0x1000 // Unknown file format | 36 | #define AFMT_UNKNOWN 0x1000 // Unknown file format |
37 | 37 | ||
38 | #define CODEC_SET_FILEBUF_WATERMARK 1 | ||
39 | #define CODEC_SET_FILEBUF_CHUNKSIZE 2 | ||
40 | #define CODEC_SET_FILEBUF_LIMIT 3 | ||
41 | |||
42 | /* Not yet implemented. */ | ||
43 | #define CODEC_SET_AUDIOBUF_WATERMARK 4 | ||
44 | |||
38 | struct codec_api { | 45 | struct codec_api { |
39 | off_t filesize; | 46 | off_t filesize; |
40 | off_t curpos; | 47 | off_t curpos; |
@@ -60,6 +67,8 @@ struct codec_api { | |||
60 | bool (*seek_buffer)(off_t newpos); | 67 | bool (*seek_buffer)(off_t newpos); |
61 | off_t (*mp3_get_filepos)(int newtime); | 68 | off_t (*mp3_get_filepos)(int newtime); |
62 | bool (*request_next_track)(void); | 69 | bool (*request_next_track)(void); |
70 | |||
71 | void (*configure)(int setting, void *value); | ||
63 | }; | 72 | }; |
64 | 73 | ||
65 | #endif | 74 | #endif |
diff --git a/apps/plugins/codecflac.c b/apps/plugins/codecflac.c index 8862bbc215..d577006440 100644 --- a/apps/plugins/codecflac.c +++ b/apps/plugins/codecflac.c | |||
@@ -171,7 +171,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
171 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); | 171 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); |
172 | #endif | 172 | #endif |
173 | 173 | ||
174 | /* This function sets up the buffers and reads the file into RAM */ | 174 | ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*10)); |
175 | ci->configure(CODEC_SET_FILEBUF_WATERMARK, (int *)(1024*512)); | ||
175 | 176 | ||
176 | next_track: | 177 | next_track: |
177 | 178 | ||
diff --git a/apps/plugins/codecmpa.c b/apps/plugins/codecmpa.c index 46014127b8..88f6b8c624 100644 --- a/apps/plugins/codecmpa.c +++ b/apps/plugins/codecmpa.c | |||
@@ -216,8 +216,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
216 | 216 | ||
217 | /* Create a decoder instance */ | 217 | /* Create a decoder instance */ |
218 | 218 | ||
219 | next_track: | 219 | ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); |
220 | 220 | ||
221 | next_track: | ||
221 | memset(&Stream, 0, sizeof(struct mad_stream)); | 222 | memset(&Stream, 0, sizeof(struct mad_stream)); |
222 | memset(&Frame, 0, sizeof(struct mad_frame)); | 223 | memset(&Frame, 0, sizeof(struct mad_frame)); |
223 | memset(&Synth, 0, sizeof(struct mad_synth)); | 224 | memset(&Synth, 0, sizeof(struct mad_synth)); |
diff --git a/apps/plugins/codecvorbis.c b/apps/plugins/codecvorbis.c index 948482677f..c1ccdfd3fa 100644 --- a/apps/plugins/codecvorbis.c +++ b/apps/plugins/codecvorbis.c | |||
@@ -104,7 +104,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
104 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); | 104 | rb->memcpy(iramstart, iramcopy, iramend-iramstart); |
105 | #endif | 105 | #endif |
106 | 106 | ||
107 | /* This function sets up the buffers and reads the file into RAM */ | 107 | ci->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); |
108 | 108 | ||
109 | /* We need to flush reserver memory every track load. */ | 109 | /* We need to flush reserver memory every track load. */ |
110 | next_track: | 110 | next_track: |