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

Reply via email to