Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
以采样率和buffer size为线索来跟踪开机时Audio Hal第一次初始化:
AudioPolicyManager ->
ConfigParsingUtils::loadAudioPolicyConfig -> AUDIO_POLICY_CONFIG_FILE是/system/etc/audio_policy.conf, 对应/device/rockchip/common/audio_policy_rk30board.conf
loadHwModules ->
loadHwModule ->
config_find(root, INPUTS_TAG); //INPUTS_TAG是inputs,在audio_policy.conf能找到.
module->loadInput ->
HwModule::loadInput ->
profile->loadSamplingRates -> 找到SAMPLING_RATES_TAG的内容,即sampling_rates
mSamplingRates.add //所有支持采样率都存下来,其他如format, channel也一样被各自存下来
mInputProfiles.add //一个input节点当做一个profile存下来
new AudioInputDescriptor(inProfile); -> 根据上面profile来创建
profile->pickSamplingRate //获取最大采样率,这里就是48kHz, channel也是类似.
mpClientInterface->openInput -> 将上面获取的sample rate以及channel还有format组成config传给hal看是否真支持,不支持的话HAL会重新配置.
AudioFlinger::openInput_l ->
inHwHal->open_input_stream ->
adev_open_input_stream -> audio_hw.c
static int adev_open_input_stream(struct audio_hw_device *dev,
audio_io_handle_t handle,
audio_devices_t devices,
struct audio_config *config, //从audio_policy.conf得到的最大支持配置
struct audio_stream_in **stream_in, //传进来是新的
audio_input_flags_t flags,
const char *address __unused,
audio_source_t source __unused)
{
struct audio_device *adev = (struct audio_device *)dev;
struct stream_in *in;
int ret;
*stream_in = NULL;
//不管它传进来是哪种,直接定死为双声道.
config->channel_mask = AUDIO_CHANNEL_IN_STEREO;
#ifdef ALSA_IN_DEBUG
//用来调试抓取pcm数据
in_debug = fopen("/data/debug.pcm","wb");//please touch /data/debug.pcm first
#endif
......
in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
if (!in)
return -ENOMEM;
......
//audio_policy.conf中的最大采样率,是48kHz
in->requested_rate = config->sample_rate;
......
in->channel_mask = config->channel_mask;
ALOGE("in->channel_mask:%d", in->channel_mask);
......
//默认用的是pcm_config_in
//struct pcm_config pcm_config_in = {
//.channels = 2,
//.rate = 44100,
//.period_size = 16,
//.period_count = 128,
//.format = PCM_FORMAT_S16_LE,
//};
struct pcm_config *pcm_config = flags & AUDIO_INPUT_FLAG_FAST ?
&pcm_config_in_low_latency : &pcm_config_in;
in->config = pcm_config;
//用pcm_config_in的配置来计算, audio_stream_in_frame_size(&in->stream)调用的是
//in_get_format(),固定是AUDIO_FORMAT_PCM_16_BIT, audio_channel_count_from_out_mask()用来转换
//channel宏定义为实际的number.不过这里有疑问的是这样不是多了一个pcm_config->channels了?
//audio_stream_in_frame_size()已经包含了channel了,我觉得它是多申请了.
in->buffer = malloc(pcm_config->period_size * pcm_config->channels
* audio_stream_in_frame_size(&in->stream));
......
//当上层采样率和HAL配置的采样率不想等时,要resample,当然,数据最终也是从resample后的buffer中获取.
if (in->requested_rate != pcm_config->rate) {
//和正常非resample的获取kernel录音数据方式一样.
in->buf_provider.get_next_buffer = get_next_buffer;
in->buf_provider.release_buffer = release_buffer;
ALOGD("pcm_config->rate:%d,in->requested_rate:%d,in->channel_mask:%d",
pcm_config->rate,in->requested_rate,audio_channel_count_from_in_mask(in->channel_mask));
ret = create_resampler(pcm_config->rate,
in->requested_rate,
audio_channel_count_from_in_mask(in->channel_mask),
RESAMPLER_QUALITY_DEFAULT,
&in->buf_provider,
&in->resampler);
if (ret != 0) {
ret = -EINVAL;
goto err_resampler;
}
}
......
*stream_in = &in->stream;
return 0;
......
}
上层通过in_get_buffer_size()来获取buffer size
static size_t in_get_buffer_size(const struct audio_stream *stream)
{
struct stream_in *in = (struct stream_in *)stream;
ALOGE("in_get_buffer_size");
//还是和前面说的一样, 第一请求用的是audio_policy.conf中的值.
//in->requested_rate=48kHz
//audio_channel_count_from_in_mask(in_get_channels(stream))在前面被固定了,因此为2.
return get_input_buffer_size(in->requested_rate,
AUDIO_FORMAT_PCM_16_BIT,
audio_channel_count_from_in_mask(in_get_channels(stream)),
(in->flags & AUDIO_INPUT_FLAG_FAST) != 0);
}
static size_t get_input_buffer_size(unsigned int sample_rate,
audio_format_t format,
unsigned int channel_count,
bool is_low_latency)
{
const struct pcm_config *config = is_low_latency ?
&pcm_config_in_low_latency : &pcm_config_in;
size_t size;
//考虑了对齐以及采样率不一致的因素.
size = (config->period_size * sample_rate) / config->rate;
size = ((size + 15) / 16) * 16;
//一次采样的大小就是period size * channel * format.
return size * channel_count * audio_bytes_per_sample(format);
}