AudioFlinger::MixerThread::threadLoop

本文参考 JianqunXu文章,以及这篇文章,结合目前看的代码进行日常总结。

主要介绍下MixerThread混音回放线程的创建、启动、运行。

1、MixerThread创建

AudioFlinger::openoutput
	| - AudioFlinger::openoutput_l
		| - new MixerThread
sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(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)

{
	//查找outHwDev 
	AudioHwDevice *outHwDev = findSuitableHwDev_l(module, devices);
	
	//······

	//打开outputstream
	status_t status = outHwDev->openOutputStream(
            &outputStream,
            *output,
            devices,
            flags,
            config,
            address.string());

	//······
	
	//根据条件判断,创建不同的线程
	 sp<PlaybackThread> thread;
	 if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
	     thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
	     ALOGV("openOutput_l() created offload output: ID %d thread %p",
	           *output, thread.get());
	 } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
	         || !isValidPcmSinkFormat(config->format)
	         || !isValidPcmSinkChannelMask(config->channel_mask)) {
	     thread = new DirectOutputThread(this, outputStream, *output, devices, mSystemReady);
	     ALOGV("openOutput_l() created direct output: ID %d thread %p",
	           *output, thread.get());
	 } else {
	 	//创建MixerThread
	     thread = new MixerThread(this, outputStream, *output, devices, mSystemReady);
	     ALOGV("openOutput_l() created mixer output: ID %d thread %p",
	           *output, thread.get());
	 }
	 
	 //添加到播放线程表
	 mPlaybackThreads.add(*output, thread);
	 return thread;

}

new MixerThread的参数outputStream

  1. 由moudle和devices找到outHwDev(音频硬件设备)
  2. 打开outHwDev的音频流outputStream

问题

Q: AudioFlinger::openoutput是怎么被调用的
A: AudioPolicyManager的构造函数中
		构造函数先解析XML文件,for循环遍历modules
		1、加载各个module
		2、打开对应的output和input
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
	//······
	
	//解析XML文件
#ifdef USE_XML_AUDIO_POLICY_CONF
    mVolumeCurves = new VolumeCurvesCollection();
    AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
                             mDefaultOutputDevice, speakerDrcEnabled,
                             static_cast<VolumeCurvesCollection *>(mVolumeCurves));
    if (deserializeAudioPolicyXmlConfig(config) != NO_ERROR) {
#else
    mVolumeCurves = new StreamDescriptorCollection();
    AudioPolicyConfig config(mHwModules, mAvailableOutputDevices, mAvailableInputDevices,
                             mDefaultOutputDevice, speakerDrcEnabled);
    if ((ConfigParsingUtils::loadConfig(AUDIO_POLICY_VENDOR_CONFIG_FILE, config) != NO_ERROR) &&
            (ConfigParsingUtils::loadConfig(AUDIO_POLICY_CONFIG_FILE, config) != NO_ERROR)) {
#endif

	//······
	
	//遍历modules,加载函数为loadHwModule
    for (size_t i = 0; i < mHwModules.size(); i++) {
        mHwModules[i]->mHandle = mpClientInterface->loadHwModule(mHwModules[i]->getName());
        
        //······
		
		for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++)
		
		//······
		//打开output
			status_t status = mpClientInterface->openOutput(outProfile->getModuleHandle(),
                                                            &output,
                                                            &config,
                                                            &outputDesc->mDevice,
                                                            address,
                                                            &outputDesc->mLatency,
                                                            outputDesc->mFlags);
		//······
		//打开input
			status_t status = mpClientInterface->openInput(inProfile->getModuleHandle(),
                                                           &input,
                                                           &config,
                                                           &inputDesc->mDevice,
                                                           address,
                                                           AUDIO_SOURCE_MIC,
                                                           AUDIO_INPUT_FLAG_NONE);
	
		//······
}

2、MixerThread启动

2.1 初始化

AudioFlinger::PlaybackThread::onFirstRef
	| - run
void AudioFlinger::PlaybackThread::onFirstRef()
{
    run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
}

注意,在创建mixerthread的时候就已经唤醒了该线程环,不过没有可执行的activetrack,该线程就会沉睡,直到接收到广播被唤醒。

2.2 唤醒

唤醒函数

Track-> strat
	| - addtrack_l
		| - onAddNewTrack_l
			| - broadcast_l
status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused,
                                                    audio_session_t triggerSession __unused)
{
	status = playbackThread->addTrack_l(this);
}


status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
{
	onAddNewTrack_l();
}


void AudioFlinger::PlaybackThread::onAddNewTrack_l()
{
    ALOGV("signal playback thread");
	//发送广播,唤醒线程
    broadcast_l();
}

等待唤醒

bool AudioFlinger::PlaybackThread::threadLoop()
{
	//······
	
    while (!exitPending())  
    {
    	
    	
		//······

        //创建MixerThread时,mActiveTracks肯定是空的,并且当前时间会超出standbyTime
        if ((!mActiveTracks.size() && systemTime() > standbyTime) || isSuspended()) {
               //创建MixerThread时肯定会进入待机 
               if (shouldStandby_l()) {
                       threadLoop_standby();                        
                       mStandby = true;                                                    }
               }
               if (!mActiveTracks.size() && mConfigEvents.isEmpty()) {
                   //然后MixerThread会在这里睡眠等待,直到AudioTrack:: start发送广播唤醒
                      mWaitWorkCV.wait(mLock);
                   standbyTime = systemTime() + standbyDelay;
                   sleepTime = idleSleepTime;
               }

    	//······
		}
	}
}

3、运行

bool AudioFlinger::PlaybackThread::threadLoop()
{
	//处理配置事件;当有配置改变的事件发生时,需要调用 sendConfigEvent_l() 来通知 PlaybackThread,这样 PlaybackThread 才能及时处理配置事件;常见的配置事件是切换音频通路;
   	processConfigEvents_l();
	
	//准备数据
	mMixerStatus = prepareTracks_l(&tracksToRemove);

	//判断是否需要混音
	if (mMixerStatus == MIXER_TRACKS_READY) {
	    // threadLoop_mix() sets mCurrentWriteLength
	    threadLoop_mix();
	} 
	
	//写给HAL
	ret = threadLoop_write();

}


ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
{
	//在向硬件抽象层写数据
	bytesWritten = mOutput->write((char *)mSinkBuffer + offset, mBytesRemaining);
}
Q:在Thread.cpp中只找到了播放线程的threadloop,没有mixerThread的threadloop
A:在这个threadloop函数内包含了多种线程情况,故猜测所有的线程都在这个playbackthread的threadloop中运行(待解决)
已解决:mixerthread继承playbackthread,所以未定义mixerthread::threadloop,那就运行的是playbackthread::threadloop,并且playbackthread::threadloop中也包含了其他线程情况的判断。
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值