本文参考 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
- 由moudle和devices找到outHwDev(音频硬件设备)
- 打开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中也包含了其他线程情况的判断。