summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-03-02 04:41:29 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-03-02 04:41:29 +0000
commit64647f34036684d2d69c525460ee6a6409f2a31f (patch)
tree9fe6595dea8581e760e91b46988545c95d070158
parentb3bfc09852007fed60bf71451a6c71df8c28b3ed (diff)
downloadrockbox-64647f34036684d2d69c525460ee6a6409f2a31f.tar.gz
rockbox-64647f34036684d2d69c525460ee6a6409f2a31f.zip
buffering: Unusual cases when a handle ridx is briefly seeked ahead of widx need to be handled properly. In the best case, buffer useful would be wrong and in the worst, a packet audio move_handle delta would be quite incorrect, causing the handle to be moved too far.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29490 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/buffering.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/apps/buffering.c b/apps/buffering.c
index 54c6c05baa..2f6623a936 100644
--- a/apps/buffering.c
+++ b/apps/buffering.c
@@ -560,6 +560,17 @@ fill_buffer : Call buffer_handle for all handles that have data to buffer
560 560
561These functions are used by the buffering thread to manage buffer space. 561These functions are used by the buffering thread to manage buffer space.
562*/ 562*/
563static size_t handle_size_available(const struct memory_handle *h)
564{
565 /* Obtain proper distances from data start */
566 size_t rd = ringbuf_sub(h->ridx, h->data);
567 size_t wr = ringbuf_sub(h->widx, h->data);
568
569 if (LIKELY(wr > rd))
570 return wr - rd;
571
572 return 0; /* ridx is ahead of or equal to widx at this time */
573}
563 574
564static void update_data_counters(struct data_counters *dc) 575static void update_data_counters(struct data_counters *dc)
565{ 576{
@@ -582,6 +593,8 @@ static void update_data_counters(struct data_counters *dc)
582 m = first_handle; 593 m = first_handle;
583 while (m) { 594 while (m) {
584 buffered += m->available; 595 buffered += m->available;
596 /* wasted could come out larger than the buffer size if ridx's are
597 overlapping data ahead of their handles' buffered data */
585 wasted += ringbuf_sub(m->ridx, m->data); 598 wasted += ringbuf_sub(m->ridx, m->data);
586 remaining += m->filerem; 599 remaining += m->filerem;
587 600
@@ -589,7 +602,7 @@ static void update_data_counters(struct data_counters *dc)
589 is_useful = true; 602 is_useful = true;
590 603
591 if (is_useful) 604 if (is_useful)
592 useful += ringbuf_sub(m->widx, m->ridx); 605 useful += handle_size_available(m);
593 606
594 m = m->next; 607 m = m->next;
595 } 608 }
@@ -795,7 +808,11 @@ static void shrink_handle(struct memory_handle *h)
795 } 808 }
796 } else { 809 } else {
797 /* only move the handle struct */ 810 /* only move the handle struct */
798 delta = ringbuf_sub(h->ridx, h->data); 811 size_t rd = ringbuf_sub(h->ridx, h->data);
812 size_t wr = ringbuf_sub(h->widx, h->data);
813
814 /* ridx could be ahead of widx on a mini rebuffer */
815 delta = MIN(rd, wr);
799 if (!move_handle(&h, &delta, 0, true)) 816 if (!move_handle(&h, &delta, 0, true))
800 return; 817 return;
801 818
@@ -1245,18 +1262,6 @@ int bufadvance(int handle_id, off_t offset)
1245 * actual amount of data available for reading. This function explicitly 1262 * actual amount of data available for reading. This function explicitly
1246 * does not check the validity of the input handle. It does do range checks 1263 * does not check the validity of the input handle. It does do range checks
1247 * on size and returns a valid (and explicit) amount of data for reading */ 1264 * on size and returns a valid (and explicit) amount of data for reading */
1248static size_t handle_size_available(const struct memory_handle *h)
1249{
1250 /* Obtain proper distances from data start */
1251 size_t rd = ringbuf_sub(h->ridx, h->data);
1252 size_t wr = ringbuf_sub(h->widx, h->data);
1253
1254 if (LIKELY(wr > rd))
1255 return wr - rd;
1256
1257 return 0; /* ridx is ahead of or equal to widx at this time */
1258}
1259
1260static struct memory_handle *prep_bufdata(int handle_id, size_t *size, 1265static struct memory_handle *prep_bufdata(int handle_id, size_t *size,
1261 bool guardbuf_limit) 1266 bool guardbuf_limit)
1262{ 1267{