speaker-test stalls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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. 

So for example, period size is 8192, buffer is 32768, and the wave file
has 71042 samples (Front_Left.wav for speaker-test).

speaker-test will break that into 8 writes of 8192 samples, and one of
5506.

If you get a XRUN in the last 32k of the file, the PCM will be stopped,
and prepared, and we'll start loading data into again. Because we have a
tail of 5506 samples, we get to the point where the available space is
less than our minimum, and then snd_pcm_lib_write1() will wait forever
for the available space to be >= runtime->avail_min, even though the
channel is stopped.

[snip from a trace, patch to pcm_lib.c attached]
writei size 8192 avail 32768 min 8192 xfer 1 state 2
writei size 8192 avail 24576 min 8192 xfer 1 state 2
writei size 5506 avail 16384 min 8192 xfer 1 state 2
writei size 8192 avail 10878 min 8192 xfer 1 state 2
writei size 8192 avail 2686 min 8192 xfer 1 state 2
writei loop avail 2686 min 8192
writei loop avail 2686 min 8192
writei loop avail 2686 min 8192
writei loop avail 2686 min 8192


Assuming that this is desired behavior from the kernel side, then I see
three options to fix this in speaker-test:
1) snd_pcm_sw_params_set_avail_min() to 1 sample
2) snd_pcm_sw_params_set_start_threshold() to start when (nperiods - 1)
are ready (or be even more aggressive)
3) call snd_pcm_drain() at the end of each loop to clear out the buffer.
This won't help if the wave file has fewer samples than the buffer size.

Options 1 or 2 seem to be best.

Thoughts?

Dave

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 806f1fb..deac5e8 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -177,6 +177,8 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream
 			xrun(substream);
 		return -EPIPE;
 	}
+	printk(KERN_DEBUG "avail %lu max %lu min %lu\n", avail, runtime->avail_max,
+				runtime->control->avail_min);
 	if (avail >= runtime->control->avail_min)
 		wake_up(&runtime->sleep);
 	return 0;
@@ -1651,6 +1653,10 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
 		if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
 			snd_pcm_update_hw_ptr(substream);
 		avail = snd_pcm_playback_avail(runtime);
+		printk(KERN_DEBUG "writei size %lu avail %lu min %lu xfer %lu state %d\n",
+				size, avail, runtime->control->avail_min, runtime->xfer_align,
+				runtime->status->state);
+
 		if (((avail < runtime->control->avail_min && size > avail) ||
 		   (size >= runtime->xfer_align && avail < runtime->xfer_align))) {
 			wait_queue_t wait;
@@ -1695,6 +1701,8 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
 					break;
 				}
 				avail = snd_pcm_playback_avail(runtime);
+				printk(KERN_DEBUG "writei loop avail %lu min %lu\n", avail,
+						runtime->control->avail_min);
 				if (avail >= runtime->control->avail_min) {
 					state = READY;
 					break;
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxx
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux