From 1c55ff9baa4fe5715c91a02957d28d1fd939dba4 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Thu, 8 Nov 2012 13:10:35 -0800 Subject: [PATCH] Fix sleeping problem with rate plugin The rate plugin can only process complete periods of data. Because of this sometimes the rate plugin's buffer has frames in it that have not yet been sent to its slave. This means the rate plugin's buffer has less available space than the slave's buffer. When more data is written, the rate plugin's buffer will have less than avail_min space and so alsa-lib will try to wait for more space to become available. This in turn becomes a wait on the slave's buffer. But the slave's buffer has more space available! So it doesn't sleep and the wait returns immediatly. ALSA gets stuck in a tight loop with the writing code decided that the rate plugin's buffer is too full and trying to sleep, and the sleeping code deciding that the slave's buffer is empty enough and not sleeping. We get around this by tweeking avail_min to decrease it by the unprocessed data. When deciding to sleep, this has the same effect as increasing the available space by the unprocessed data. In effect, we turn avail(rate) into avail(rate->slave). Can make our sleep decision based on the slave's buffer, instead of on the rate buffer. There was an unused field, orig_avail_min, in the rate struct. This changes it to be the rate's original avai_min rather than the slave's original avail_min. Signed-off-by: Trent Piepho --- src/pcm/pcm_rate.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 4ba8521..41089d7 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -395,8 +395,8 @@ static int snd_pcm_rate_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params) if (rate->ops.adjust_pitch) rate->ops.adjust_pitch(rate->obj, &rate->info); - recalc(pcm, &sparams->avail_min); rate->orig_avail_min = sparams->avail_min; + recalc(pcm, &sparams->avail_min); recalc(pcm, &sparams->start_threshold); if (sparams->avail_min < 1) sparams->avail_min = 1; if (sparams->start_threshold <= slave->buffer_size) { @@ -969,6 +969,10 @@ static int snd_pcm_rate_sync_playback_area(snd_pcm_t *pcm, snd_pcm_uframes_t app if (rate->last_commit_ptr >= pcm->boundary) rate->last_commit_ptr = 0; } + /* Tweek avail_min to take into account the data not yet sent to the + * slave pcm. */ + pcm->avail_min = rate->orig_avail_min >= xfer ? + rate->orig_avail_min - xfer : 1; return 0; } -- 1.7.9.5