In the case that: * the buffer size is not an integer multiple of the period size, and * drain must flush a partial period located before the end of the buffer but without a full period available, where * these conditions may pertain to the source or slave pcm buffer, and * because rate conversion is always done on a full period, it is necessary to check that both a full source period is available before source pcm buffer wrap and a full slave period is available before slave pcm buffer wrap in order to use the simple, single-commit implementation in snd_pcm_rate_commit_area(). The alternative fix would be to change snd_pcm_rate_write_areas1() to take size and slave_size parameters. This would be more disruptive to the code base, tricky to get right, and is unnecessary given that snd_pcm_mmap_commit() only commits the partial period of actually valid converted samples. Fixes: 3047f8fa5a3dce0c9775404a2285fb2cff462d96 Signed-off-by: Alan Young <consult.awy@xxxxxxxxx> --- src/pcm/pcm_rate.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/pcm/pcm_rate.c b/src/pcm/pcm_rate.c index c45895a9..ba5364c0 100644 --- a/src/pcm/pcm_rate.c +++ b/src/pcm/pcm_rate.c @@ -781,16 +781,25 @@ static int snd_pcm_rate_commit_area(snd_pcm_t *pcm, snd_pcm_rate_t *rate, snd_pcm_sframes_t result; areas = snd_pcm_mmap_areas(pcm); - if (cont >= size) { + /* + * Because snd_pcm_rate_write_areas1() below will convert a full source period + * then there had better be a full period available in the current buffer. + */ + if (cont >= pcm->period_size) { result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames); if (result < 0) return result; - if (slave_frames < slave_size) { + /* + * Because snd_pcm_rate_write_areas1() below will convert to a full slave period + * then there had better be a full slave period available in the slave buffer. + */ + if (slave_frames < rate->gen.slave->period_size) { snd_pcm_rate_write_areas1(pcm, areas, appl_offset, rate->sareas, 0); goto __partial; } snd_pcm_rate_write_areas1(pcm, areas, appl_offset, slave_areas, slave_offset); + /* Only commit the requested slave_size, even if more was actually converted */ result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, slave_size); if (result < (snd_pcm_sframes_t)slave_size) { if (result < 0) -- 2.25.1