Hi.
For the attached test case snd_pcm_avail_update returns values higher than the buffer size when run with the OSS PCM plugin. Output of alsa-info.sh is at http://www.alsa-project.org/db/?f=77a873e55d5d6ca50d67a035a9d6b7e10cca179d .
--- alsa_oss_pcm_avail_bug.c --- /* * Public domain test case to illustrate a bug in the ALSA OSS PCM plugin * where snd_pcm_avail_update returns bogus values. */
#include <alsa/asoundlib.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
static short buf[803 * 2]; static snd_pcm_t *pcm_handle = NULL;
void close_pcm(void) { if (pcm_handle) snd_pcm_close(pcm_handle);
pcm_handle = NULL; }
static int set_pcm_parameters(void) { snd_pcm_hw_params_t *hwparams; snd_pcm_hw_params_alloca(&hwparams);
if (snd_pcm_hw_params_any(pcm_handle, hwparams) < 0) { fprintf(stderr, "snd_pcm_hw_params_any failed.\n"); return -1; }
if (snd_pcm_hw_params_set_access(pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { fprintf(stderr, "snd_pcm_hw_params_set_access failed.\n"); return -1; }
if (snd_pcm_hw_params_set_format(pcm_handle, hwparams, SND_PCM_FORMAT_S16) < 0) { fprintf(stderr, "snd_pcm_hw_params_set_format failed.\n"); return -1; }
{ unsigned rate = 48000;
if (snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, &rate, 0) < 0) { fprintf(stderr, "snd_pcm_hw_params_set_rate_near failed.\n"); return -1; } }
if (snd_pcm_hw_params_set_channels(pcm_handle, hwparams, 2) < 0) { fprintf(stderr, "snd_pcm_hw_params_set_channels failed.\n"); return -1; }
{ unsigned ulatency = 100000;
if (snd_pcm_hw_params_set_buffer_time_near(pcm_handle, hwparams, &ulatency, 0) < 0) { fprintf(stderr, "snd_pcm_hw_params_set_buffer_time_near failed.\n"); return -1; } }
if (snd_pcm_hw_params(pcm_handle, hwparams) < 0) { fprintf(stderr, "snd_pcm_hw_params failed.\n"); return -1; }
{ snd_pcm_uframes_t bSize = 0;
if (snd_pcm_hw_params_get_buffer_size(hwparams, &bSize) < 0) { fprintf(stderr, "snd_pcm_hw_params_get_buffer_size failed\n"); return -1; }
printf("buffer_size: %u\n", (unsigned int) bSize); }
return 0; }
static void test_loop(int n) { while (n--) { snd_pcm_sframes_t sframes = snd_pcm_avail_update(pcm_handle); printf("snd_pcm_avail: %d\n", (int) sframes); printf("writing %d frames\n", (int) sizeof(buf) / 4); sframes = snd_pcm_writei(pcm_handle, buf, sizeof(buf) / 4);
if (sframes != sizeof(buf) / 4) { if (sframes < 0) snd_pcm_prepare(pcm_handle);
printf("snd_pcm_writei returned %d\n", (int) sframes); } } }
int main(int argc, char **argv) { atexit(close_pcm);
if (argc < 2) { printf("usage: %s <ALSA pcm device>\n", argv[0]); return 0; }
if (snd_pcm_open(&pcm_handle, argv[1], SND_PCM_STREAM_PLAYBACK, 0) < 0) { fprintf(stderr, "Error opening PCM device %s\n", argv[1]); pcm_handle = NULL; return -1; }
if (set_pcm_parameters() < 0) return -1;
memset(buf, 0, sizeof(buf));
test_loop(500);
return 0; }
-- Sindre Aamås