[pulseaudio-discuss] [PATCH] Third draft implementation of better drain reporting
Tanu Kaskinen
tanuk at iki.fi
Mon Mar 18 13:23:42 PDT 2013
On Mon, 2013-03-18 at 13:32 +0100, David Henningsson wrote:
> Ok, so using sink_input->render_memblockq.max_rewind looked like a good idea, but in
> fact it does not work with early requests, which alsa-plugins use.
> I haven't found any drawback from skipping this check, and it actually makes the patch simpler, too.
>
> I've tested it now with both aplay and paplay (and both in parallel!) and it seems to work.
> Anybody else who wants to run it for a test?
>
> Signed-off-by: David Henningsson <david.henningsson at canonical.com>
> ---
> src/modules/alsa/alsa-sink.c | 51 ++++++++++++++++++++++++----------
> src/pulsecore/protocol-native.c | 58 ++++++++++++++++++++++++++++-----------
> src/pulsecore/sink-input.c | 26 ++++++++++++++++--
> src/pulsecore/sink-input.h | 8 ++++++
> src/pulsecore/sink.c | 26 ++++++++++++++++++
> src/pulsecore/sink.h | 2 ++
> 6 files changed, 139 insertions(+), 32 deletions(-)
The patch looks good to me (apart from the commit message and the small
issue pointed out below).
> diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
> index a4ee920..ae467f4 100644
> --- a/src/pulsecore/protocol-native.c
> +++ b/src/pulsecore/protocol-native.c
> @@ -231,6 +231,7 @@ enum {
> CONNECTION_MESSAGE_REVOKE
> };
>
> +static bool sink_input_process_underrun_cb(pa_sink_input *i);
> static int sink_input_pop_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk);
> static void sink_input_kill_cb(pa_sink_input *i);
> static void sink_input_suspend_cb(pa_sink_input *i, pa_bool_t suspend);
> @@ -1171,6 +1172,7 @@ static playback_stream* playback_stream_new(
>
> s->sink_input->parent.process_msg = sink_input_process_msg;
> s->sink_input->pop = sink_input_pop_cb;
> + s->sink_input->process_underrun = sink_input_process_underrun_cb;
> s->sink_input->process_rewind = sink_input_process_rewind_cb;
> s->sink_input->update_max_rewind = sink_input_update_max_rewind_cb;
> s->sink_input->update_max_request = sink_input_update_max_request_cb;
> @@ -1573,6 +1575,44 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
> return pa_sink_input_process_msg(o, code, userdata, offset, chunk);
> }
>
> +
> +static bool handle_input_underrun(playback_stream *s, bool force)
> +{
> + bool send_drain;
> +
> + if (pa_memblockq_is_readable(s->memblockq))
> + return false;
> +
> + if (!s->is_underrun)
> + pa_log_debug("%s %s of '%s'", force ? "Actual" : "Implicit",
> + s->drain_request ? "drain" : "underrun", pa_strnull(pa_proplist_gets(s->sink_input->proplist, PA_PROP_MEDIA_NAME)));
> +
> + send_drain = s->drain_request && (force || pa_sink_input_safe_to_remove(s->sink_input));
> +
> + if (send_drain) {
> + s->drain_request = false;
> + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
> + pa_log_debug("Drain acknowledged of '%s'", pa_strnull(pa_proplist_gets(s->sink_input->proplist, PA_PROP_MEDIA_NAME)));
> + } else if (!s->is_underrun) {
> + pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, pa_memblockq_get_read_index(s->memblockq), NULL, NULL);
> + }
> + s->is_underrun = true;
> + playback_stream_request_bytes(s);
> + return true;
> +}
> +
> +/* Called from thread context */
> +static bool sink_input_process_underrun_cb(pa_sink_input *i) {
> + playback_stream *s;
> +
> + pa_sink_input_assert_ref(i);
> + s = PLAYBACK_STREAM(i->userdata);
> + playback_stream_assert_ref(s);
> +
> + return handle_input_underrun(s, true);
> +}
> +
> +
> /* Called from thread context */
> static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {
> playback_stream *s;
> @@ -1586,22 +1626,8 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
> pa_log("%s, pop(): %lu", pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME), (unsigned long) pa_memblockq_get_length(s->memblockq));
> #endif
>
> - if (pa_memblockq_is_readable(s->memblockq))
> - s->is_underrun = FALSE;
> - else {
> - if (!s->is_underrun)
> - pa_log_debug("Underrun on '%s', %lu bytes in queue.", pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_MEDIA_NAME)), (unsigned long) pa_memblockq_get_length(s->memblockq));
> -
> - if (s->drain_request && pa_sink_input_safe_to_remove(i)) {
> - s->drain_request = FALSE;
> - pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_DRAIN_ACK, PA_UINT_TO_PTR(s->drain_tag), 0, NULL, NULL);
> - } else if (!s->is_underrun)
> - pa_asyncmsgq_post(pa_thread_mq_get()->outq, PA_MSGOBJECT(s), PLAYBACK_STREAM_MESSAGE_UNDERFLOW, NULL, pa_memblockq_get_read_index(s->memblockq), NULL, NULL);
> -
> - s->is_underrun = TRUE;
> -
> - playback_stream_request_bytes(s);
> - }
> + if (!handle_input_underrun(s, false))
> + s->is_underrun = false;
>
> /* This call will not fail with prebuf=0, hence we check for
> underrun explicitly above */
This comment refers to code that got moved elsewhere.
--
Tanu
More information about the pulseaudio-discuss
mailing list