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 <[EMAIL PROTECTED]>
#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;
}

Reply via email to