android hal 音频分析,[RK3288][Android6.0] Audio录音HAL层的初始化流程分析

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);

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值