引言
上文ALSA音频架构 – snd_pcm_open函数分析已经获取了aplay中对应的播放API writei_func = snd_pcm_writei;
,本文将具体分析该API在哪里调用。
aplay处理数据流顺序图
代码详细分析
1、对参数进行解析,存储在全局变量hwparams,配置回调writei_func = snd_pcm_writei;
2、调用snd_pcm_open
打开PCM设备,将回调关联具体的写入接口snd_pcm_hw_writei
3、调用playback
根据文件类型选择具体的播放API,本文以PCM数据流为例,所以具体的接口为playback_raw
4、playback_raw对具体的数据进行解析
playback_raw的函数原型如下
static int playback_raw(char *name, int *loaded)
{
init_raw_data();
pbrec_count = calc_count();
playback_go(fd, *loaded, pbrec_count, FORMAT_RAW, name);
return 0;
}
playback_raw主要完成的工作
调用calc_count
获取数据流大小
调用playback_go
进行具体的操作
5、playback_go
首先会调用set_params
进行具体的参数配置,然后调用pcm_write
进行写入数据流
set_params
主要设置了播放的数据流的文件格式、通道数、采样率等,函数原型如下
static void set_params(void)
{
snd_pcm_hw_params_t *params;
snd_pcm_sw_params_t *swparams;
snd_pcm_uframes_t buffer_size;
int err;
size_t n;
unsigned int rate;
snd_pcm_uframes_t start_threshold, stop_threshold;
snd_pcm_hw_params_alloca(¶ms); // 分配结构体snd_pcm_hw_params_t
snd_pcm_sw_params_alloca(&swparams);
err = snd_pcm_hw_params_any(handle, params);
...
err = snd_pcm_hw_params_set_access(handle, params, // 设置存取权限
SND_PCM_ACCESS_RW_INTERLEAVED);
...
err = snd_pcm_hw_params_set_format(handle, params, hwparams.format); // 设置文件格式
if (err < 0) {
error(_("Sample format non available"));
show_available_sample_formats(params);
prg_exit(EXIT_FAILURE);
}
err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels); // 设置通道数
if (err < 0) {
error(_("Channels count non available"));
prg_exit(EXIT_FAILURE);
}
rate = hwparams.rate;
err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0); // 设置码率
...
err = snd_pcm_hw_params(handle, params);
...
snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
snd_pcm_hw_params_get_buffer_size(params, &buffer_size); // 获取一个周期有多少帧数据
pcm_write
调用函数指针writei_func
即snd_pcm_hw_writei
完成数据流的写入,函数原型如下
static ssize_t pcm_write(u_char *data, size_t count)
{
...
while (count > 0 && !in_aborting) {
if (test_position)
do_test_position();
check_stdin();
r = writei_func(handle, data, count); //写入数据
...
}
}
至此aplay的播放在用户空间层面的操作已经完成,接下来即进入驱动层进行具体的操作。
aplay的播放流程
1、snd_pcm_open
通过SND_PCM_STREAM_PLAYBACK
打开设备获取snd_pcm_t
句柄
2、snd_pcm_hw_params_alloca
分配snd_pcm_hw_params_t
PCM设备属性
3、snd_pcm_hw_params_any
初始化PCM设备属性
4、snd_pcm_hw_params_set_access
设置存取权限
5、snd_pcm_hw_params_set_format
设置格式
6、snd_pcm_hw_params_set_channels
设置通道
7、snd_pcm_hw_params_set_rate_near
设置码率
8、snd_pcm_hw_params
将snd_pcm_hw_params_t
PCM设备属性回写设备
9、snd_pcm_hw_params_get_period_size
获取每周期的数据帧数
10、snd_pcm_writei
按帧写入数据
11、snd_pcm_drain
、snd_pcm_close
关闭PCM设备
今天的文章ALSA音频架构 — aplay播放流程分析分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/24771.html