mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-11-08 13:30:03 -05:00
pcm: rate: fix drain of partial period at end of buffer
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: 3047f8fa5a ("Fix possible problems of playback drain with rate plugin")
Signed-off-by: Alan Young <consult.awy@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
c41d710a69
commit
5b035bfa4a
1 changed files with 11 additions and 2 deletions
|
|
@ -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;
|
snd_pcm_sframes_t result;
|
||||||
|
|
||||||
areas = snd_pcm_mmap_areas(pcm);
|
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);
|
result = snd_pcm_mmap_begin(rate->gen.slave, &slave_areas, &slave_offset, &slave_frames);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
return result;
|
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);
|
snd_pcm_rate_write_areas1(pcm, areas, appl_offset, rate->sareas, 0);
|
||||||
goto __partial;
|
goto __partial;
|
||||||
}
|
}
|
||||||
snd_pcm_rate_write_areas1(pcm, areas, appl_offset,
|
snd_pcm_rate_write_areas1(pcm, areas, appl_offset,
|
||||||
slave_areas, slave_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);
|
result = snd_pcm_mmap_commit(rate->gen.slave, slave_offset, slave_size);
|
||||||
if (result < (snd_pcm_sframes_t)slave_size) {
|
if (result < (snd_pcm_sframes_t)slave_size) {
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue