[alsa-devel] speaker-test stalls
Takashi Iwai
tiwai at suse.de
Wed Dec 19 12:46:17 CET 2007
At Fri, 14 Dec 2007 12:40:04 -0500,
Dave Dillow wrote:
>
> On Fri, Dec 14, 2007 at 04:39:37PM +0100, Takashi Iwai wrote:
> > At Sat, 08 Dec 2007 15:58:40 -0500,
> > Dave Dillow wrote:
> > >
> > > While working with Fernando to get the sis7019 driver working in his
> > > buildroot setup, we kept running into a lockup of the PCM stream when
> > > using speaker-test. aplay was fine, as was other I finally tracked it
> > > down to a combination of uclibc not doing block reads, which led to
> > > XRUNs, and what I thought was issue in snd_pcm_lib_write1() when trying
> > > to fill up the tail of the PCM buffer with a large write, when there was
> > > an intervening small write.
> > >
> > > As it turns out, the lockup problem may simply be in speaker-write's
> > > sw_params settings -- it calls snd_pcm_sw_params_set_avail_min() to set
> > > the minium write to the period size, and
> > > snd_pcm_sw_params_set_start_threshold() to start once the buffer has
> > > been filled. This doesn't account for odd wave file lengths and XRUNs.
> > >
> > > The problem arises when the wave data is not a multiple of the period
> > > size, and you get an XRUN when there is less than buffer_size samples
> > > remaining in the current loop.
> >
> > Hm, it sounds weird. Basically XRUN means that you have *no* data in
> > the buffer while the stream is running. So, when you get XRUN, the
> > data must be empty, no matter which buffer or period size is.
>
> Right, the buffer empties, and then the loop in speaker-test::write_buffer()
> starts filling the buffer again, as expected.
>
> However, the sample data in the wave file is not a multiple of the buffer
> size, so it does a small write (ie, not period sized) to finish out the file,
> and the main routine calls back in to do the next loop.
>
> So, you get a pattern (buffer_size is 32768):
>
> write len buffer available before write
> XRUN happens N/A
> 8192 32768
> 8192 24576
> 5506 16384
> 8192 10878
> 8192 2686
>
> Because speaker-test sets avail_min to 8192, and the start threshold to
> 32768, snd_pcm_lib_write1() will loop forever waiting for 8192 bytes to
> become available in the buffer. That will never happen, because the XRUN
> stopped the channel, and we cannot reach the start threshold, as this last
> write that would do it is the one that blocked.
OK, point taken. It's a problem in the PCM core indeed.
The patch below should solve the problem, but it's ad hoc.
Takashi
diff -r 6f193b381db3 core/pcm_lib.c
--- a/core/pcm_lib.c Wed Dec 19 12:13:44 2007 +0100
+++ b/core/pcm_lib.c Wed Dec 19 14:36:04 2007 +0100
@@ -1655,8 +1655,11 @@ static snd_pcm_sframes_t snd_pcm_lib_wri
if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
snd_pcm_update_hw_ptr(substream);
avail = snd_pcm_playback_avail(runtime);
- if (((avail < runtime->control->avail_min && size > avail) ||
- (size >= runtime->xfer_align && avail < runtime->xfer_align))) {
+ if (!avail ||
+ (snd_pcm_running(substream) &&
+ ((avail < runtime->control->avail_min && size > avail) ||
+ (size >= runtime->xfer_align &&
+ avail < runtime->xfer_align)))) {
wait_queue_t wait;
enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
long tout;
More information about the Alsa-devel
mailing list