diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2011-01-24 22:07:44 +0100 |
---|---|---|
committer | malc <av1474@comtv.ru> | 2011-01-25 19:56:35 +0300 |
commit | 6315633b2535dc82dc1b3403f884b81e26b4c72c (patch) | |
tree | bf7f0f863058829cc9f973d29cca2efa37adf7b9 /audio | |
parent | d00b261816872d3e48adca584fca80ca21985f3b (diff) | |
download | qemu-6315633b2535dc82dc1b3403f884b81e26b4c72c.tar.gz qemu-6315633b2535dc82dc1b3403f884b81e26b4c72c.tar.bz2 qemu-6315633b2535dc82dc1b3403f884b81e26b4c72c.zip |
pulseaudio: process 1/4 buffer max at once
Limit the size of data pieces processed by the pulseaudio worker
threads. Never ever process more than 1/4 of the buffer at once.
Background: The buffer area currently processed by the pulseaudio thread
is blocked, i.e. the main thread (or iothread) can't fill in more data
there. The buffer processing time is roughly real-time due to the
pa_simple_write() call blocking when the output queue to the pulse
server is full. Thus processing big chunks at once means blocking
a large part of the buffer for a long time. This brings high latency
and can lead to dropouts.
When processing the buffer in smaller chunks the rpos handling becomes a
problem though. The thread reads hw->rpos without knowing whenever
qpa_run_out has already seen the last (small) chunk processed and
updated rpos accordingly. There is no point in reading hw->rpos though,
pa->rpos can be used instead. We just need to take care to initialize
pa->rpos before kicking the thread.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: malc <av1474@comtv.ru>
Diffstat (limited to 'audio')
-rw-r--r-- | audio/paaudio.c | 22 |
1 files changed, 9 insertions, 13 deletions
diff --git a/audio/paaudio.c b/audio/paaudio.c index 9cf685d30f..858ca81804 100644 --- a/audio/paaudio.c +++ b/audio/paaudio.c @@ -57,9 +57,6 @@ static void *qpa_thread_out (void *arg) { PAVoiceOut *pa = arg; HWVoiceOut *hw = &pa->hw; - int threshold; - - threshold = conf.divisor ? hw->samples / conf.divisor : 0; if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { return NULL; @@ -73,7 +70,7 @@ static void *qpa_thread_out (void *arg) goto exit; } - if (pa->live > threshold) { + if (pa->live > 0) { break; } @@ -82,8 +79,8 @@ static void *qpa_thread_out (void *arg) } } - decr = to_mix = pa->live; - rpos = hw->rpos; + decr = to_mix = audio_MIN (pa->live, conf.samples >> 2); + rpos = pa->rpos; if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { return NULL; @@ -110,8 +107,8 @@ static void *qpa_thread_out (void *arg) return NULL; } - pa->live = 0; pa->rpos = rpos; + pa->live -= decr; pa->decr += decr; } @@ -152,9 +149,6 @@ static void *qpa_thread_in (void *arg) { PAVoiceIn *pa = arg; HWVoiceIn *hw = &pa->hw; - int threshold; - - threshold = conf.divisor ? hw->samples / conf.divisor : 0; if (audio_pt_lock (&pa->pt, AUDIO_FUNC)) { return NULL; @@ -168,7 +162,7 @@ static void *qpa_thread_in (void *arg) goto exit; } - if (pa->dead > threshold) { + if (pa->dead > 0) { break; } @@ -177,8 +171,8 @@ static void *qpa_thread_in (void *arg) } } - incr = to_grab = pa->dead; - wpos = hw->wpos; + incr = to_grab = audio_MIN (pa->dead, conf.samples >> 2); + wpos = pa->wpos; if (audio_pt_unlock (&pa->pt, AUDIO_FUNC)) { return NULL; @@ -323,6 +317,7 @@ static int qpa_init_out (HWVoiceOut *hw, struct audsettings *as) audio_pcm_init_info (&hw->info, &obt_as); hw->samples = conf.samples; pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + pa->rpos = hw->rpos; if (!pa->pcm_buf) { dolog ("Could not allocate buffer (%d bytes)\n", hw->samples << hw->info.shift); @@ -377,6 +372,7 @@ static int qpa_init_in (HWVoiceIn *hw, struct audsettings *as) audio_pcm_init_info (&hw->info, &obt_as); hw->samples = conf.samples; pa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift); + pa->wpos = hw->wpos; if (!pa->pcm_buf) { dolog ("Could not allocate buffer (%d bytes)\n", hw->samples << hw->info.shift); |