* OSS layer doesn't ignore xruns.
@ 2003-07-15 12:01 Carlo Wood
2003-07-15 18:31 ` Jaroslav Kysela
0 siblings, 1 reply; 5+ messages in thread
From: Carlo Wood @ 2003-07-15 12:01 UTC (permalink / raw)
To: alsa-devel
Is someone looking into my report please?
I did include a compilable test case, so it shouldn't
be too hard to reproduce this :/
Myself, I am using a Creative SoundBlaster Live! value,
but I think this should give the same results with any
sound card.
Using kernel 2.5.74 here.
The previous post:
On Sun, Jul 13, 2003 at 05:59:19PM +0200, Carlo Wood wrote:
> On Sun, Jul 13, 2003 at 04:38:47AM +0200, Carlo Wood wrote:
> > I wrote a patch for sound/core/oss/pcm_oss.c, that fixes the ViaVoice
> > problem.
>
> Later I wrote a test case that still doesn't get fixed:
>
> >a.out
> Size of a fragment in bytes: 1024
> Allocated fragments for buffering: 2
> Successfully caused an xrun.
> non-blocking fragments: 2
> non-blocking bytes: 2048
> Stream is not restarted after xrun.
>
> now this is expected without my patch, but with
> the patch the stream *is* set back to a RUNNING state
> again successfully - nevertheless, snd_pcm_update_hw_ptr_interrupt
> is not called anymore.
>
> Is there anyone who can get the following test code to work
> (by patching the ALSA kernel module, not by changing the test code! ;).
>
> Test code:
>
>
> #include <stdio.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <sys/ioctl.h>
> #include <unistd.h>
> #include <sys/soundcard.h>
> #include <time.h>
>
> int main(void)
> {
> int fd = open("/dev/dsp", O_RDONLY);
> if (fd == -1) { perror("open"); exit(127); }
> int res = AFMT_S16_LE;
> if (ioctl(fd, SNDCTL_DSP_SETFMT, &res) == -1) {
> perror("ioctl"); exit(127); }
> res = 0;
> if (ioctl(fd, SNDCTL_DSP_STEREO, &res) == -1) {
> perror("ioctl"); exit(127); }
> res = 22050;
> if (ioctl(fd, SOUND_PCM_READ_RATE, 0xbfffdcfc) == -1) {
> perror("ioctl"); exit(127); }
> res = 0x7fff000a;
> if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &res) == -1) {
> perror("ioctl"); exit(127); }
> audio_buf_info info;
> if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
> perror("read"); exit(127); }
> printf(" Size of a fragment in bytes: %d\n", info.fragsize);
> printf(" Allocated fragments for buffering: %d\n", info.fragstotal);
> char buf[1024];
> if (read(fd, buf, sizeof(buf)) < 0) { perror("read"); exit(127); }
> static struct timespec naptime = { 0, 100000000 };
> int count = 0;
> do {
> if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
> perror("read"); exit(127); }
> nanosleep(&naptime, 0);
> if (++count == 20) { printf("Failed to cause an xrun.\n"); exit(127); }
> } while(info.bytes < info.fragsize * info.fragstotal);
> printf(" Successfully caused an xrun.\n");
> printf(" non-blocking fragments: %d\n", info.fragments);
> printf(" non-blocking bytes: %d\n", info.bytes);
> ssize_t bufsize = info.bytes;
> ssize_t trlen = 0;
> int nf = 0;
> for (;;)
> {
> if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
> perror("ioctl"); exit(127); }
> if (info.fragments > 0) {
> ssize_t rlen;
> if ((rlen = read(fd, buf, sizeof(buf))) < 0)
> { perror("read"); exit(127); }
> trlen += rlen;
> if (trlen > bufsize) {
> printf(" Read %d bytes: stream successfully restarted.\n", trlen);
> exit(0);
> }
> nf = 0;
> }
> else if (++nf > 10) {
> printf(" Stream is not restarted after xrun.\n");
> exit(1);
> }
> }
> close(fd);
> return 0;
> }
>
>
> Here is some debug output that I generated with added printk's:
>
> Jul 13 17:22:27 ansset kernel: Entering snd_pcm_update_hw_ptr_interrupt
> Jul 13 17:22:27 ansset kernel: snd_pcm_update_hw_ptr_interrupt: status->hw_ptr set to 1536
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 1536, control->appl_ptr = 512
> Jul 13 17:22:27 ansset kernel: Calling snd_pcm_stop, runtime->status->state = SNDRV_PCM_STATE_RUNNING
> Jul 13 17:22:27 ansset kernel: Returned from snd_pcm_stop, runtime->status->state = SNDRV_PCM_STATE_XRUN
> Jul 13 17:22:27 ansset kernel: Leaving snd_pcm_update_hw_ptr_interrupt with EPIPE
> ...
> Jul 13 17:22:27 ansset kernel: snd_pcm_oss_read3: calling snd_pcm_kernel_ioctl SNDRV_PCM_IOCTL_DRAIN
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_drain: state is SNDRV_PCM_STATE_XRUN. Calling snd_pcm_change_state.
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 1536, control->appl_ptr = 512
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_drain: Returning from snd_pcm_change_state, state is now 5
> Jul 13 17:22:27 ansset kernel: Entering snd_pcm_lib_read1
> Jul 13 17:22:27 ansset kernel: state is SNDRV_PCM_STATE_DRAINING
> Jul 13 17:22:27 ansset kernel: size = 512
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 1536, control->appl_ptr = 512
> Jul 13 17:22:27 ansset kernel: Leaving snd_pcm_lib_read1; xfer = 512, err = 0
> ...
> Jul 13 17:22:27 ansset kernel: Entering snd_pcm_lib_read1
> Jul 13 17:22:27 ansset kernel: state is SNDRV_PCM_STATE_DRAINING
> Jul 13 17:22:27 ansset kernel: size = 512
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 1536, control->appl_ptr = 1024
> Jul 13 17:22:27 ansset kernel: Leaving snd_pcm_lib_read1; xfer = 512, err = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_status: status->hw_ptr copied to be 1536
> Jul 13 17:22:27 ansset kernel: Calling snd_pcm_capture_avail()
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 1536, control->appl_ptr = 1536
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail returned status->avail = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_status_user: status.avail = 0
>
> [start of effect of my patch]
>
> Jul 13 17:22:27 ansset kernel: snd_pcm_oss_read3: calling snd_pcm_kernel_ioctl(SNDRV_PCM_IOCTL_PREPARE)
> Jul 13 17:22:27 ansset kernel: snd_pcm_lib_ioctl_reset: status->hw_ptr set to 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_oss_read3: state now SNDRV_PCM_STATE_RUNNING
> Jul 13 17:22:27 ansset kernel: snd_pcm_update_hw_ptr: status->hw_ptr set to 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 0, control->appl_ptr = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_status: status->hw_ptr copied to be 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 0, control->appl_ptr = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail returned status->avail = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_status_user: status.avail = 0
> Jul 13 17:22:27 ansset kernel: space: bytes = 0, periods = 0, fragstotal = 2, fragsize = 1024
>
> [end of patch effects]
>
> ...
>
> but snd_pcm_update_hw_ptr_interrupt is never called anymore,
> it only repeats
>
> Jul 13 17:22:27 ansset kernel: snd_pcm_update_hw_ptr: status->hw_ptr set to 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 0, control->appl_ptr = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_status: status->hw_ptr copied to be 0
> Jul 13 17:22:27 ansset kernel: Calling snd_pcm_capture_avail()
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail: boundary = 1073741824, status->hw_ptr = 0, control->appl_ptr = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_capture_avail returned status->avail = 0
> Jul 13 17:22:27 ansset kernel: snd_pcm_status_user: status.avail = 0
> Jul 13 17:22:27 ansset kernel: space: bytes = 0, periods = 0, fragstotal = 2, fragsize = 1024
>
> after that.
>
> --
> Carlo Wood <carlo@alinoe.com>
>
>
> -------------------------------------------------------
> This SF.Net email sponsored by: Parasoft
> Error proof Web apps, automate testing & more.
> Download & eval WebKing and get a free book.
> www.parasoft.com/bulletproofapps1
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/alsa-devel
--
Carlo Wood <carlo@alinoe.com>
-------------------------------------------------------
This SF.Net email sponsored by: Parasoft
Error proof Web apps, automate testing & more.
Download & eval WebKing and get a free book.
www.parasoft.com/bulletproofapps1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: OSS layer doesn't ignore xruns.
2003-07-15 12:01 OSS layer doesn't ignore xruns Carlo Wood
@ 2003-07-15 18:31 ` Jaroslav Kysela
2003-07-16 0:11 ` Carlo Wood
2003-07-16 22:44 ` OSS layer still " Carlo Wood
0 siblings, 2 replies; 5+ messages in thread
From: Jaroslav Kysela @ 2003-07-15 18:31 UTC (permalink / raw)
To: Carlo Wood; +Cc: alsa-devel
[-- Attachment #1: Type: TEXT/PLAIN, Size: 793 bytes --]
On Tue, 15 Jul 2003, Carlo Wood wrote:
> Is someone looking into my report please?
>
> I did include a compilable test case, so it shouldn't
> be too hard to reproduce this :/
Well, in case of urgent help we have something called as SuSE
professional services. You can eventually buy our time, otherwise
you will have to wait for our free timeslot (if any).
I looked to the problem and it seems that the overrun state is handled
differently in the OSS API than ALSA implemented. It seems that the stream
is not stopped but rather the oldest period (fragment) is discarded.
The new code (plus some optimization) is in the ALSA CVS tree. The patch
is attached to this e-mail.
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs
[-- Attachment #2: Type: TEXT/plain, Size: 5373 bytes --]
Index: pcm_oss.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/core/oss/pcm_oss.c,v
retrieving revision 1.39
retrieving revision 1.41
diff -u -r1.39 -r1.41
--- pcm_oss.c 12 Jul 2003 19:21:16 -0000 1.39
+++ pcm_oss.c 15 Jul 2003 18:13:34 -0000 1.41
@@ -445,7 +445,7 @@
} else {
sw_params->start_threshold = runtime->boundary;
}
- if (atomic_read(&runtime->mmap_count))
+ if (atomic_read(&runtime->mmap_count) || substream->stream == SNDRV_PCM_STREAM_CAPTURE)
sw_params->stop_threshold = runtime->boundary;
else
sw_params->stop_threshold = runtime->buffer_size;
@@ -570,6 +570,31 @@
return 0;
}
+static int snd_pcm_oss_capture_position_fixup(snd_pcm_substream_t *substream, snd_pcm_sframes_t *delay)
+{
+ snd_pcm_runtime_t *runtime;
+ snd_pcm_uframes_t frames;
+ int err = 0;
+
+ while (1) {
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, delay);
+ if (err < 0)
+ break;
+ runtime = substream->runtime;
+ if (*delay <= runtime->buffer_size)
+ break;
+ /* in case of overrun, skip whole periods like OSS/Linux driver does */
+ /* until avail(delay) <= buffer_size */
+ frames = (*delay - runtime->buffer_size) + runtime->period_size - 1;
+ frames /= runtime->period_size;
+ frames *= runtime->period_size;
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_FORWARD, &frames);
+ if (err < 0)
+ break;
+ }
+ return err;
+}
+
snd_pcm_sframes_t snd_pcm_oss_write3(snd_pcm_substream_t *substream, const char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
@@ -608,6 +633,7 @@
snd_pcm_sframes_t snd_pcm_oss_read3(snd_pcm_substream_t *substream, char *ptr, snd_pcm_uframes_t frames, int in_kernel)
{
snd_pcm_runtime_t *runtime = substream->runtime;
+ snd_pcm_sframes_t delay;
int ret;
while (1) {
if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
@@ -626,6 +652,9 @@
if (ret < 0)
break;
}
+ ret = snd_pcm_oss_capture_position_fixup(substream, &delay);
+ if (ret < 0)
+ break;
if (in_kernel) {
mm_segment_t fs;
fs = snd_enter_user();
@@ -1335,7 +1364,7 @@
{
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- snd_pcm_status_t status;
+ snd_pcm_sframes_t delay;
struct count_info info;
int err;
@@ -1353,14 +1382,17 @@
return -EFAULT;
return 0;
}
- memset(&status, 0, sizeof(status));
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status);
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &delay);
+ } else {
+ err = snd_pcm_oss_capture_position_fixup(substream, &delay);
+ }
if (err < 0)
return err;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, runtime->buffer_size - status.avail);
+ info.bytes = runtime->oss.bytes - snd_pcm_oss_bytes(substream, delay);
} else {
- info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, status.avail);
+ info.bytes = runtime->oss.bytes + snd_pcm_oss_bytes(substream, delay);
}
info.ptr = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr % runtime->buffer_size);
if (atomic_read(&runtime->mmap_count)) {
@@ -1373,10 +1405,7 @@
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
snd_pcm_oss_simulate_fill(substream);
} else {
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- info.blocks = (runtime->buffer_size - status.avail) / runtime->period_size;
- else
- info.blocks = status.avail / runtime->period_size;
+ info.blocks = delay / runtime->period_size;
}
if (copy_to_user(_info, &info, sizeof(info)))
return -EFAULT;
@@ -1387,7 +1416,7 @@
{
snd_pcm_substream_t *substream;
snd_pcm_runtime_t *runtime;
- snd_pcm_status_t status;
+ snd_pcm_sframes_t avail;
struct audio_buf_info info;
int err;
@@ -1404,7 +1433,6 @@
info.fragsize = runtime->oss.period_bytes;
info.fragstotal = runtime->periods;
- memset(&status, 0, sizeof(status));
if (runtime->oss.prepare) {
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
info.bytes = runtime->oss.period_bytes * runtime->periods;
@@ -1414,20 +1442,18 @@
info.fragments = 0;
}
} else {
- err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_STATUS, &status);
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ err = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DELAY, &avail);
+ avail = runtime->buffer_size - avail;
+ } else {
+ err = snd_pcm_oss_capture_position_fixup(substream, &avail);
+ }
if (err < 0)
return err;
- info.bytes = snd_pcm_oss_bytes(substream, status.avail);
- info.fragments = status.avail / runtime->period_size;
+ info.bytes = snd_pcm_oss_bytes(substream, avail);
+ info.fragments = avail / runtime->period_size;
}
-#if 0
- /* very experimental stuff to get Quake2 working */
- runtime->oss.period = (info.periods - 1) << 16;
- for (tmp = info.fragsize; tmp > 1; tmp >>= 1)
- runtime->oss.period++;
- runtime->oss.subdivision = 1; /* disable SUBDIVIDE */
-#endif
#ifdef OSS_DEBUG
printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize);
#endif
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: OSS layer doesn't ignore xruns.
2003-07-15 18:31 ` Jaroslav Kysela
@ 2003-07-16 0:11 ` Carlo Wood
2003-07-16 22:44 ` OSS layer still " Carlo Wood
1 sibling, 0 replies; 5+ messages in thread
From: Carlo Wood @ 2003-07-16 0:11 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: alsa-devel
On Tue, Jul 15, 2003 at 08:31:50PM +0200, Jaroslav Kysela wrote:
> Well, in case of urgent help we have something called as SuSE
> professional services. You can eventually buy our time, otherwise
> you will have to wait for our free timeslot (if any).
Like you, I volunteer to code Open Source. In my case 60 hours/week
with zero pay. No need to rub into my face that you don't get paid.
As I said before, I am not doing this for myself. There also wasn't
any hurry (except the deadline of the release of kernel 2.6 imho,
for which this better had be fixed) - I just wanted to know if someone
was looking into it.
> I looked to the problem and it seems that the overrun state is handled
> differently in the OSS API than ALSA implemented. It seems that the stream
> is not stopped but rather the oldest period (fragment) is discarded.
>
> The new code (plus some optimization) is in the ALSA CVS tree. The patch
> is attached to this e-mail.
Thanks for the patch. I couldn't have wished a better reply ;).
--
Carlo Wood <carlo@alinoe.com>
-------------------------------------------------------
This SF.net email is sponsored by: VM Ware
With VMware you can run multiple operating systems on a single machine.
WITHOUT REBOOTING! Mix Linux / Windows / Novell virtual machines at the
same time. Free trial click here: http://www.vmware.com/wl/offer/345/0
^ permalink raw reply [flat|nested] 5+ messages in thread
* OSS layer still doesn't ignore xruns.
2003-07-15 18:31 ` Jaroslav Kysela
2003-07-16 0:11 ` Carlo Wood
@ 2003-07-16 22:44 ` Carlo Wood
2003-07-17 10:14 ` Jaroslav Kysela
1 sibling, 1 reply; 5+ messages in thread
From: Carlo Wood @ 2003-07-16 22:44 UTC (permalink / raw)
To: Jaroslav Kysela; +Cc: alsa-devel
[-- Attachment #1: Type: text/plain, Size: 4637 bytes --]
On Tue, Jul 15, 2003 at 08:31:50PM +0200, Jaroslav Kysela wrote:
> I looked to the problem and it seems that the overrun state is handled
> differently in the OSS API than ALSA implemented. It seems that the stream
> is not stopped but rather the oldest period (fragment) is discarded.
>
> The new code (plus some optimization) is in the ALSA CVS tree. The patch
> is attached to this e-mail.
This patch does not solve the problem.
As soon as the buffers runs exactly full - which is now a coincidence,
but happens reasonable quickly, the alsa layer detects an "overrun"
and stops the stream.
The stream is then still not restarted.
Attached is the source code of a slightly adjusted
test case that shows the problem.
Example output of attached test code:
>a.out
Allocated 2 buffers of 1024 bytes.
Allocated 2 buffers of 2048 bytes.
Allocated 2 buffers of 4096 bytes.
Successfully allocated a buffer that is large enough.
Available bytes: 0
Available bytes: 1632
Available bytes: 3264
Available bytes: 4896
Available bytes: 6528
Available bytes: 8160
Available bytes: 5696
Available bytes: 7328
Available bytes: 4864
Available bytes: 6496
Available bytes: 8128
Available bytes: 5664
Available bytes: 7296
Available bytes: 4832
Available bytes: 6464
Available bytes: 8096
Available bytes: 5632
Available bytes: 7264
Available bytes: 4800
Available bytes: 6432
Available bytes: 8064
Available bytes: 5600
Available bytes: 7232
Available bytes: 4768
Available bytes: 6400
Available bytes: 8032
Available bytes: 5568
Available bytes: 7200
Available bytes: 4736
Available bytes: 6368
Available bytes: 8000
Available bytes: 5536
Available bytes: 7168
Available bytes: 4704
Available bytes: 6336
Available bytes: 7968
Available bytes: 5504
Available bytes: 7136
Available bytes: 4672
Available bytes: 6304
Available bytes: 7936
Available bytes: 5472
Available bytes: 7104
Available bytes: 4640
Available bytes: 6272
Available bytes: 7904
Available bytes: 5440
Available bytes: 7072
Available bytes: 4608
Available bytes: 6240
Available bytes: 7872
Available bytes: 5408
Available bytes: 7040
Available bytes: 4576
Available bytes: 6208
Available bytes: 7840
Available bytes: 5376
Available bytes: 7008
Available bytes: 4544
Available bytes: 6176
Available bytes: 7808
Available bytes: 5344
Available bytes: 6976
Available bytes: 4512
Available bytes: 6144
Available bytes: 7776
Available bytes: 5312
Available bytes: 6944
Available bytes: 4480
Available bytes: 6112
Available bytes: 7744
Available bytes: 5280
Available bytes: 6912
Available bytes: 4448
Available bytes: 6080
Available bytes: 7712
Available bytes: 5248
Available bytes: 6880
Available bytes: 4416
Available bytes: 6048
Available bytes: 7680
Available bytes: 5216
Available bytes: 6848
Available bytes: 4384
Available bytes: 6016
Available bytes: 7648
Available bytes: 5184
Available bytes: 6816
Available bytes: 4352
Available bytes: 5984
Available bytes: 7616
Available bytes: 5152
Available bytes: 6784
Available bytes: 4320
Available bytes: 5952
Available bytes: 7584
Available bytes: 5120
Available bytes: 6752
Available bytes: 4288
Available bytes: 5920
Available bytes: 7552
Available bytes: 5088
Available bytes: 6720
Available bytes: 4256
Available bytes: 5888
Available bytes: 7520
Available bytes: 5056
Available bytes: 6688
Available bytes: 4224
Available bytes: 5856
Available bytes: 7488
Available bytes: 5024
Available bytes: 6656
Available bytes: 4192
Available bytes: 5824
Available bytes: 7456
Available bytes: 4992
Available bytes: 6624
Available bytes: 4160
Available bytes: 5792
Available bytes: 7424
Available bytes: 4960
Available bytes: 6592
Available bytes: 4128
Available bytes: 5760
Available bytes: 7392
Available bytes: 4928
Available bytes: 6560
Available bytes: 8192
Successfully caused an xrun.
non-blocking fragments: 2
non-blocking bytes: 8192
Available bytes in buffer: 5728
Additionally read 1024 bytes.
Additionally read 1024 bytes.
Additionally read 1024 bytes.
Additionally read 1024 bytes.
Stream is not restarted after xrun.
--
Carlo Wood <carlo@alinoe.com>
[-- Attachment #2: testcode.c --]
[-- Type: text/plain, Size: 2771 bytes --]
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/soundcard.h>
#include <time.h>
int main(void)
{
int fd;
int res = 0x7fff0009;
audio_buf_info info;
int prev_size = 0;
do
{
++res;
close(fd);
fd = open("/dev/dsp", O_RDONLY);
if (fd == -1) { perror("open"); exit(127); }
if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &res) == -1) {
perror("ioctl"); exit(127); }
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
printf(" Allocated %d buffers of %d bytes.\n", info.fragstotal, info.fragsize);
if (prev_size == info.fragsize * info.fragstotal)
{
printf(" It seems impossible to set a recording buffer with a\n"
" total size of at least 8192 bytes. This is not going\n"
" to work with ViaVoice. Sorry.\n");
exit(126);
}
prev_size = info.fragsize * info.fragstotal;
}
while (prev_size < 8192);
printf(" Successfully allocated a buffer that is large enough.\n");
res = AFMT_S16_LE;
if (ioctl(fd, SNDCTL_DSP_SETFMT, &res) == -1) {
perror("ioctl"); exit(127); }
res = 0;
if (ioctl(fd, SNDCTL_DSP_STEREO, &res) == -1) {
perror("ioctl"); exit(127); }
res = 22050;
if (ioctl(fd, SOUND_PCM_READ_RATE, 0xbfffdcfc) == -1) {
perror("ioctl"); exit(127); }
char buf[1024];
if (read(fd, buf, sizeof(buf)) < 0) { perror("read"); exit(127); }
static struct timespec naptime = { 0, 100000000 };
do {
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
printf(" Available bytes: %d\n", info.bytes);
nanosleep(&naptime, 0);
} while(info.bytes < info.fragsize * info.fragstotal);
printf(" Successfully caused an xrun.\n");
printf(" non-blocking fragments: %d\n", info.fragments);
printf(" non-blocking bytes: %d\n", info.bytes);
ssize_t bufsize = info.bytes;
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
printf(" Available bytes in buffer: %d\n", info.bytes);
ssize_t trlen = 0;
int nf = 0;
for (;;)
{
if (info.fragments > 0) {
ssize_t rlen;
if ((rlen = read(fd, buf, sizeof(buf))) < 0)
{ perror("read"); exit(127); }
printf(" Additionally read %d bytes.\n", rlen);
trlen += rlen;
if (trlen > bufsize) {
printf(" Read %d bytes: stream successfully restarted.\n", trlen);
break;
}
nf = 0;
}
else if (++nf > 10) {
printf(" Stream is not restarted after xrun.\n");
exit(1);
}
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
}
close(fd);
return 0;
}
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: OSS layer still doesn't ignore xruns.
2003-07-16 22:44 ` OSS layer still " Carlo Wood
@ 2003-07-17 10:14 ` Jaroslav Kysela
0 siblings, 0 replies; 5+ messages in thread
From: Jaroslav Kysela @ 2003-07-17 10:14 UTC (permalink / raw)
To: Carlo Wood; +Cc: alsa-devel
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1176 bytes --]
On Thu, 17 Jul 2003, Carlo Wood wrote:
> On Tue, Jul 15, 2003 at 08:31:50PM +0200, Jaroslav Kysela wrote:
> > I looked to the problem and it seems that the overrun state is handled
> > differently in the OSS API than ALSA implemented. It seems that the stream
> > is not stopped but rather the oldest period (fragment) is discarded.
> >
> > The new code (plus some optimization) is in the ALSA CVS tree. The patch
> > is attached to this e-mail.
>
> This patch does not solve the problem.
> As soon as the buffers runs exactly full - which is now a coincidence,
> but happens reasonable quickly, the alsa layer detects an "overrun"
> and stops the stream.
Nope. Your test code is buggy. If you have 2 fragments per 4096 bytes and
you will read samples then the ring buffer goes filled bellow 4096 bytes,
then info.frags is zero, thus your loop goes very quickly to 10
iterations. I attached fixed code which adds additional wait - not
very clean solution - poll() is prefered (plus commented code which
sleeps 4 seconds to generate an overrun at the start).
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SuSE Labs
[-- Attachment #2: Type: TEXT/plain, Size: 3048 bytes --]
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <sys/soundcard.h>
#include <time.h>
int main(void)
{
int fd;
int res = 0x20009;
audio_buf_info info;
int prev_size = 0;
do
{
++res;
close(fd);
fd = open("/dev/dsp", O_RDONLY);
if (fd == -1) { perror("open"); exit(127); }
if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &res) == -1) {
perror("ioctl"); exit(127); }
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
printf(" Allocated %d buffers of %d bytes.\n", info.fragstotal, info.fragsize);
if (prev_size == info.fragsize * info.fragstotal)
{
printf(" It seems impossible to set a recording buffer with a\n"
" total size of at least 8192 bytes. This is not going\n"
" to work with ViaVoice. Sorry.\n");
exit(126);
}
prev_size = info.fragsize * info.fragstotal;
}
while (prev_size < 8192);
printf(" Successfully allocated a buffer that is large enough.\n");
res = AFMT_S16_LE;
if (ioctl(fd, SNDCTL_DSP_SETFMT, &res) == -1) {
perror("ioctl"); exit(127); }
res = 0;
if (ioctl(fd, SNDCTL_DSP_STEREO, &res) == -1) {
perror("ioctl"); exit(127); }
res = 22050;
if (ioctl(fd, SOUND_PCM_READ_RATE, 0xbfffdcfc) == -1) {
perror("ioctl"); exit(127); }
char buf[1024];
if (read(fd, buf, sizeof(buf)) < 0) { perror("read"); exit(127); }
static struct timespec naptime = { 0, 100000000 };
#if 1
do {
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
printf(" Available bytes: %d\n", info.bytes);
nanosleep(&naptime, 0);
} while(info.bytes < info.fragsize * info.fragstotal);
#else
sleep(4);
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
#endif
printf(" Successfully caused an xrun.\n");
printf(" non-blocking fragments: %d\n", info.fragments);
printf(" non-blocking bytes: %d\n", info.bytes);
ssize_t bufsize = info.bytes;
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
ssize_t trlen = 0;
int nf = 0;
for (;;)
{
printf(" Available bytes in buffer: %d (frags %d)\n", info.bytes, info.fragments);
if (info.fragments > 0) {
ssize_t rlen;
if ((rlen = read(fd, buf, sizeof(buf))) < 0)
{ perror("read"); exit(127); }
printf(" Additionally read %d bytes.\n", rlen);
trlen += rlen;
if (trlen > bufsize) {
printf(" Read %d bytes: stream successfully restarted.\n", trlen);
break;
}
nf = 0;
}
else if (++nf > 10) {
printf(" Stream is not restarted after xrun.\n");
exit(1);
} else {
usleep(100000);
}
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) == -1) {
perror("read"); exit(127); }
}
close(fd);
return 0;
}
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2003-07-17 10:14 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-15 12:01 OSS layer doesn't ignore xruns Carlo Wood
2003-07-15 18:31 ` Jaroslav Kysela
2003-07-16 0:11 ` Carlo Wood
2003-07-16 22:44 ` OSS layer still " Carlo Wood
2003-07-17 10:14 ` Jaroslav Kysela
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.