diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2005-06-07 06:34:54 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2005-06-07 06:34:54 +0000 |
commit | 82c2927d1e8e900bee29c73f066e341cf4ec0ea5 (patch) | |
tree | 3ae85cd77fe62d08163c28f95e677c4a54bf1288 | |
parent | 0f10e898f0040e30f0a23719e67223744c47f90d (diff) | |
download | rockbox-82c2927d1e8e900bee29c73f066e341cf4ec0ea5.tar.gz rockbox-82c2927d1e8e900bee29c73f066e341cf4ec0ea5.zip |
Fixed: Ogg Vorbis crashing, MP3 file seeking, USB mode and a little
faster file buffering.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6591 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/playback.c | 109 | ||||
-rw-r--r-- | apps/plugins/codecvorbis.c | 3 | ||||
-rw-r--r-- | firmware/export/pcm_playback.h | 1 | ||||
-rw-r--r-- | firmware/pcm_playback.c | 19 |
4 files changed, 110 insertions, 22 deletions
diff --git a/apps/playback.c b/apps/playback.c index 6751266d7f..d1678a89e1 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -114,11 +114,11 @@ char *codecbuf; | |||
114 | int codecbuflen; | 114 | int codecbuflen; |
115 | 115 | ||
116 | /* Bytes available in the buffer. */ | 116 | /* Bytes available in the buffer. */ |
117 | volatile int codecbufused; | 117 | static volatile int codecbufused; |
118 | 118 | ||
119 | /* Ring buffer read and write indexes. */ | 119 | /* Ring buffer read and write indexes. */ |
120 | static int buf_ridx; | 120 | static volatile int buf_ridx; |
121 | static int buf_widx; | 121 | static volatile int buf_widx; |
122 | 122 | ||
123 | #define MAX_TRACK 10 | 123 | #define MAX_TRACK 10 |
124 | struct track_info { | 124 | struct track_info { |
@@ -140,8 +140,8 @@ struct track_info { | |||
140 | /* Track information (count in file buffer, read/write indexes for | 140 | /* Track information (count in file buffer, read/write indexes for |
141 | track ring structure. */ | 141 | track ring structure. */ |
142 | static int track_count; | 142 | static int track_count; |
143 | static int track_ridx; | 143 | static volatile int track_ridx; |
144 | static int track_widx; | 144 | static volatile int track_widx; |
145 | static bool track_changed; | 145 | static bool track_changed; |
146 | 146 | ||
147 | /* Playlist position to tell the next track. */ | 147 | /* Playlist position to tell the next track. */ |
@@ -224,7 +224,6 @@ size_t codec_filebuf_callback(void *ptr, size_t size) | |||
224 | part_n = MIN(copy_n, codecbuflen - buf_ridx); | 224 | part_n = MIN(copy_n, codecbuflen - buf_ridx); |
225 | memcpy(buf, &codecbuf[buf_ridx], part_n); | 225 | memcpy(buf, &codecbuf[buf_ridx], part_n); |
226 | if (part_n < copy_n) { | 226 | if (part_n < copy_n) { |
227 | part_n = copy_n - part_n; | ||
228 | memcpy(&buf[part_n], &codecbuf[0], copy_n - part_n); | 227 | memcpy(&buf[part_n], &codecbuf[0], copy_n - part_n); |
229 | } | 228 | } |
230 | 229 | ||
@@ -293,6 +292,8 @@ void codec_advance_buffer_loc_callback(void *ptr) | |||
293 | codec_advance_buffer_callback(amount); | 292 | codec_advance_buffer_callback(amount); |
294 | } | 293 | } |
295 | 294 | ||
295 | int mp3_get_file_pos(void); | ||
296 | |||
296 | off_t codec_mp3_get_filepos_callback(int newtime) | 297 | off_t codec_mp3_get_filepos_callback(int newtime) |
297 | { | 298 | { |
298 | int oldtime; | 299 | int oldtime; |
@@ -300,7 +301,7 @@ off_t codec_mp3_get_filepos_callback(int newtime) | |||
300 | 301 | ||
301 | oldtime = cur_ti->id3.elapsed; | 302 | oldtime = cur_ti->id3.elapsed; |
302 | cur_ti->id3.elapsed = newtime; | 303 | cur_ti->id3.elapsed = newtime; |
303 | newpos = audio_get_file_pos(); | 304 | newpos = mp3_get_file_pos(); |
304 | cur_ti->id3.elapsed = oldtime; | 305 | cur_ti->id3.elapsed = oldtime; |
305 | 306 | ||
306 | return newpos; | 307 | return newpos; |
@@ -394,6 +395,18 @@ int probe_file_format(const char *filename) | |||
394 | 395 | ||
395 | } | 396 | } |
396 | 397 | ||
398 | void yield_codecs(void) | ||
399 | { | ||
400 | #ifndef SIMULATOR | ||
401 | if (!pcm_is_playing()) | ||
402 | sleep(5); | ||
403 | while (pcm_is_lowdata()) | ||
404 | yield(); | ||
405 | #else | ||
406 | yield(); | ||
407 | #endif | ||
408 | } | ||
409 | |||
397 | void audio_fill_file_buffer(void) | 410 | void audio_fill_file_buffer(void) |
398 | { | 411 | { |
399 | size_t i; | 412 | size_t i; |
@@ -402,7 +415,9 @@ void audio_fill_file_buffer(void) | |||
402 | logf("Filling buffer..."); | 415 | logf("Filling buffer..."); |
403 | i = 0; | 416 | i = 0; |
404 | while ((off_t)i < tracks[track_widx].filerem) { | 417 | while ((off_t)i < tracks[track_widx].filerem) { |
405 | sleep(5); /* Give codecs some processing time. */ | 418 | /* Give codecs some processing time. */ |
419 | yield_codecs(); | ||
420 | |||
406 | if (!playing) { | 421 | if (!playing) { |
407 | logf("Filling interrupted"); | 422 | logf("Filling interrupted"); |
408 | close(current_fd); | 423 | close(current_fd); |
@@ -413,13 +428,13 @@ void audio_fill_file_buffer(void) | |||
413 | if (fill_bytesleft < MIN(AUDIO_FILE_CHUNK, | 428 | if (fill_bytesleft < MIN(AUDIO_FILE_CHUNK, |
414 | tracks[track_widx].filerem - i)) | 429 | tracks[track_widx].filerem - i)) |
415 | break ; | 430 | break ; |
416 | |||
417 | rc = MIN(AUDIO_FILE_CHUNK, codecbuflen - buf_widx); | 431 | rc = MIN(AUDIO_FILE_CHUNK, codecbuflen - buf_widx); |
418 | rc = read(current_fd, &codecbuf[buf_widx], rc); | 432 | rc = read(current_fd, &codecbuf[buf_widx], rc); |
419 | if (rc <= 0) { | 433 | if (rc <= 0) { |
420 | tracks[track_widx].filerem = 0; | 434 | tracks[track_widx].filerem = 0; |
421 | break ; | 435 | break ; |
422 | } | 436 | } |
437 | |||
423 | buf_widx += rc; | 438 | buf_widx += rc; |
424 | if (buf_widx == codecbuflen) | 439 | if (buf_widx == codecbuflen) |
425 | buf_widx = 0; | 440 | buf_widx = 0; |
@@ -521,7 +536,7 @@ bool loadcodec(const char *trackname, bool start_play) | |||
521 | 536 | ||
522 | i = 0; | 537 | i = 0; |
523 | while (i < size) { | 538 | while (i < size) { |
524 | yield(); | 539 | yield_codecs(); |
525 | if (!playing) { | 540 | if (!playing) { |
526 | logf("Buffering interrupted"); | 541 | logf("Buffering interrupted"); |
527 | close(fd); | 542 | close(fd); |
@@ -616,7 +631,7 @@ bool audio_load_track(int offset, bool start_play) | |||
616 | i = 0; | 631 | i = 0; |
617 | while (i < size) { | 632 | while (i < size) { |
618 | /* Give codecs some processing time to prevent glitches. */ | 633 | /* Give codecs some processing time to prevent glitches. */ |
619 | sleep(5); | 634 | yield_codecs(); |
620 | if (!playing) { | 635 | if (!playing) { |
621 | logf("Buffering interrupted"); | 636 | logf("Buffering interrupted"); |
622 | close(fd); | 637 | close(fd); |
@@ -635,7 +650,7 @@ bool audio_load_track(int offset, bool start_play) | |||
635 | return false; | 650 | return false; |
636 | } | 651 | } |
637 | buf_widx += rc; | 652 | buf_widx += rc; |
638 | if (buf_widx == codecbuflen) | 653 | if (buf_widx >= codecbuflen) |
639 | buf_widx = 0; | 654 | buf_widx = 0; |
640 | i += rc; | 655 | i += rc; |
641 | tracks[track_widx].available += rc; | 656 | tracks[track_widx].available += rc; |
@@ -731,6 +746,7 @@ void audio_check_buffer(void) | |||
731 | for (i = 0; i < MAX_TRACK - track_count; i++) { | 746 | for (i = 0; i < MAX_TRACK - track_count; i++) { |
732 | if (++cur_idx >= MAX_TRACK) | 747 | if (++cur_idx >= MAX_TRACK) |
733 | cur_idx = 0; | 748 | cur_idx = 0; |
749 | tracks[cur_idx].filesize = 0; | ||
734 | tracks[cur_idx].available = 0; | 750 | tracks[cur_idx].available = 0; |
735 | } | 751 | } |
736 | 752 | ||
@@ -806,7 +822,7 @@ bool codec_request_next_track_callback(void) | |||
806 | if (ci.reload_codec && new_track > 0) { | 822 | if (ci.reload_codec && new_track > 0) { |
807 | if (++track_ridx == MAX_TRACK) | 823 | if (++track_ridx == MAX_TRACK) |
808 | track_ridx = 0; | 824 | track_ridx = 0; |
809 | if (track_ridx == track_widx && tracks[track_ridx].filerem == 0) { | 825 | if (tracks[track_ridx].filesize == 0) { |
810 | logf("Loading from disk..."); | 826 | logf("Loading from disk..."); |
811 | new_track = 0; | 827 | new_track = 0; |
812 | queue_post(&audio_queue, AUDIO_PLAY, (void *)(last_offset)); | 828 | queue_post(&audio_queue, AUDIO_PLAY, (void *)(last_offset)); |
@@ -820,7 +836,7 @@ bool codec_request_next_track_callback(void) | |||
820 | track_ridx = MAX_TRACK-1; | 836 | track_ridx = MAX_TRACK-1; |
821 | if (tracks[track_ridx].filesize == 0 || | 837 | if (tracks[track_ridx].filesize == 0 || |
822 | codecbufused+ci.curpos+tracks[track_ridx].filesize | 838 | codecbufused+ci.curpos+tracks[track_ridx].filesize |
823 | + (off_t)tracks[track_ridx].codecsize > codecbuflen) { | 839 | /*+ (off_t)tracks[track_ridx].codecsize*/ > codecbuflen) { |
824 | logf("Loading from disk..."); | 840 | logf("Loading from disk..."); |
825 | last_offset -= track_count; | 841 | last_offset -= track_count; |
826 | if (last_offset < 0) | 842 | if (last_offset < 0) |
@@ -946,7 +962,7 @@ void codec_thread(void) | |||
946 | break ; | 962 | break ; |
947 | } | 963 | } |
948 | codecbufused -=codecsize; | 964 | codecbufused -=codecsize; |
949 | cur_ti->codecsize = 0; | 965 | // cur_ti->codecsize = 0; |
950 | 966 | ||
951 | ci.stop_codec = false; | 967 | ci.stop_codec = false; |
952 | wrap = (int)&codecbuf[codecbuflen] - (int)cur_ti->codecbuf; | 968 | wrap = (int)&codecbuf[codecbuflen] - (int)cur_ti->codecbuf; |
@@ -1136,6 +1152,68 @@ int audio_get_file_pos(void) | |||
1136 | return 0; | 1152 | return 0; |
1137 | } | 1153 | } |
1138 | 1154 | ||
1155 | |||
1156 | /* Copied from mpeg.c. Should be moved somewhere else. */ | ||
1157 | int mp3_get_file_pos(void) | ||
1158 | { | ||
1159 | int pos = -1; | ||
1160 | struct mp3entry *id3 = audio_current_track(); | ||
1161 | |||
1162 | if (id3->vbr) | ||
1163 | { | ||
1164 | if (id3->has_toc) | ||
1165 | { | ||
1166 | /* Use the TOC to find the new position */ | ||
1167 | unsigned int percent, remainder; | ||
1168 | int curtoc, nexttoc, plen; | ||
1169 | |||
1170 | percent = (id3->elapsed*100)/id3->length; | ||
1171 | if (percent > 99) | ||
1172 | percent = 99; | ||
1173 | |||
1174 | curtoc = id3->toc[percent]; | ||
1175 | |||
1176 | if (percent < 99) | ||
1177 | nexttoc = id3->toc[percent+1]; | ||
1178 | else | ||
1179 | nexttoc = 256; | ||
1180 | |||
1181 | pos = (id3->filesize/256)*curtoc; | ||
1182 | |||
1183 | /* Use the remainder to get a more accurate position */ | ||
1184 | remainder = (id3->elapsed*100)%id3->length; | ||
1185 | remainder = (remainder*100)/id3->length; | ||
1186 | plen = (nexttoc - curtoc)*(id3->filesize/256); | ||
1187 | pos += (plen/100)*remainder; | ||
1188 | } | ||
1189 | else | ||
1190 | { | ||
1191 | /* No TOC exists, estimate the new position */ | ||
1192 | pos = (id3->filesize / (id3->length / 1000)) * | ||
1193 | (id3->elapsed / 1000); | ||
1194 | } | ||
1195 | } | ||
1196 | else if (id3->bpf && id3->tpf) | ||
1197 | pos = (id3->elapsed/id3->tpf)*id3->bpf; | ||
1198 | else | ||
1199 | { | ||
1200 | return -1; | ||
1201 | } | ||
1202 | |||
1203 | if (pos >= (int)(id3->filesize - id3->id3v1len)) | ||
1204 | { | ||
1205 | /* Don't seek right to the end of the file so that we can | ||
1206 | transition properly to the next song */ | ||
1207 | pos = id3->filesize - id3->id3v1len - 1; | ||
1208 | } | ||
1209 | else if (pos < (int)id3->first_frame_offset) | ||
1210 | { | ||
1211 | /* skip past id3v2 tag and other leading garbage */ | ||
1212 | pos = id3->first_frame_offset; | ||
1213 | } | ||
1214 | return pos; | ||
1215 | } | ||
1216 | |||
1139 | #ifndef SIMULATOR | 1217 | #ifndef SIMULATOR |
1140 | void audio_set_buffer_margin(int seconds) | 1218 | void audio_set_buffer_margin(int seconds) |
1141 | { | 1219 | { |
@@ -1181,6 +1259,7 @@ void audio_init(void) | |||
1181 | ci.seek_buffer = codec_seek_buffer_callback; | 1259 | ci.seek_buffer = codec_seek_buffer_callback; |
1182 | ci.set_elapsed = codec_set_elapsed_callback; | 1260 | ci.set_elapsed = codec_set_elapsed_callback; |
1183 | 1261 | ||
1262 | queue_init(&audio_queue); | ||
1184 | queue_init(&codec_queue); | 1263 | queue_init(&codec_queue); |
1185 | 1264 | ||
1186 | create_thread(codec_thread, codec_stack, sizeof(codec_stack), | 1265 | create_thread(codec_thread, codec_stack, sizeof(codec_stack), |
diff --git a/apps/plugins/codecvorbis.c b/apps/plugins/codecvorbis.c index 41db223494..2fcc031ce5 100644 --- a/apps/plugins/codecvorbis.c +++ b/apps/plugins/codecvorbis.c | |||
@@ -106,6 +106,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
106 | 106 | ||
107 | /* This function sets up the buffers and reads the file into RAM */ | 107 | /* This function sets up the buffers and reads the file into RAM */ |
108 | 108 | ||
109 | /* We need to flush reserver memory every track load. */ | ||
110 | next_track: | ||
109 | if (codec_init(api, ci)) { | 111 | if (codec_init(api, ci)) { |
110 | return PLUGIN_ERROR; | 112 | return PLUGIN_ERROR; |
111 | } | 113 | } |
@@ -118,7 +120,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parm) | |||
118 | callbacks.tell_func=tell_handler; | 120 | callbacks.tell_func=tell_handler; |
119 | callbacks.close_func=close_handler; | 121 | callbacks.close_func=close_handler; |
120 | 122 | ||
121 | next_track: | ||
122 | error=ov_open_callbacks(ci,&vf,NULL,0,callbacks); | 123 | error=ov_open_callbacks(ci,&vf,NULL,0,callbacks); |
123 | 124 | ||
124 | vi=ov_info(&vf,-1); | 125 | vi=ov_info(&vf,-1); |
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h index f83443b3e9..3c29018394 100644 --- a/firmware/export/pcm_playback.h +++ b/firmware/export/pcm_playback.h | |||
@@ -41,6 +41,7 @@ int pcm_play_num_used_buffers(void); | |||
41 | void pcm_play_set_watermark(int numbytes, void (*callback)(int bytes_left)); | 41 | void pcm_play_set_watermark(int numbytes, void (*callback)(int bytes_left)); |
42 | 42 | ||
43 | void pcm_set_boost_mode(bool state); | 43 | void pcm_set_boost_mode(bool state); |
44 | bool pcm_is_lowdata(void); | ||
44 | unsigned int audiobuffer_get_latency(void); | 45 | unsigned int audiobuffer_get_latency(void); |
45 | bool audiobuffer_insert(char *buf, size_t length); | 46 | bool audiobuffer_insert(char *buf, size_t length); |
46 | 47 | ||
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c index 318cfd4aa0..61573e6602 100644 --- a/firmware/pcm_playback.c +++ b/firmware/pcm_playback.c | |||
@@ -211,8 +211,7 @@ void pcm_play_data(const unsigned char* start, int size, | |||
211 | callback_for_more = get_more; | 211 | callback_for_more = get_more; |
212 | dma_start(start, size); | 212 | dma_start(start, size); |
213 | 213 | ||
214 | if (get_more == pcm_play_callback) | 214 | get_more(&next_start, &next_size); |
215 | get_more(&next_start, &next_size); | ||
216 | } | 215 | } |
217 | 216 | ||
218 | void pcm_play_stop(void) | 217 | void pcm_play_stop(void) |
@@ -256,7 +255,6 @@ void DMA0(void) __attribute__ ((interrupt_handler, section(".icode"))); | |||
256 | void DMA0(void) | 255 | void DMA0(void) |
257 | { | 256 | { |
258 | int res = DSR0; | 257 | int res = DSR0; |
259 | bool rockboy = callback_for_more != pcm_play_callback; | ||
260 | 258 | ||
261 | DSR0 = 1; /* Clear interrupt */ | 259 | DSR0 = 1; /* Clear interrupt */ |
262 | 260 | ||
@@ -267,13 +265,11 @@ void DMA0(void) | |||
267 | } | 265 | } |
268 | else | 266 | else |
269 | { | 267 | { |
270 | if (callback_for_more && rockboy) | ||
271 | callback_for_more(&next_start, &next_size); | ||
272 | if(next_size) | 268 | if(next_size) |
273 | { | 269 | { |
274 | SAR0 = (unsigned long)next_start; /* Source address */ | 270 | SAR0 = (unsigned long)next_start; /* Source address */ |
275 | BCR0 = next_size; /* Bytes to transfer */ | 271 | BCR0 = next_size; /* Bytes to transfer */ |
276 | if (callback_for_more && !rockboy) | 272 | if (callback_for_more) |
277 | callback_for_more(&next_start, &next_size); | 273 | callback_for_more(&next_start, &next_size); |
278 | } | 274 | } |
279 | else | 275 | else |
@@ -366,6 +362,17 @@ unsigned int audiobuffer_get_latency(void) | |||
366 | return latency; | 362 | return latency; |
367 | } | 363 | } |
368 | 364 | ||
365 | bool pcm_is_lowdata(void) | ||
366 | { | ||
367 | if (!pcm_is_playing()) | ||
368 | return false; | ||
369 | |||
370 | if (PCMBUF_SIZE - audiobuffer_free <= PCM_WATERMARK) | ||
371 | return true; | ||
372 | |||
373 | return false; | ||
374 | } | ||
375 | |||
369 | bool audiobuffer_insert(char *buf, size_t length) | 376 | bool audiobuffer_insert(char *buf, size_t length) |
370 | { | 377 | { |
371 | size_t copy_n = 0; | 378 | size_t copy_n = 0; |