AudioFlinger::MixerThread::threadLoop

本文深入探讨AudioFlinger::MixerThread的threadLoop过程,涉及音频输出、缓冲区管理和多线程播放的关键细节。

1、进程的创建

int AudioFlinger::openOutput(uint32_t *pDevices,

                                uint32_t *pSamplingRate,

                                uint32_t *pFormat,

                                uint32_t *pChannels,

                                uint32_t *pLatencyMs,

                                uint32_t flags)

{
if (output != 0) {

        thread = new MixerThread(this, output, ++mNextThreadId);

        }
}

2、进程的启动

void AudioFlinger::PlaybackThread::onFirstRef()

{

    const size_t SIZE = 256;

    char buffer[SIZE];

 

    snprintf(buffer, SIZE, "Playback Thread %p", this);

    run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);

}

3、进程的运行

bool AudioFlinger::MixerThread::threadLoop()
{
    Vector< sp<Track> > tracksToRemove;
    uint32_t mixerStatus = MIXER_IDLE;
    nsecs_t standbyTime = systemTime();
    size_t mixBufferSize = mFrameCount * mFrameSize;
    // FIXME: Relaxed timing because of a certain device that can't meet latency
    // Should be reduced to 2x after the vendor fixes the driver issue
    nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
    nsecs_t lastWarning = 0;
    bool longStandbyExit = false;
    uint32_t activeSleepTime = activeSleepTimeUs();//当有活跃音轨时需要sleep的时间
    uint32_t idleSleepTime = idleSleepTimeUs();//当mixer处于idle状态,没有活跃音轨时需要sleep的时间
    uint32_t sleepTime = idleSleepTime;//真正需要sleep时候的时间,初始化为idle状态的时间
    Vector< sp<EffectChain> > effectChains;

    while (!exitPending())//exitPending是每个进程的一个开关标志,创建该进程是初始化为false,所以这里while一直条件为真,进程一直运行
    {
        processConfigEvents();//处理广播消息事件

	//初始化mixerStatus, 该变量有三种状态:idle enabled ready 
        mixerStatus = MIXER_IDLE;
        { // scope for mLock

            Mutex::Autolock _l(mLock);
		//如果有新参数,设置相应的变量值
		//新参数包括:采样率、格式、通道数、帧数、路由情况
		//相应的变量值包括:周期大小、缓存大小等
            if (checkForNewParameters_l()) {
                mixBufferSize = mFrameCount * mFrameSize;
                // FIXME: Relaxed timing because of a certain device that can't meet latency
                // Should be reduced to 2x after the vendor fixes the driver issue
                maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
                activeSleepTime = activeSleepTimeUs();
                idleSleepTime = idleSleepTimeUs();
            }
		//找出活跃音轨数组,活跃音轨个数是硬件退出standby的一个条件
            const SortedVector< wp<Track> >& activeTracks = mActiveTracks;

            // put audio hardware into standby after short delay
            if UNLIKELY((!activeTracks.size() && systemTime() > standbyTime) ||
                        mSuspended) {
           //两种情况需要硬件进入standby
           //第一:没有活跃音轨而且standbyTime  过期
           //第二:需要Suspend
                if (!mStandby) {//状态为standby
                    LOGV("Audio hardware entering standby, mixer %p, mSuspended %d\n", this, mSuspended);
                    mOutput->standby();
                    mStandby = true;
                    mBytesWritten = 0;
                }
                //没有活跃音轨并且没有广播消息
                if (!activeTracks.size() && mConfigEvents.isEmpty()) {
                    // we're about to wait, flush the binder command buffer
                    IPCThreadState::self()->flushCommands();

                    if (exitPending()) break;

                    // wait until we have something to do...
                    LOGV("MixerThread %p TID %d going to sleep\n", this, gettid());
                    mWaitWorkCV.wait(mLock);//等待广播消息,包括配置参数、活跃音轨添加等消息
                    LOGV("MixerThread %p TID %d waking up\n", this, gettid());

                    if (mMasterMute == false) {
                        char value[PROPERTY_VALUE_MAX];
                        property_get("ro.audio.silent", value, "0");
                        if (atoi(value)) {
                            LOGD("Silence is golden");
                            setMasterMute(true);
                        }
                    }

                    standbyTime = systemTime() + kStandbyTimeInNsecs;
                    sleepTime = idleSleepTime;
                    continue;
                }
            }
            //为音轨混音做准备,返回值作为mixerStatus
            mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);

            // prevent any changes in effect chain list and in each effect chain
            // during mixing and effect process as the audio buffers could be deleted
            // or modified if an effect is created or deleted
            lockEffectChains_l(effectChains);
       }
        //只有当音轨准备就绪,才能进入到混音处理函数process
        if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
            // mix buffers...
            mAudioMixer->process();
            sleepTime = 0;//sleepTime设置为零表示有数据需要写入到硬件层的缓冲中
            standbyTime = systemTime() + kStandbyTimeInNsecs;
            //TODO: delay standby when effects have a tail
        } else {
            // If no tracks are ready, sleep once for the duration of an output
            // buffer size, then write 0s to the output
            if (sleepTime == 0) {//如果音轨还未准备好,但是有数据需要传输,说明需要播放,就sleep一个周期的时间
                if (mixerStatus == MIXER_TRACKS_ENABLED) {
                    sleepTime = activeSleepTime;//这个是硬件延时周期的一半时间,(mOutput->latency() * 1000) / 2;
                } else {
                    sleepTime = idleSleepTime;//这个是半个buffer传输时间,1024帧的44100采样率就是11.7ms
                }
            } else if (mBytesWritten != 0 ||
                       (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
                memset (mMixBuffer, 0, mixBufferSize);
                sleepTime = 0;
                LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
            }
            // TODO add standby time extension fct of effect tail
        }

        if (mSuspended) {
            sleepTime = suspendSleepTimeUs();
        }
        // sleepTime == 0 means we must write to audio hardware
        if (sleepTime == 0) {
             for (size_t i = 0; i < effectChains.size(); i ++) {
                 effectChains[i]->process_l();
             }
             // enable changes in effect chain
             unlockEffectChains(effectChains);

            mLastWriteTime = systemTime();
            mInWrite = true;
            mBytesWritten += mixBufferSize;

            int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);//这里是实际在向硬件抽象层写数据,返回写了多少byte数据
            if (bytesWritten < 0) mBytesWritten -= mixBufferSize;
            mNumWrites++;
            mInWrite = false;
            nsecs_t now = systemTime();
            nsecs_t delta = now - mLastWriteTime;//写数据花了多少时间
            if (delta > maxPeriod) {//写的太慢!maxPeriod是按FramCount和SampleRate算出来的,和硬件延时有关,即I2S播放完DMAbuffer数据需要的时间
                mNumDelayedWrites++;
                if ((now - lastWarning) > kWarningThrottle) {//超过警告时间上限,不能忍受,容易导致断音,必须输出log告知开发者
                    LOGW("write blocked for %llu msecs, %d delayed writes, thread %p",
                            ns2ms(delta), mNumDelayedWrites, this);
                    lastWarning = now;
                }
                if (mStandby) {
                    longStandbyExit = true;
                }
            }
            mStandby = false;
        } else {//没有数据需要传输,休眠了
            // enable changes in effect chain
            unlockEffectChains(effectChains);
            usleep(sleepTime);
        }

        // finally let go of all our tracks, without the lock held
        // since we can't guarantee the destructors won't acquire that
        // same lock.
        tracksToRemove.clear();

        // Effect chains will be actually deleted here if they were removed from
        // mEffectChains list during mixing or effects processing
        effectChains.clear();
    }

    if (!mStandby) {
        mOutput->standby();
    }

    LOGV("MixerThread %p exiting", this);
    return false;
}


<think>我们正在讨论Android音频系统中的AudioFlinger::openOutput方法。 根据要求,回答需包含详细解析,并在最后提出3-5个相关问题,且第一行必须为"§§相关问题§§"。 注意:用户要求使用中文回答,且回答格式必须严格遵守示例。 现在开始回答:</think>在 Android 音频系统中,**`AudioFlinger::openOutput()`** 是音频服务核心方法,负责创建和管理物理音频输出通道。以下是深度解析: --- ### 一、功能定位与调用流程 **核心作用**:创建音频输出流并绑定到硬件设备 **调用路径**: ```mermaid graph LR A[AudioPolicyManager::openOutput] --> B[AudioFlinger::openOutput] B --> C[加载HAL层驱动] C --> D[创建PlaybackThread] ``` --- ### 二、函数原型与参数 ```cpp status_t AudioFlinger::openOutput( audio_module_handle_t module, // 硬件模块句柄 audio_io_handle_t *output, // 输出流句柄(输出参数) audio_config_t *config, // 音频配置参数 audio_devices_t *devices, // 目标设备类型 const String8& address, // 设备物理地址 audio_output_flags_t flags, // 输出标志位 audio_port_handle_t *selectedDeviceId // 选择的设备ID ) ``` --- ### 三、核心实现流程 #### 1. 硬件模块加载 ```cpp // 获取对应的HAL模块 sp<AudioHwDevice> hwDevice = mDevices.getDevice(module); if (hwDevice == 0) { return BAD_VALUE; // 模块不存在 } ``` #### 2. HAL层输出流创建 ```cpp // 调用HAL接口 audio_hw_device_t *halDevice = hwDevice->hwDevice(); audio_stream_out_t *halStream = nullptr; int status = halDevice->open_output_stream( halDevice, nextUniqueId(), // 生成唯一ID devices, flags, config, &halStream, address.string() ); ``` #### 3. 创建播放线程 根据输出标志位选择线程类型: ```cpp sp<PlaybackThread> thread; switch (flags & AUDIO_OUTPUT_FLAG_MASK) { case AUDIO_OUTPUT_FLAG_FAST: thread = new FastMixerThread(this, outputConfig); // 低延迟线程 break; case AUDIO_OUTPUT_FLAG_DIRECT: thread = new DirectOutputThread(this, outputConfig); // 直通输出 break; default: thread = new MixerThread(this, outputConfig); // 普通混音线程 } ``` #### 4. 资源注册 ```cpp // 注册到全局管理 *output = nextUniqueId(); mPlaybackThreads.add(*output, thread); thread->setHalStream(halStream); // 绑定HAL流 ``` --- ### 四、关键数据结构 #### 1. PlaybackThread 层级 ```cpp class PlaybackThread : public ThreadBase { virtual void threadLoop(); // 核心音频处理循环 }; class MixerThread : public PlaybackThread; // 普通混音 class FastMixerThread : public MixerThread; // 低延迟 class DirectOutputThread : public PlaybackThread; // 直通输出 ``` #### 2. HAL 层接口 ```cpp struct audio_hw_device { 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 ); }; ``` --- ### 五、特殊场景处理 #### 1. 多客户端共享输出 ```cpp // 当多个应用使用相同配置时 if (existingThread = findExistingOutput(config, flags)) { *output = existingThread->id(); return ALREADY_EXISTS; // 返回现有句柄 } ``` #### 2. 动态重配置 ```cpp // 设备不支持配置时自动降级 if (status == BAD_VALUE) { config->format = AUDIO_FORMAT_PCM_16_BIT; // 降级为16位 config->sample_rate = 48000; // 降级采样率 retryOpenOutput(); // 重试打开 } ``` #### 3. 资源限制处理 ```cpp // 检查系统资源限制 if (mPlaybackThreads.size() >= MAX_PLAYBACK_THREADS) { return NO_MEMORY; // 拒绝创建新线程 } ``` --- ### 六、性能优化机制 #### 1. 线程优先级提升 ```cpp // 设置实时优先级 thread->setPriority(PRIORITY_URGENT_AUDIO); // -19优先级 ``` #### 2. 内存池预分配 ```cpp // 为FAST线程预分配内存 if (flags & AUDIO_OUTPUT_FLAG_FAST) { thread->allocateFastBuffer(1024); // 预分配1KB } ``` #### 3. 热路径优化 ```cpp // 关键路径禁用锁 AutoMutex lock(mLock); if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) { lock.unlock(); // 非关键路径释放锁 } ``` --- ### 七、调试与问题排查 #### 1. 状态监控 ```bash adb shell dumpsys media.audio_flinger # 输出片段: Output thread 0xab34: Stream type: fast Sample rate: 48000 Hz ``` #### 2. 延迟测量 ```cpp // 测量输出延迟 audio_stream_out_t *stream = thread->halStream(); uint32_t latency = stream->get_latency(stream); ALOGI("Output latency: %ums", latency); ``` #### 3. 常见错误处理 | 错误码 | 原因 | 解决方案 | |-------|------|----------| | **PERMISSION_DENIED** | 无权限访问设备 | 检查权限配置 | | **NO_INIT** | HAL未初始化 | 验证HAL层实现 | | **BAD_VALUE** | 无效参数 | 检查音频配置 |
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值