ALSA音频架构 — aplay播放流程分析

ALSA音频架构 — aplay播放流程分析上文已经获取了aplay中对应的播放API,本文将具体分析该API在哪里调用。

引言

上文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(&params); // 分配结构体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_paramssnd_pcm_hw_params_t PCM设备属性回写设备
9、snd_pcm_hw_params_get_period_size获取每周期的数据帧数
10、snd_pcm_writei按帧写入数据
11、snd_pcm_drainsnd_pcm_close关闭PCM设备

今天的文章ALSA音频架构 — aplay播放流程分析分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/24771.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注