From: Lennart Poettering Date: Mon, 1 Oct 2007 16:41:50 +0000 (+0000) Subject: Move request size handling into pa_memblockq, function pa_memblockq_pop_missing() X-Git-Url: https://code.delx.au/pulseaudio/commitdiff_plain/2e780e88c219fdd63f8b0f4c835c7d0500b88910 Move request size handling into pa_memblockq, function pa_memblockq_pop_missing() git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1923 fefdeb5f-60dc-0310-8127-8f9354f1896f --- diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index ecdf45b6..a46155a9 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -47,15 +47,17 @@ struct list_item { }; PA_STATIC_FLIST_DECLARE(list_items, 0, pa_xfree); - + struct pa_memblockq { struct list_item *blocks, *blocks_tail; unsigned n_blocks; size_t maxlength, tlength, base, prebuf, minreq; int64_t read_index, write_index; - int in_prebuf; + pa_bool_t in_prebuf; pa_memblock *silence; pa_mcalign *mcalign; + int64_t missing; + size_t requested; }; pa_memblockq* pa_memblockq_new( @@ -109,6 +111,9 @@ pa_memblockq* pa_memblockq_new( bq->silence = silence ? pa_memblock_ref(silence) : NULL; bq->mcalign = NULL; + bq->missing = bq->tlength; + bq->requested = 0; + return bq; } @@ -116,7 +121,7 @@ void pa_memblockq_free(pa_memblockq* bq) { pa_assert(bq); pa_memblockq_flush(bq); - + if (bq->silence) pa_memblock_unref(bq->silence); @@ -150,7 +155,7 @@ static void drop_block(pa_memblockq *bq, struct list_item *q) { bq->n_blocks--; } -static int can_push(pa_memblockq *bq, size_t l) { +static pa_bool_t can_push(pa_memblockq *bq, size_t l) { int64_t end; pa_assert(bq); @@ -161,7 +166,7 @@ static int can_push(pa_memblockq *bq, size_t l) { if (l > d) l -= d; else - return 1; + return TRUE; } end = bq->blocks_tail ? bq->blocks_tail->index + bq->blocks_tail->chunk.length : 0; @@ -169,15 +174,15 @@ static int can_push(pa_memblockq *bq, size_t l) { /* Make sure that the list doesn't get too long */ if (bq->write_index + (int64_t)l > end) if (bq->write_index + l - bq->read_index > bq->maxlength) - return 0; + return FALSE; - return 1; + return TRUE; } int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { - struct list_item *q, *n; pa_memchunk chunk; + int64_t old, delta; pa_assert(bq); pa_assert(uchunk); @@ -191,6 +196,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { if (!can_push(bq, uchunk->length)) return -1; + old = bq->write_index; chunk = *uchunk; if (bq->read_index > bq->write_index) { @@ -207,7 +213,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { } else { /* We drop the incoming data completely */ bq->write_index += chunk.length; - return 0; + goto finish; } } @@ -245,7 +251,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { /* Create a new list entry for the end of thie memchunk */ if (!(p = pa_flist_pop(PA_STATIC_FLIST_GET(list_items)))) p = pa_xnew(struct list_item, 1); - + p->chunk = q->chunk; pa_memblock_ref(p->chunk.memblock); @@ -308,15 +314,14 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { q->chunk.length += chunk.length; bq->write_index += chunk.length; - return 0; + goto finish; } } else pa_assert(!bq->blocks || (bq->write_index + (int64_t)chunk.length <= bq->blocks->index)); - if (!(n = pa_flist_pop(PA_STATIC_FLIST_GET(list_items)))) n = pa_xnew(struct list_item, 1); - + n->chunk = chunk; pa_memblock_ref(n->chunk.memblock); n->index = bq->write_index; @@ -336,27 +341,42 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) { bq->blocks = n; bq->n_blocks++; + +finish: + + delta = bq->write_index - old; + + if (delta >= bq->requested) { + delta -= bq->requested; + bq->requested = 0; + } else { + bq->requested -= delta; + delta = 0; + } + + bq->missing -= delta; + return 0; } -static int memblockq_check_prebuf(pa_memblockq *bq) { +static pa_bool_t memblockq_check_prebuf(pa_memblockq *bq) { pa_assert(bq); - + if (bq->in_prebuf) { - + if (pa_memblockq_get_length(bq) < bq->prebuf) - return 1; + return TRUE; - bq->in_prebuf = 0; - return 0; + bq->in_prebuf = FALSE; + return FALSE; } else { if (bq->prebuf > 0 && bq->read_index >= bq->write_index) { - bq->in_prebuf = 1; - return 1; + bq->in_prebuf = TRUE; + return TRUE; } - return 0; + return FALSE; } } @@ -409,15 +429,18 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) { } void pa_memblockq_drop(pa_memblockq *bq, size_t length) { + int64_t old, delta; pa_assert(bq); pa_assert(length % bq->base == 0); - + + old = bq->read_index; + while (length > 0) { /* Do not drop any data when we are in prebuffering mode */ if (memblockq_check_prebuf(bq)) break; - + if (bq->blocks) { size_t d; @@ -462,6 +485,9 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) { break; } } + + delta = bq->read_index - old; + bq->missing += delta; } int pa_memblockq_is_readable(pa_memblockq *bq) { @@ -493,6 +519,7 @@ size_t pa_memblockq_missing(pa_memblockq *bq) { return 0; l = bq->tlength - l; + return l >= bq->minreq ? l : 0; } @@ -503,27 +530,43 @@ size_t pa_memblockq_get_minreq(pa_memblockq *bq) { } void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { + int64_t old, delta; pa_assert(bq); + old = bq->write_index; + switch (seek) { case PA_SEEK_RELATIVE: bq->write_index += offset; - return; + break; case PA_SEEK_ABSOLUTE: bq->write_index = offset; - return; + break; case PA_SEEK_RELATIVE_ON_READ: bq->write_index = bq->read_index + offset; - return; + break; case PA_SEEK_RELATIVE_END: bq->write_index = (bq->blocks_tail ? bq->blocks_tail->index + (int64_t) bq->blocks_tail->chunk.length : bq->read_index) + offset; - return; + break; + default: + pa_assert_not_reached(); } - pa_assert_not_reached(); + delta = bq->write_index - old; + + if (delta >= bq->requested) { + delta -= bq->requested; + bq->requested = 0; + } else if (delta >= 0) { + bq->requested -= delta; + delta = 0; + } + + bq->missing -= delta; } void pa_memblockq_flush(pa_memblockq *bq) { + int64_t old, delta; pa_assert(bq); while (bq->blocks) @@ -531,9 +574,22 @@ void pa_memblockq_flush(pa_memblockq *bq) { pa_assert(bq->n_blocks == 0); + old = bq->write_index; bq->write_index = bq->read_index; pa_memblockq_prebuf_force(bq); + + delta = bq->write_index - old; + + if (delta > bq->requested) { + delta -= bq->requested; + bq->requested = 0; + } else if (delta >= 0) { + bq->requested -= delta; + delta = 0; + } + + bq->missing -= delta; } size_t pa_memblockq_get_tlength(pa_memblockq *bq) { @@ -594,14 +650,14 @@ void pa_memblockq_shorten(pa_memblockq *bq, size_t length) { void pa_memblockq_prebuf_disable(pa_memblockq *bq) { pa_assert(bq); - bq->in_prebuf = 0; + bq->in_prebuf = FALSE; } void pa_memblockq_prebuf_force(pa_memblockq *bq) { pa_assert(bq); if (!bq->in_prebuf && bq->prebuf > 0) - bq->in_prebuf = 1; + bq->in_prebuf = TRUE; } size_t pa_memblockq_get_maxlength(pa_memblockq *bq) { @@ -615,3 +671,20 @@ size_t pa_memblockq_get_prebuf(pa_memblockq *bq) { return bq->prebuf; } + +size_t pa_memblockq_pop_missing(pa_memblockq *bq) { + size_t l; + + pa_assert(bq); + +/* pa_log("pop: %lli", bq->missing); */ + + if (bq->missing <= 0) + return 0; + + l = (size_t) bq->missing; + bq->missing = 0; + bq->requested += l; + + return l; +} diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index 5eb23aac..8c3e70fc 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -103,6 +103,10 @@ size_t pa_memblockq_get_length(pa_memblockq *bq); /* Return how many bytes are missing in queue to the specified fill amount */ size_t pa_memblockq_missing(pa_memblockq *bq); +/* Return the number of bytes that are missing since the last call to + * this function, reset the internal counter to 0. */ +size_t pa_memblockq_pop_missing(pa_memblockq *bq); + /* Returns the minimal request value */ size_t pa_memblockq_get_minreq(pa_memblockq *bq);