From 373b5efe51238b0ad34cb9a9d8fc61b973afdad8 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 1 Apr 2009 23:05:09 +0200 Subject: properly account for seeks in the requested_bytes counter --- src/pulsecore/memblockq.c | 18 ++++++++++-------- src/pulsecore/memblockq.h | 2 +- src/pulsecore/protocol-native.c | 29 ++++++++++++++++------------- src/pulsecore/sink-input.c | 4 ++-- src/pulsecore/source-output.c | 2 +- 5 files changed, 30 insertions(+), 25 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c index e6e7b736..d12d13a8 100644 --- a/src/pulsecore/memblockq.c +++ b/src/pulsecore/memblockq.c @@ -601,7 +601,7 @@ size_t pa_memblockq_missing(pa_memblockq *bq) { return l >= bq->minreq ? l : 0; } -void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { +void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa_bool_t account) { int64_t old, delta; pa_assert(bq); @@ -628,12 +628,14 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek) { delta = bq->write_index - old; - if (delta >= (int64_t) bq->requested) { - delta -= (int64_t) bq->requested; - bq->requested = 0; - } else if (delta >= 0) { - bq->requested -= (size_t) delta; - delta = 0; + if (account) { + if (delta >= (int64_t) bq->requested) { + delta -= (int64_t) bq->requested; + bq->requested = 0; + } else if (delta >= 0) { + bq->requested -= (size_t) delta; + delta = 0; + } } bq->missing -= delta; @@ -895,7 +897,7 @@ int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source) { pa_memblock_unref(chunk.memblock); } else - pa_memblockq_seek(bq, (int64_t) chunk.length, PA_SEEK_RELATIVE); + pa_memblockq_seek(bq, (int64_t) chunk.length, PA_SEEK_RELATIVE, TRUE); pa_memblockq_drop(bq, chunk.length); } diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h index e315b831..146d261b 100644 --- a/src/pulsecore/memblockq.h +++ b/src/pulsecore/memblockq.h @@ -85,7 +85,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *chunk); int pa_memblockq_push_align(pa_memblockq* bq, const pa_memchunk *chunk); /* Manipulate the write pointer */ -void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek); +void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa_bool_t account); /* Return a copy of the next memory chunk in the queue. It is not * removed from the queue. There are two reasons this function might diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index e11d7a6c..30d68f35 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -738,24 +738,21 @@ static int playback_stream_process_msg(pa_msgobject *o, int code, void*userdata, switch (code) { case PLAYBACK_STREAM_MESSAGE_REQUEST_DATA: { pa_tagstruct *t; - uint32_t l = 0; + int l = 0; for (;;) { - if ((l = (uint32_t) pa_atomic_load(&s->missing)) <= 0) - break; + if ((l = pa_atomic_load(&s->missing)) <= 0) + return 0; - if (pa_atomic_cmpxchg(&s->missing, (int) l, 0)) + if (pa_atomic_cmpxchg(&s->missing, l, 0)) break; } - if (l <= 0) - break; - t = pa_tagstruct_new(NULL, 0); pa_tagstruct_putu32(t, PA_COMMAND_REQUEST); pa_tagstruct_putu32(t, (uint32_t) -1); /* tag */ pa_tagstruct_putu32(t, s->index); - pa_tagstruct_putu32(t, l); + pa_tagstruct_putu32(t, (uint32_t) l); pa_pstream_send_tagstruct(s->connection->pstream, t); /* pa_log("Requesting %lu bytes", (unsigned long) l); */ @@ -1097,7 +1094,8 @@ static playback_stream* playback_stream_new( /* Called from IO context */ static void playback_stream_request_bytes(playback_stream *s) { - size_t m, previous_missing, minreq; + size_t m, minreq; + int previous_missing; playback_stream_assert_ref(s); @@ -1108,11 +1106,11 @@ static void playback_stream_request_bytes(playback_stream *s) { /* pa_log("request_bytes(%lu)", (unsigned long) m); */ - previous_missing = (size_t) pa_atomic_add(&s->missing, (int) m); + previous_missing = pa_atomic_add(&s->missing, (int) m); minreq = pa_memblockq_get_minreq(s->memblockq); if (pa_memblockq_prebuf_active(s->memblockq) || - (previous_missing < minreq && previous_missing+m >= minreq)) + (previous_missing < (int) minreq && previous_missing + (int) m >= (int) minreq)) pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_REQUEST_DATA, NULL, 0, NULL, NULL); } @@ -1297,7 +1295,12 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int int64_t windex; windex = pa_memblockq_get_write_index(s->memblockq); - pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata)); + + /* The client side is incapable of accounting correctly + * for seeks of a type != PA_SEEK_RELATIVE. We need to be + * able to deal with that. */ + + pa_memblockq_seek(s->memblockq, offset, PA_PTR_TO_UINT(userdata), PA_PTR_TO_UINT(userdata) == PA_SEEK_RELATIVE); handle_seek(s, windex); return 0; @@ -1315,7 +1318,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int if (pa_memblockq_push_align(s->memblockq, chunk) < 0) { pa_log_warn("Failed to push data into queue"); pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_OVERFLOW, NULL, 0, NULL, NULL); - pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE); + pa_memblockq_seek(s->memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE); } handle_seek(s, windex); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 0ed16dd8..1fdb3fa6 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -631,7 +631,7 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, p * data, so let's just hand out silence */ pa_atomic_store(&i->thread_info.drained, 1); - pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE); + pa_memblockq_seek(i->thread_info.render_memblockq, (int64_t) slength, PA_SEEK_RELATIVE, TRUE); i->thread_info.playing_for = 0; if (i->thread_info.underrun_for != (uint64_t) -1) i->thread_info.underrun_for += ilength; @@ -776,7 +776,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam if (amount > 0) /* Ok, now update the write pointer */ - pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE); + pa_memblockq_seek(i->thread_info.render_memblockq, - ((int64_t) amount), PA_SEEK_RELATIVE, TRUE); if (i->thread_info.rewrite_flush) pa_memblockq_silence(i->thread_info.render_memblockq); diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 27f24cd1..1c37be93 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -434,7 +434,7 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { if (pa_memblockq_push(o->thread_info.delay_memblockq, chunk) < 0) { pa_log_debug("Delay queue overflow!"); - pa_memblockq_seek(o->thread_info.delay_memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE); + pa_memblockq_seek(o->thread_info.delay_memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE); } limit = o->process_rewind ? 0 : o->source->thread_info.max_rewind; -- cgit