Android音视频二:AudioFlinger的启动

2022-06-10  本文已影响0人  小城哇哇

文章开始前面的说明:

  1. 这是我看源码时候认为是流程的地方,代码只是拿了关键代码

main_audioserver的初始化

前面初始化的流程和AudioPolicyService一样的,这里就直接调用构造函数和onFirstRef方法了

# frameworks/av/media/audioserver/main_audioserver.cpp

int main(int argc __unused, char **argv)
{

        // 两个重要的Service初始化(不知道调换顺序会不会有关系?)
        AudioFlinger::instantiate();
        AudioPolicyService::instantiate();

}

构造函数和onFirstRef方法

构造函数和onFirstRef仿佛没做什么事情(也有可能是我没看出来) 流程就这样结束了,AudioFlinger创建出来就等着别人来使用

AudioFlinger::AudioFlinger(): BnAudioFlinger(),省略各种赋值
{
    // 创建设备HAL层工厂
    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    // 创建效果HAL层工厂
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();

}

void AudioFlinger::onFirstRef()
{
    // 音频模式
    mMode = AUDIO_MODE_NORMAL;
    gAudioFlinger = this;
    // HDIL回调? 有什么作用?
    mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
    mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
}


AudioFlinger的loadHwModule

这里接着AudioPliocyService继续进入,总结起来就是(因为openDevice涉及HDIL和HAL层,就先不写了,后面再写)

  1. 先从mAudioHwDevs列表中找,不重复加载,也是做一份缓存
  2. openDevice通过HDIL和HAL交互,最后返回的dev = new DeviceHalHidl() = 设备
  3. 拿到设备之后,对设备进行一些赋值,用flag来记录,且会分配一个handle句柄
  4. 把所有信息封装到AudioHwDevice类,存到mAudioHwDevs列表
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
    // 调用了自己的方法
    return loadHwModule_l(name);
}

audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{
    // 缓存,加载过的不再加载
    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
        if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
            return mAudioHwDevs.keyAt(i);
        }
    }
    
    // 强智能指针 最后结果是 dev = new DeviceHalHidl()
    sp<DeviceHalInterface> dev;

    // 重要方法 加载硬件设备 --> mDevicesFactoryHal = DevicesFactoryHalHybrid --> DevicesFactoryHalHidl
    // 和HIDL相关,先放着 ,方法执行openDevice完后会得到 dev = new DeviceHalHidl()
    int rc = mDevicesFactoryHal->openDevice(name, &dev);

    mHardwareStatus = AUDIO_HW_INIT;
    // 检查设备是否正常初始化
    rc = dev->initCheck();
    mHardwareStatus = AUDIO_HW_IDLE;


    AudioHwDevice::Flags flags = static_cast<AudioHwDevice::Flags>(0);
    // 第一次加载获取的主设备值
    if (0 == mAudioHwDevs.size()) {
        mHardwareStatus = AUDIO_HW_GET_MASTER_VOLUME;
        float mv;
        if (OK == dev->getMasterVolume(&mv)) {
            // 主音量
            mMasterVolume = mv;
        }

        mHardwareStatus = AUDIO_HW_GET_MASTER_MUTE;
        bool mm;
        if (OK == dev->getMasterMute(&mm)) {
            // 是否静音
            mMasterMute = mm;
        }
    }
    // 用每一位对应一个属性值,最后全在flag中
     mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME;
    if (OK == dev->setMasterVolume(mMasterVolume)) {
        flags = static_cast<AudioHwDevice::Flags>(flags |
                AudioHwDevice::AHWD_CAN_SET_MASTER_VOLUME);
    }

    mHardwareStatus = AUDIO_HW_SET_MASTER_MUTE;
    if (OK == dev->setMasterMute(mMasterMute)) {
        flags = static_cast<AudioHwDevice::Flags>(flags |
                AudioHwDevice::AHWD_CAN_SET_MASTER_MUTE);
    }
    // 分配一个句柄/id
    audio_module_handle_t handle = (audio_module_handle_t) nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
    // 相当于包装 把所有相关的信息保存起来在AudioHwDevice类中管理
    AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);
    // 做一个保存,handle为设备句柄,看作id,下标
    mAudioHwDevs.add(handle, audioDevice);
    // 返回句柄,有句柄就可以在mAudioHwDevs中找到你想要的device
    return handle;

}


AudioFlinger的openOutput

总得来说就是两句话:

  1. 通过HIDL打开设备的输出流
  2. 根据流的类型创建相应的Thread,且保存在mPlaybackThreads
// 打开输出流
status_t AudioFlinger::openOutput(audio_module_handle_t module,
                                  audio_io_handle_t *output,
                                  audio_config_t *config,
                                  const sp<DeviceDescriptorBase>& device,
                                  uint32_t *latencyMs,
                                  audio_output_flags_t flags)
{
    // 调用内部方法,得到一个播放thraed
    sp<ThreadBase> thread = openOutput_l(module, output, config, deviceType, address, flags);
    if (thread != 0) {
        if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
            // latency传输延迟
            *latencyMs = playbackThread->latency();
            // notify client processes of the new output creation
            // 通知客户端进程创建了新的输出
            playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
        }
    }
    return NO_INIT;
}


# 继续看openOutput_l

sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
                                                        audio_io_handle_t *output,
                                                        audio_config_t *config,
                                                        audio_devices_t deviceType,
                                                        const String8& address,
                                                        audio_output_flags_t flags)
{
    // 找到合适输出设备
    AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);

    // 修改状态
    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;

    
    AudioStreamOut *outputStream = NULL;
    // 输出流,最终还是通过HIDL调用打开输出流
    status_t status = outHwDev->openOutputStream(
            &outputStream,
            *output,
            deviceType,
            flags,
            config,
            address.string());

    mHardwareStatus = AUDIO_HW_IDLE;

    if (status == NO_ERROR) {
        if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
           ....
        } else {
            // 创建播放线程名,根据类型去创建类型
            sp<PlaybackThread> thread;
            if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
                // offloadThread 未经过软件解码的,要输出的硬件解码器解码
                thread = new OffloadThread(this, outputStream, *output, mSystemReady);
            } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                    || !isValidPcmSinkFormat(config->format)
                    || !isValidPcmSinkChannelMask(config->channel_mask)) {
                // DirectOutputThread 不需要软件混音,自己输出到设备
                thread = new DirectOutputThread(this, outputStream, *output, mSystemReady);
            } else {
                // MixerThread 混音后输出,通常都是创建这个
                thread = new MixerThread(this, outputStream, *output, mSystemReady);
            }
            // 保存所有thread到mPlaybackThreads列表
            mPlaybackThreads.add(*output, thread);
            mPatchPanel.notifyStreamOpened(outHwDev, *output);
             // 返回给调用者
            return thread;
        }
    }
    return 0;
}


上一篇下一篇

猜你喜欢

热点阅读