美文网首页
Android音视频二:AudioFlinger的启动

Android音视频二:AudioFlinger的启动

作者: 小城哇哇 | 来源:发表于2022-06-10 16:02 被阅读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;
    }
    
    
    

    相关文章

      网友评论

          本文标题:Android音视频二:AudioFlinger的启动

          本文链接:https://www.haomeiwen.com/subject/kkjbmrtx.html