ALSADMA缓冲区分析.doc
文本预览下载声明
ALSA应用程序(播放器)调用ALSA lib库中的函数snd_pcm_writei()向声卡硬件(或虚拟的)写入交错(write后的i代表interleaved)数据。在ALSA lib中最后会调到snd_pcm_hw_writen(snd_pcm_t *pcm, void **bufs, snd_pcm_uframes_t size)函数,这个函数调用通用的ioctl接口:err = ioctl(fd, SNDRV_PCM_IOCTL_WRITEN_FRAMES, xfern);在ALSA驱动层中 snd_pcm_playback_ioctl1函数响应ioctl,在这个函数中某个位置会调用result = snd_pcm_lib_writev(substream, bufs, xfern.frames);它会继续调用:snd_pcm_lib_write1(substream, (unsigned long)bufs, frames,nonblock, snd_pcm_lib_writev_transfer)函数,其中snd_pcm_lib_writev_transfer是个函数指针。这个函数很关键,其中包括下面的代码: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;...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;snd_assert(frames != 0, 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);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);offse
显示全部