Audio outStream and Volume Gain

本文深入解析Android音频HAL层,涵盖HAL、Kernel与Codec寄存器关键概念。介绍HAL硬件层结构,包括audio_module、audio_hw_device及hw_module_methods_t,探讨RK3399项目中的音频实现,并简述Kernel层面的ALSA驱动。

Audio Stream and Volume Gain

音频outstream简介

audio框架在Android系统中 占据很大用户市场,音频的复杂,Android框架一直在调整中。
看一张高通的音频各个场景的路径:
这里写图片描述

这张图片来着高通,各个芯片方案路线基本一致。对于HAL上层已经在前面两篇文章进行了分析,这篇重要分析HAL、 Kernel、CODEC寄存器。
用项目RK3399 来理解。

HAL

HAL hardware Layer是与kernel最接近的一层,通过IOCTL与kernel进行通信。将对应的操作封装到厂商动态链接库。
简述如何实现HAL层模块。
先简单介绍重要的三个结构体:
hw_module_t: 描述硬件模块基类
hw_device_t: 描述硬件设备基类
hw_module_methods_t: 打开硬件模块种包含的硬件设备,获得指向硬件设备结构体的指针。
这里写图片描述

Audio HAL实现步骤

1 struct audio_module

/**
 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
 * and the fields of this data structure must begin with hw_module_t
 * followed by module specific information.
 */
struct audio_module {
    struct hw_module_t common;
};

定义 audio_module 的 HAL_MODULE_INFO_SYM 变量

struct audio_module HAL_MODULE_INFO_SYM = {
    .common = {
        .tag = HARDWARE_MODULE_TAG,
        .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
        .hal_api_version = HARDWARE_HAL_API_VERSION,
        .id = AUDIO_HARDWARE_MODULE_ID,
        .name = "QCOM Audio HAL",
        .author = "The Linux Foundation",
        .methods = &hal_module_methods,
    },
};

2 struct audio_hw_device

struct audio_hw_device {
    /**
     * Common methods of the audio device.  This *must* be the first member of audio_hw_device
     * as users of this structure will cast a hw_device_t to audio_hw_device pointer in contexts
     * where it's known the hw_device_t references an audio_hw_device.
     */
    struct hw_device_t common;



    /** set the audio volume of a voice call. Range is between 0.0 and 1.0 */
    int (*set_voice_volume)(struct audio_hw_device *dev, float volume);


    int (*set_master_volume)(struct audio_hw_device *dev, float volume);


    int (*get_master_volume)(struct audio_hw_device *dev, float *volume);


    int (*set_mode)(struct audio_hw_device *dev, audio_mode_t mode);

    /* mic mute */
    int (*set_mic_mute)(struct audio_hw_device *dev, bool state);
    int (*get_mic_mute)(const struct audio_hw_device *dev, bool *state);

    /* set/get global audio parameters */
    int (*set_parameters)(struct audio_hw_device *dev, const char *kv_pairs);


    char * (*get_parameters)(const struct audio_hw_device *dev,
                             const char *keys);


    size_t (*get_input_buffer_size)(const struct audio_hw_device *dev,
                                    const struct audio_config *config);



    int (*open_output_stream)(struct audio_hw_device *dev,
                              audio_io_handle_t handle,
                              audio_devices_t devices,
                              audio_output_flags_t flags,
                              struct audio_config *config,
                              struct audio_stream_out **stream_out,
                              const char *address);

    void (*close_output_stream)(struct audio_hw_device *dev,
                                struct audio_stream_out* stream_out);

    /** This method creates and opens the audio hardware input stream */
    int (*open_input_stream)(struct audio_hw_device *dev,
                             audio_io_handle_t handle,
                             audio_devices_t devices,
                             struct audio_config *config,
                             struct audio_stream_in **stream_in,
                             audio_input_flags_t flags,
                             const char *address,
                             audio_source_t source);

    void (*close_input_stream)(struct audio_hw_device *dev,
                               struct audio_stream_in *stream_in);
    int (*set_master_mute)(struct audio_hw_device *dev, bool mute);
    int (*get_master_mute)(struct audio_hw_device *dev, bool *mute);
    ...
};

audio_hw_device 的定义中,第一个结构体成员就是 struct hw_device_t 类型的,而其他的结构体成员都是函数指针, open_output_stream 函数就是用来打开播放音频的扬声器设备,open_input_stream 函数则是用来打开录音用的麦克风设备。

3 struct hw_module_methods_t 函数列表

hardware\qcom\audio\hal\audio_hw.c

static struct hw_module_methods_t hal_module_methods = {
    .open = adev_open,
};

hardware\qcom\audio\hal\audio_hw.c

static int adev_open(const hw_module_t *module, const char *name,
                     hw_device_t **device)
{
    int i, ret;
    /hw_device 初始化
    adev->device.common.tag = HARDWARE_DEVICE_TAG;
    adev->device.common.version = AUDIO_DEVICE_API_VERSION_2_0;
    adev->device.common.module = (struct hw_module_t *)module;
    adev->device.common.close = adev_close;
    /函数列表...
    adev->device.init_check = adev_init_check;
    adev->device.set_voice_volume = adev_set_voice_volume;
    adev->device.set_master_volume = adev_set_master_volume;
    adev->device.get_master_volume = adev_get_master_volume;
    adev->device.set_master_mute = adev_set_master_mute;
    adev->device.get_master_mute = adev_get_master_mute;
    adev->device.set_mode = adev_set_mode;
    adev->device.set_mic_mute = adev_set_mic_mute;
    adev->device.get_mic_mute = adev_get_mic_mute;
    adev->device.set_parameters = adev_set_parameters;
    adev->device.get_parameters = adev_get_parameters;
    adev->device.get_input_buffer_size = adev_get_input_buffer_size;
    adev->device.open_output_stream = adev_open_output_stream;
    adev->device.close_output_stream = adev_close_output_stream;
    adev->device.open_input_stream = adev_open_input_stream;
    adev->device.close_input_stream = adev_close_input_stream;
    adev->device.dump = adev_dump;
    ...
    return 0

看Audio HAL层时,按照HAL层的三个结构体来看,此方法推广到其它HAL定义。

kernel

这里不再分析ALSA中 codec driver ,platform driver 和machine driver .

来两个其他case

这里写图片描述

这里写图片描述

这里写图片描述

<think>我们正在讨论AudioFlinger::openOutput_l函数。注意:这个函数是openOutput的内部锁定版本,通常在持有AudioFlinger锁的情况下调用。 根据Android源码,openOutput_l负责实际创建输出线程并管理相关资源。 由于用户要求中文回答,我们将使用中文进行解析。</think>在 Android 音频系统中,**`AudioFlinger::openOutput_l()`** 是 `openOutput()` 的内部锁定版本,负责在持有互斥锁的情况下执行核心输出流创建操作。以下是深度解析: --- ### 一、方法定位与作用 **核心功能**:在持有 `mLock` 的情况下安全创建音频输出流 **与 `openOutput()` 的关系**: ```mermaid graph TB A[AudioFlinger::openOutput] --> B[获取mLock] B --> C[调用openOutput_l] C --> D[执行核心创建逻辑] D --> E[释放mLock] ``` --- ### 二、关键实现细节 #### 1. 线程安全保护 ```cpp status_t AudioFlinger::openOutput_l(audio_module_handle_t module, audio_io_handle_t *output, audio_config_t *config, ...) { // 在持有mLock的状态下执行 AutoMutex lock(mLock); // 实际上锁已在调用方获取 // 核心创建逻辑... } ``` #### 2. 输出流复用机制 ```cpp // 检查是否存在兼容的输出线程 for (size_t i = 0; i < mPlaybackThreads.size(); i++) { sp<PlaybackThread> thread = mPlaybackThreads.valueAt(i); if (thread->supportsConfig_l(config, devices, flags)) { *output = thread->id(); // 返回现有句柄 return ALREADY_EXISTS; // 避免重复创建 } } ``` #### 3. 硬件能力适配 ```cpp // 自动降级处理 if (halDevice->open_output_stream(...) != NO_ERROR) { if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { config->format = AUDIO_FORMAT_PCM_16_BIT; // 强制降级 config->sample_rate = 48000; retryOpen(); // 重试打开 } } ``` --- ### 三、核心创建流程 #### 1. HAL 层交互 ```cpp audio_hw_device_t *hwDev = mDevices.getDevice(module)->hwDevice(); audio_stream_out_t *outStream = nullptr; int status = hwDev->open_output_stream( hwDev, nextUniqueId(), devices, flags, config, &outStream, // 输出流指针 address.string() ); ``` #### 2. 线程类型选择 ```cpp sp<PlaybackThread> thread; if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { thread = new OffloadThread(this, outStream); // 硬件卸载 } else if (flags & AUDIO_OUTPUT_FLAG_DIRECT) { thread = new DirectOutputThread(this, outStream); // 直通输出 } else if ((flags & AUDIO_OUTPUT_FLAG_FAST) && mFastMixerEnabled) { thread = new FastMixerThread(this, outStream); // 低延迟 } else { thread = new MixerThread(this, outStream); // 普通混音 } ``` #### 3. 资源注册 ```cpp // 分配唯一ID并注册 *output = nextUniqueId(); mPlaybackThreads.add(*output, thread); // 初始化线程 thread->setMasterVolume(mMasterVolume); thread->setMasterMute(mMasterMute); thread->setStreamVolume(AUDIO_STREAM_MUSIC, 1.0f); // 默认音量 ``` --- ### 四、特殊场景处理 #### 1. 多客户端共享 ```cpp // 设置共享计数 if (thread->isShared()) { thread->incSharedCount(); } else { thread->setShared(true); } ``` #### 2. 动态重配置 ```cpp // 检查是否需要重配置现有线程 if (thread->canUpdateConfig(config)) { thread->reconfigure(config); // 动态更新参数 return NO_ERROR; } ``` #### 3. 资源监控 ```cpp // 检查系统负载 if (mTotalMemory + thread->getMemoryUsage() > MAX_MEMORY) { ALOGW("内存不足,拒绝创建新线程"); return NO_MEMORY; } mTotalMemory += thread->getMemoryUsage(); // 更新内存计数 ``` --- ### 五、性能关键路径优化 #### 1. 热路径优化 ```cpp // 避免在关键路径分配内存 thread->preallocateBuffers(); // 预分配缓冲区 // 禁用调试日志 #ifndef DEBUG thread->disableLogging(); #endif ``` #### 2. 实时性保障 ```cpp // 设置实时优先级 thread->setPriority(PRIORITY_URGENT_AUDIO); // 绑定到大核CPU thread->bindToBigCores(); ``` #### 3. 延迟敏感处理 ```cpp // FAST线程特殊处理 if (flags & AUDIO_OUTPUT_FLAG_FAST) { thread->setWarmupTime(0); // 取消预热 thread->setMinimumSleepTime(0); // 最小休眠时间为0 } ``` --- ### 六、调试与问题排查 #### 1. 状态追踪 ```cpp // 添加调试标记 thread->setCreationFlags(flags); thread->setCreationConfig(*config); ``` #### 2. 资源泄漏检测 ```cpp // 注册析构回调 thread->addDestructionCallback([](PlaybackThread* t) { mTotalMemory -= t->getMemoryUsage(); // 自动更新内存计数 }); ``` #### 3. 常见错误处理 | 错误场景 | 检测方法 | 处理措施 | |---------|---------|----------| | **HAL层崩溃** | 捕获SIGSEGV | 重启音频服务 | | **配置冲突** | 检查mPlaybackThreads | 返回ALREADY_EXISTS | | **资源耗尽** | 内存/线程数监控 | 返回NO_MEMORY |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lin_AIOS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值