Hi. I'm writing the alsa plugin for gstreamer. When I go to capture audio, my
loop eats the entire cpu. I set avail_min but still sometimes get out 32 frame
avail values. Here's the relevant portion:
/* shamelessly stolen from pbd's audioengine. thanks, paul! */
static void
gst_alsa_loop (GstElement *element)
{
struct pollfd pfd;
gboolean xrun_detected;
guint32 x;
GstAlsa *this = (GstAlsa*) element;
g_return_if_fail(this != NULL);
if (this->stream == SND_PCM_STREAM_PLAYBACK) {
snd_pcm_poll_descriptors (this->handle, &pfd, 1);
pfd.events = POLLOUT | POLLERR;
}
do {
if (this->stream == SND_PCM_STREAM_PLAYBACK) {
if (poll (&pfd, 1, 1000) < 0) {
if (errno == EINTR) {
// this happens mostly when run
// under gdb, or when exiting due to a signal
continue;
}
g_warning("poll call failed (%s)", strerror(errno));
return;
}
if (pfd.revents & POLLERR) {
g_warning("alsa: poll reports error.");
return;
}
if (pfd.revents == 0) {
// timed out, such as when the device is paused
continue;
}
}
xrun_detected = FALSE;
this->avail = snd_pcm_avail_update (this->handle);
while (this->avail < this->period_frames) {
if (this->avail < 0) {
if (this->avail == -EPIPE) {
xrun_detected = TRUE;
} else {
g_warning("unknown ALSA avail_update return value (%d)",
(int)this->avail);
return;
}
} else {
snd_pcm_wait(this->handle, 1000);
}
this->avail = snd_pcm_avail_update (this->handle);
}
if (xrun_detected)
g_warning ("xrun detected");
if (!gst_alsa_get_channel_addresses (this) < 0) {
g_error("could not get channels");
return;
}
if (this->mute && this->stream == SND_PCM_STREAM_PLAYBACK) {
for (x = 0; x < this->channels; x++) {
if (this->mute & (1<<x)) {
gst_alsa_sink_silence_on_channel (this, x, this->buffer_frames);
}
}
// silence_pending = 0;
}
// channels_not_done = channel_done_bits;
// prefold_all_channels (contiguous);
if (!this->process(this, this->avail)) {
g_warning("alsa: something happened while processing audio");
return;
}
// if (channels_not_done) {
// silence_untouched_channels (contiguous);
// }
gst_alsa_release_channel_addresses(this);
} while (!GST_ELEMENT_IS_COTHREAD_STOPPING (element));
// clean up bytestreams
}
// this is one of the possible functions for this->process on a capture device
static gboolean
gst_alsa_src_interleaved_process (GstAlsa *this, snd_pcm_uframes_t frames)
{
GstBuffer *buf;
gint len;
g_return_val_if_fail(this->pad != NULL, FALSE);
len = frames * this->sample_bytes * this->channels;
buf = gst_buffer_new();
GST_BUFFER_DATA(buf) = g_malloc(len);
GST_BUFFER_SIZE(buf) = len;
GST_BUFFER_MAXSIZE(buf) = len;
memcpy(GST_BUFFER_DATA(buf), this->access_addr[0], len);
gst_pad_push(this->pad, buf);
return TRUE;
}
For the record, playback works quite well now. Thanks to all who helped!
wingo
_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel