[PATCH] fix infinite draining of the rate plugin in SND_PCM_NONBLOCK mode
The draining function of the rate plugin does not handle properly the SND_PCM_NONBLOCK case. It can write data to the slave plugin each time the function is called, but does not update its internal state in order to reach a stopping condition. Use a last_commit_ptr workaround to reach such condition.
signed-off-by: Sylvain BERTRAND sylvain.bertrand@legeek.net --- src/pcm/pcm_rate.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) --- diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index 21611f62..25574a50 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -1051,6 +1051,7 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm) /* commit the remaining fraction (if any) */ snd_pcm_uframes_t size, ofs, saved_avail_min; snd_pcm_sw_params_t sw_params; + int commit_err;
__snd_pcm_lock(pcm); /* temporarily set avail_min to one */ @@ -1066,7 +1067,7 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm) while (size > 0) { snd_pcm_uframes_t psize, spsize; int err; - + err = __snd_pcm_wait_in_lock(rate->gen.slave, -1); if (err < 0) break; @@ -1079,14 +1080,29 @@ static int snd_pcm_rate_drain(snd_pcm_t *pcm) if (! spsize) break; } - snd_pcm_rate_commit_area(pcm, rate, ofs, + commit_err = snd_pcm_rate_commit_area(pcm, rate, ofs, psize, spsize); + if (commit_err == 1) { + rate->last_commit_ptr += psize; + if (rate->last_commit_ptr >= pcm->boundary) + rate->last_commit_ptr = 0; + } else if (commit_err == 0) { + if (pcm->mode & SND_PCM_NONBLOCK != 0) { + commit_err = -EAGAIN; + break; + } + continue; + } else + break; + ofs = (ofs + psize) % pcm->buffer_size; size -= psize; } sw_params.avail_min = saved_avail_min; snd_pcm_sw_params(rate->gen.slave, &sw_params); __snd_pcm_unlock(pcm); + if (commit_err < 0) + return commit_err; } return snd_pcm_drain(rate->gen.slave); }
Dne 28. 04. 20 v 14:09 sylvain.bertrand@gmail.com napsal(a):
The draining function of the rate plugin does not handle properly the SND_PCM_NONBLOCK case. It can write data to the slave plugin each time the function is called, but does not update its internal state in order to reach a stopping condition. Use a last_commit_ptr workaround to reach such condition.
signed-off-by: Sylvain BERTRAND sylvain.bertrand@legeek.net
Applied. Thank you.
Jaroslav
participants (2)
-
Jaroslav Kysela
-
sylvain.bertrand@gmail.com