Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15358679
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-11-19 14:03:48

static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
                        unsigned long data,
                        snd_pcm_uframes_t size,
                        int nonblock,
                        transfer_f transfer)
{
    struct snd_pcm_runtime *runtime = substream->runtime;
    snd_pcm_uframes_t xfer = 0;
    snd_pcm_uframes_t offset = 0;
    int err = 0;

    if (size == 0)
        return 0;

    snd_pcm_stream_lock_irq(substream);
    switch (runtime->status->state) {
    case SNDRV_PCM_STATE_PREPARED:
    case SNDRV_PCM_STATE_RUNNING:
    case SNDRV_PCM_STATE_PAUSED:
        break;
    case SNDRV_PCM_STATE_XRUN:
        err = -EPIPE;
        goto _end_unlock;
    case SNDRV_PCM_STATE_SUSPENDED:
        err = -ESTRPIPE;
        goto _end_unlock;
    default:
        err = -EBADFD;
        goto _end_unlock;
    }

    while (size > 0) {
        snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
        snd_pcm_uframes_t avail;
        snd_pcm_uframes_t cont;
        if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
            snd_pcm_update_hw_ptr(substream);
        avail = snd_pcm_playback_avail(runtime);
        if (!avail) {
            if (nonblock) {
                err = -EAGAIN;
                goto _end_unlock;
            }
            err = wait_for_avail_min(substream, &avail);
            if (err < 0)
                goto _end_unlock;
        }
        frames = size > avail ? avail : size;
        cont = runtime->buffer_size - runtime->control->appl_ptr % runtime->buffer_size;
        if (frames > cont)
            frames = cont;
        if (snd_BUG_ON(!frames)) {
            snd_pcm_stream_unlock_irq(substream);
            return -EINVAL;
        }
        appl_ptr = runtime->control->appl_ptr;
        appl_ofs = appl_ptr % runtime->buffer_size;
        snd_pcm_stream_unlock_irq(substream);
        // 上面是组织数据,下面对于snd_pcm_lib_write调用,transfer为snd_pcm_lib_write_transfer 《浅析alsa声卡驱动snd_pcm_lib_write_transfer函数》
        // 将数据拷贝到runtime->dma_area这个DMA空间[luther.gliethttp]
        if ((err = transfer(substream, appl_ofs, data, offset, frames)) < 0)
            goto _end;
        snd_pcm_stream_lock_irq(substream);
        switch (runtime->status->state) {
        case SNDRV_PCM_STATE_XRUN:
            err = -EPIPE;
            goto _end_unlock;
        case SNDRV_PCM_STATE_SUSPENDED:
            err = -ESTRPIPE;
            goto _end_unlock;
        default:
            break;
        }
        appl_ptr += frames;
        if (appl_ptr >= runtime->boundary)
            appl_ptr -= runtime->boundary;
        runtime->control->appl_ptr = appl_ptr;
        if (substream->ops->ack)
            substream->ops->ack(substream);

        offset += frames;
        size -= frames;
        xfer += frames;
        if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
            snd_pcm_playback_hw_avail(runtime) >= (snd_pcm_sframes_t)runtime->start_threshold) {
            err = snd_pcm_start(substream); // start all linked streams启动发送,将streams中的所有音频数据递交到硬件[luther.gliethttp] 《浅析alsa声卡驱动snd_pcm_start函数-将音频数据真实的发送到外部音频接口硬件》
            if (err < 0)
                goto _end_unlock;
        }
    }
 _end_unlock:
    snd_pcm_stream_unlock_irq(substream);
 _end:
    return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
}
阅读(5835) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-05-14 21:08:20

详细点好不好?没什么实质性的东西,看了等于白看。