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

猜你喜欢

转载自blog.csdn.net/kris_fei/article/details/71706624