Make sure we don't get stuck when prebuf is too high
authorLennart Poettering <lennart@poettering.net>
Mon, 6 Apr 2009 20:09:38 +0000 (22:09 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 6 Apr 2009 20:13:41 +0000 (22:13 +0200)
If prebuf is greater than tlength minus minreq we might end up waiting
for the buffer to fill up further however without ever asking for more
data from the client since less minreq bytes might be missing.

This fixes bug #440

src/pulsecore/memblockq.c
src/pulsecore/protocol-native.c

index d12d13a..77f9efc 100644 (file)
@@ -90,8 +90,8 @@ pa_memblockq* pa_memblockq_new(
 
     pa_memblockq_set_maxlength(bq, maxlength);
     pa_memblockq_set_tlength(bq, tlength);
-    pa_memblockq_set_prebuf(bq, prebuf);
     pa_memblockq_set_minreq(bq, minreq);
+    pa_memblockq_set_prebuf(bq, prebuf);
     pa_memblockq_set_maxrewind(bq, maxrewind);
 
     pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
@@ -784,16 +784,13 @@ void pa_memblockq_set_maxlength(pa_memblockq *bq, size_t maxlength) {
 
     if (bq->tlength > bq->maxlength)
         pa_memblockq_set_tlength(bq, bq->maxlength);
-
-    if (bq->prebuf > bq->maxlength)
-        pa_memblockq_set_prebuf(bq, bq->maxlength);
 }
 
 void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
     size_t old_tlength;
     pa_assert(bq);
 
-    if (tlength <= 0)
+    if (tlength <= 0 || tlength == (size_t) -1)
         tlength = bq->maxlength;
 
     old_tlength = bq->tlength;
@@ -802,49 +799,46 @@ void pa_memblockq_set_tlength(pa_memblockq *bq, size_t tlength) {
     if (bq->tlength > bq->maxlength)
         bq->tlength = bq->maxlength;
 
-    if (bq->prebuf > bq->tlength)
-        pa_memblockq_set_prebuf(bq, bq->tlength);
-
     if (bq->minreq > bq->tlength)
         pa_memblockq_set_minreq(bq, bq->tlength);
 
+    if (bq->prebuf > bq->tlength+bq->base-bq->minreq)
+        pa_memblockq_set_prebuf(bq, bq->tlength+bq->base-bq->minreq);
+
     bq->missing += (int64_t) bq->tlength - (int64_t) old_tlength;
 }
 
+void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) {
+    pa_assert(bq);
+
+    bq->minreq = (minreq/bq->base)*bq->base;
+
+    if (bq->minreq > bq->tlength)
+        bq->minreq = bq->tlength;
+
+    if (bq->minreq < bq->base)
+        bq->minreq = bq->base;
+
+    if (bq->prebuf > bq->tlength+bq->base-bq->minreq)
+        pa_memblockq_set_prebuf(bq, bq->tlength+bq->base-bq->minreq);
+}
+
 void pa_memblockq_set_prebuf(pa_memblockq *bq, size_t prebuf) {
     pa_assert(bq);
 
     if (prebuf == (size_t) -1)
-        prebuf = bq->tlength;
+        prebuf = bq->tlength+bq->base-bq->minreq;
 
     bq->prebuf = ((prebuf+bq->base-1)/bq->base)*bq->base;
 
     if (prebuf > 0 && bq->prebuf < bq->base)
         bq->prebuf = bq->base;
 
-    if (bq->prebuf > bq->tlength)
-        bq->prebuf = bq->tlength;
+    if (bq->prebuf > bq->tlength+bq->base-bq->minreq)
+        bq->prebuf = bq->tlength+bq->base-bq->minreq;
 
     if (bq->prebuf <= 0 || pa_memblockq_get_length(bq) >= bq->prebuf)
         bq->in_prebuf = FALSE;
-
-    if (bq->minreq > bq->prebuf)
-        pa_memblockq_set_minreq(bq, bq->prebuf);
-}
-
-void pa_memblockq_set_minreq(pa_memblockq *bq, size_t minreq) {
-    pa_assert(bq);
-
-    bq->minreq = (minreq/bq->base)*bq->base;
-
-    if (bq->minreq > bq->tlength)
-        bq->minreq = bq->tlength;
-
-    if (bq->minreq > bq->prebuf)
-        bq->minreq = bq->prebuf;
-
-    if (bq->minreq < bq->base)
-        bq->minreq = bq->base;
 }
 
 void pa_memblockq_set_maxrewind(pa_memblockq *bq, size_t maxrewind) {
index 59e5d80..edcd598 100644 (file)
@@ -850,7 +850,7 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata,
 
 /* Called from main context */
 static void fix_playback_buffer_attr(playback_stream *s) {
-    size_t frame_size;
+    size_t frame_size, max_prebuf;
     pa_usec_t orig_tlength_usec, tlength_usec, orig_minreq_usec, minreq_usec, sink_usec;
 
     pa_assert(s);
@@ -976,8 +976,11 @@ static void fix_playback_buffer_attr(playback_stream *s) {
     if (s->buffer_attr.tlength <= s->buffer_attr.minreq)
         s->buffer_attr.tlength = s->buffer_attr.minreq*2 + (uint32_t) frame_size;
 
-    if (s->buffer_attr.prebuf == (uint32_t) -1 || s->buffer_attr.prebuf > s->buffer_attr.tlength)
-        s->buffer_attr.prebuf = s->buffer_attr.tlength;
+    max_prebuf = s->buffer_attr.tlength + (uint32_t)frame_size - s->buffer_attr.minreq;
+
+    if (s->buffer_attr.prebuf == (uint32_t) -1 ||
+        s->buffer_attr.prebuf > max_prebuf)
+        s->buffer_attr.prebuf = max_prebuf;
 }
 
 /* Called from main context */