diff options
author | Jeffrey Goode <jeffg7@gmail.com> | 2009-11-05 17:32:32 +0000 |
---|---|---|
committer | Jeffrey Goode <jeffg7@gmail.com> | 2009-11-05 17:32:32 +0000 |
commit | 013fe35992c2e735f6f93e51ca26fb6d61dd8c33 (patch) | |
tree | 38da6463deb82c7bd7b15c0fbe226c20dd74d809 | |
parent | 070d515049fab343786b237bc92881f9a28ea688 (diff) | |
download | rockbox-013fe35992c2e735f6f93e51ca26fb6d61dd8c33.tar.gz rockbox-013fe35992c2e735f6f93e51ca26fb6d61dd8c33.zip |
pcmbuf: better latency calculation, added debug code
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23537 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/codec_thread.c | 8 | ||||
-rw-r--r-- | apps/codecs.h | 2 | ||||
-rw-r--r-- | apps/pcmbuf.c | 86 | ||||
-rw-r--r-- | apps/pcmbuf.h | 2 | ||||
-rw-r--r-- | apps/plugins/test_codec.c | 2 |
5 files changed, 70 insertions, 30 deletions
diff --git a/apps/codec_thread.c b/apps/codec_thread.c index affb560183..fbcb23179d 100644 --- a/apps/codec_thread.c +++ b/apps/codec_thread.c | |||
@@ -215,7 +215,7 @@ static bool codec_pcmbuf_insert_callback( | |||
215 | return true; | 215 | return true; |
216 | } /* codec_pcmbuf_insert_callback */ | 216 | } /* codec_pcmbuf_insert_callback */ |
217 | 217 | ||
218 | static void codec_set_elapsed_callback(unsigned int value) | 218 | static void codec_set_elapsed_callback(unsigned long value) |
219 | { | 219 | { |
220 | if (ci.seek_time) | 220 | if (ci.seek_time) |
221 | return; | 221 | return; |
@@ -224,12 +224,12 @@ static void codec_set_elapsed_callback(unsigned int value) | |||
224 | ab_position_report(value); | 224 | ab_position_report(value); |
225 | #endif | 225 | #endif |
226 | 226 | ||
227 | unsigned int latency = pcmbuf_get_latency(); | 227 | unsigned long latency = pcmbuf_get_latency(); |
228 | if (value < latency) | 228 | if (value < latency) |
229 | thistrack_id3->elapsed = 0; | 229 | thistrack_id3->elapsed = 0; |
230 | else | 230 | else |
231 | { | 231 | { |
232 | unsigned int elapsed = value - latency; | 232 | unsigned long elapsed = value - latency; |
233 | if (elapsed > thistrack_id3->elapsed || | 233 | if (elapsed > thistrack_id3->elapsed || |
234 | elapsed < thistrack_id3->elapsed - 2) | 234 | elapsed < thistrack_id3->elapsed - 2) |
235 | { | 235 | { |
@@ -243,7 +243,7 @@ static void codec_set_offset_callback(size_t value) | |||
243 | if (ci.seek_time) | 243 | if (ci.seek_time) |
244 | return; | 244 | return; |
245 | 245 | ||
246 | unsigned int latency = pcmbuf_get_latency() * thistrack_id3->bitrate / 8; | 246 | unsigned long latency = pcmbuf_get_latency() * thistrack_id3->bitrate / 8; |
247 | if (value < latency) | 247 | if (value < latency) |
248 | thistrack_id3->offset = 0; | 248 | thistrack_id3->offset = 0; |
249 | else | 249 | else |
diff --git a/apps/codecs.h b/apps/codecs.h index b61c3c0c94..39a8457666 100644 --- a/apps/codecs.h +++ b/apps/codecs.h | |||
@@ -123,7 +123,7 @@ struct codec_api { | |||
123 | automatically. */ | 123 | automatically. */ |
124 | bool (*pcmbuf_insert)(const void *ch1, const void *ch2, int count); | 124 | bool (*pcmbuf_insert)(const void *ch1, const void *ch2, int count); |
125 | /* Set song position in WPS (value in ms). */ | 125 | /* Set song position in WPS (value in ms). */ |
126 | void (*set_elapsed)(unsigned int value); | 126 | void (*set_elapsed)(unsigned long value); |
127 | 127 | ||
128 | /* Read next <size> amount bytes from file buffer to <ptr>. | 128 | /* Read next <size> amount bytes from file buffer to <ptr>. |
129 | Will return number of bytes read or 0 if end of file. */ | 129 | Will return number of bytes read or 0 if end of file. */ |
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index 3b461ecdc1..c8f89d9af9 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -136,6 +136,45 @@ static void pcmbuf_under_watermark(bool under); | |||
136 | static bool pcmbuf_flush_fillpos(void); | 136 | static bool pcmbuf_flush_fillpos(void); |
137 | 137 | ||
138 | 138 | ||
139 | /**************************************/ | ||
140 | |||
141 | /* define this to show detailed pcmbufdesc usage information on the sim console */ | ||
142 | /*#define DESC_DEBUG*/ | ||
143 | |||
144 | #ifndef SIMULATOR | ||
145 | #undef DESC_DEBUG | ||
146 | #endif | ||
147 | #ifdef DESC_DEBUG | ||
148 | static struct pcmbufdesc *first_desc; | ||
149 | static bool show_desc_in_use = false; | ||
150 | #define DISPLAY_DESC(caller) while(!show_desc(caller)) | ||
151 | #define DESC_IDX(desc) (desc ? desc - first_desc : -1) | ||
152 | #define DESCL_IDX(desc) (desc && desc->link ? desc->link - first_desc : -1) | ||
153 | #define SHOW_1ST(desc) if(DESC_IDX (desc)==-1) DEBUGF(" -- "); \ | ||
154 | else DEBUGF(" %02d ", DESC_IDX(desc)) | ||
155 | #define SHOW_2ND(desc) if(DESCL_IDX(desc)==-1) DEBUGF("l -- "); \ | ||
156 | else DEBUGF("l %02d ", DESCL_IDX(desc)) | ||
157 | #define DESC_SHOW(tag, desc) DEBUGF(tag);SHOW_1ST(desc); \ | ||
158 | DEBUGF(tag);SHOW_2ND(desc) | ||
159 | |||
160 | static bool show_desc(char *caller) | ||
161 | { | ||
162 | if (show_desc_in_use) return false; | ||
163 | show_desc_in_use = true; | ||
164 | DEBUGF("%-14s\t", caller); | ||
165 | DESC_SHOW("r", pcmbuf_read); | ||
166 | DESC_SHOW("re", pcmbuf_read_end); | ||
167 | DEBUGF(" "); | ||
168 | DESC_SHOW("w", pcmbuf_write); | ||
169 | DESC_SHOW("we", pcmbuf_write_end); | ||
170 | DEBUGF("\n"); | ||
171 | show_desc_in_use = false; | ||
172 | return true; | ||
173 | } | ||
174 | #else | ||
175 | #define DISPLAY_DESC(caller) do{}while(0) | ||
176 | #endif | ||
177 | |||
139 | /* Track change functions */ | 178 | /* Track change functions */ |
140 | 179 | ||
141 | /* The codec is moving on to the next track, but the current track is | 180 | /* The codec is moving on to the next track, but the current track is |
@@ -232,6 +271,7 @@ static void pcmbuf_pcm_callback(unsigned char** start, size_t* size) | |||
232 | pcmbuf_finish_track_change(); | 271 | pcmbuf_finish_track_change(); |
233 | } | 272 | } |
234 | } | 273 | } |
274 | DISPLAY_DESC("callback"); | ||
235 | } | 275 | } |
236 | 276 | ||
237 | static void pcmbuf_set_watermark_bytes(void) | 277 | static void pcmbuf_set_watermark_bytes(void) |
@@ -287,6 +327,7 @@ static inline void pcmbuf_add_chunk(void) | |||
287 | audiobuffer_pos -= pcmbuf_size; | 327 | audiobuffer_pos -= pcmbuf_size; |
288 | 328 | ||
289 | audiobuffer_fillpos = 0; | 329 | audiobuffer_fillpos = 0; |
330 | DISPLAY_DESC("add_chunk"); | ||
290 | } | 331 | } |
291 | 332 | ||
292 | #ifdef HAVE_PRIORITY_SCHEDULING | 333 | #ifdef HAVE_PRIORITY_SCHEDULING |
@@ -348,11 +389,11 @@ static void pcmbuf_under_watermark(bool under) | |||
348 | } | 389 | } |
349 | } | 390 | } |
350 | 391 | ||
351 | unsigned int pcmbuf_get_latency(void) | 392 | unsigned long pcmbuf_get_latency(void) |
352 | { | 393 | { |
353 | /* Be careful how this calculation is rearranged, it's easy to overflow */ | 394 | /* Be careful how this calculation is rearranged, it's easy to overflow */ |
354 | size_t bytes = pcmbuf_unplayed_bytes + pcm_get_bytes_waiting(); | 395 | size_t bytes = pcmbuf_unplayed_bytes + pcm_get_bytes_waiting(); |
355 | return bytes / 4 / (NATIVE_FREQUENCY/1000); | 396 | return bytes / 4 * 1000 / NATIVE_FREQUENCY; |
356 | } | 397 | } |
357 | 398 | ||
358 | void pcmbuf_set_low_latency(bool state) | 399 | void pcmbuf_set_low_latency(bool state) |
@@ -437,6 +478,7 @@ void pcmbuf_play_stop(void) | |||
437 | crossfade_init = false; | 478 | crossfade_init = false; |
438 | crossfade_active = false; | 479 | crossfade_active = false; |
439 | pcmbuf_flush = false; | 480 | pcmbuf_flush = false; |
481 | DISPLAY_DESC("play_stop"); | ||
440 | 482 | ||
441 | #ifdef HAVE_PRIORITY_SCHEDULING | 483 | #ifdef HAVE_PRIORITY_SCHEDULING |
442 | /* Can unboost the codec thread here no matter who's calling */ | 484 | /* Can unboost the codec thread here no matter who's calling */ |
@@ -462,6 +504,9 @@ int pcmbuf_descs(void) | |||
462 | 504 | ||
463 | static void pcmbuf_init_pcmbuffers(void) | 505 | static void pcmbuf_init_pcmbuffers(void) |
464 | { | 506 | { |
507 | #ifdef DESC_DEBUG | ||
508 | first_desc = pcmbuf_write; | ||
509 | #endif | ||
465 | struct pcmbufdesc *next = pcmbuf_write; | 510 | struct pcmbufdesc *next = pcmbuf_write; |
466 | next++; | 511 | next++; |
467 | pcmbuf_write_end = pcmbuf_write; | 512 | pcmbuf_write_end = pcmbuf_write; |
@@ -470,6 +515,7 @@ static void pcmbuf_init_pcmbuffers(void) | |||
470 | pcmbuf_write_end=next; | 515 | pcmbuf_write_end=next; |
471 | next++; | 516 | next++; |
472 | } | 517 | } |
518 | DISPLAY_DESC("init"); | ||
473 | } | 519 | } |
474 | 520 | ||
475 | static size_t pcmbuf_get_next_required_pcmbuf_size(void) | 521 | static size_t pcmbuf_get_next_required_pcmbuf_size(void) |
@@ -755,24 +801,6 @@ static size_t crossfade_mix(int factor, const char *buf, size_t length) | |||
755 | return 0; | 801 | return 0; |
756 | } | 802 | } |
757 | 803 | ||
758 | static void pcmbuf_flush_buffer(const char *buf, size_t length) | ||
759 | { | ||
760 | size_t copy_n; | ||
761 | while (length > 0) { | ||
762 | size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; | ||
763 | if (NEED_FLUSH(audiobuffer_index)) | ||
764 | { | ||
765 | pcmbuf_flush_fillpos(); | ||
766 | audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; | ||
767 | } | ||
768 | copy_n = MIN(length, pcmbuf_size - audiobuffer_index); | ||
769 | memcpy(&audiobuffer[audiobuffer_index], buf, copy_n); | ||
770 | buf += copy_n; | ||
771 | audiobuffer_fillpos += copy_n; | ||
772 | length -= copy_n; | ||
773 | } | ||
774 | } | ||
775 | |||
776 | static void flush_crossfade(char *buf, size_t length) | 804 | static void flush_crossfade(char *buf, size_t length) |
777 | { | 805 | { |
778 | if (length) | 806 | if (length) |
@@ -826,11 +854,23 @@ static void flush_crossfade(char *buf, size_t length) | |||
826 | /* Flush samples to the buffer */ | 854 | /* Flush samples to the buffer */ |
827 | while (!prepare_insert(length)) | 855 | while (!prepare_insert(length)) |
828 | sleep(1); | 856 | sleep(1); |
829 | pcmbuf_flush_buffer(buf, length); | 857 | while (length > 0) |
858 | { | ||
859 | size_t audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; | ||
860 | if (NEED_FLUSH(audiobuffer_index)) | ||
861 | { | ||
862 | pcmbuf_flush_fillpos(); | ||
863 | audiobuffer_index = audiobuffer_pos + audiobuffer_fillpos; | ||
864 | } | ||
865 | size_t copy_n = MIN(length, pcmbuf_size - audiobuffer_index); | ||
866 | memcpy(&audiobuffer[audiobuffer_index], buf, copy_n); | ||
867 | buf += copy_n; | ||
868 | audiobuffer_fillpos += copy_n; | ||
869 | length -= copy_n; | ||
870 | } | ||
830 | } | 871 | } |
831 | |||
832 | } | 872 | } |
833 | #endif | 873 | #endif /* HAVE_CROSSFADE */ |
834 | 874 | ||
835 | static bool prepare_insert(size_t length) | 875 | static bool prepare_insert(size_t length) |
836 | { | 876 | { |
diff --git a/apps/pcmbuf.h b/apps/pcmbuf.h index b6f0c767f2..1d893f9c62 100644 --- a/apps/pcmbuf.h +++ b/apps/pcmbuf.h | |||
@@ -59,7 +59,7 @@ void pcmbuf_play_start(void); | |||
59 | bool pcmbuf_crossfade_init(bool manual_skip); | 59 | bool pcmbuf_crossfade_init(bool manual_skip); |
60 | void pcmbuf_start_track_change(void); | 60 | void pcmbuf_start_track_change(void); |
61 | size_t pcmbuf_free(void); | 61 | size_t pcmbuf_free(void); |
62 | unsigned int pcmbuf_get_latency(void); | 62 | unsigned long pcmbuf_get_latency(void); |
63 | void pcmbuf_set_low_latency(bool state); | 63 | void pcmbuf_set_low_latency(bool state); |
64 | void * pcmbuf_request_buffer(int *count); | 64 | void * pcmbuf_request_buffer(int *count); |
65 | void pcmbuf_write_complete(int count); | 65 | void pcmbuf_write_complete(int count); |
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index b41f053571..465030d7fc 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c | |||
@@ -363,7 +363,7 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | |||
363 | } | 363 | } |
364 | 364 | ||
365 | /* Set song position in WPS (value in ms). */ | 365 | /* Set song position in WPS (value in ms). */ |
366 | static void set_elapsed(unsigned int value) | 366 | static void set_elapsed(unsigned long value) |
367 | { | 367 | { |
368 | elapsed = value; | 368 | elapsed = value; |
369 | } | 369 | } |