1. 都有什么thread,有什么区别
class RecordThread; // 录制线程类,由 ThreadBase 派生
class PlaybackThread; // 播放thread的基类
class MixerThread; // 混音回放线程类,由PlaybackThread派生,负责
// 处理标识为 AUDIO_OUTPUT_FLAG_PRIMARY、
// AUDIO_OUTPUT_FLAG_FAST、
// AUDIO_OUTPUT_FLAG_DEEP_BUFFER
//的音频流,MixerThread 可以把多个音轨的数据混音后再输出
class DirectOutputThread; // 直输回放线程类,由 PlaybackThread 派生,负责处理标识为
// AUDIO_OUTPUT_FLAG_DIRECT 的音频流,
// 这种音频流数据不需要软件混音,直接输出到音频设备即可
class OffloadThread; // 硬解回放线程类,由 DirectOutputThread 派生,负责处理
// 标识为 AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD 的音频流,
// 需要输出到硬件解码器,由硬件解码器解码成 PCM 数据
class DuplicatingThread; // 复制回放线程类,由 MixerThread 派生,负责
// 复制音频流数据到其他输出设备,
// 使用场景如主声卡设备、蓝牙耳机设备、USB 声卡设备同时输出
audioflinger class里面有两个vector存放record和playback的threads,
mPlaybackThreads&mRecordThreads. 在AudioFlinger::openInput_l时会更新
mRecordThreads,mRecordThreads.add(*input, thread);
在AudioFlinger::openOutput_l和AudioFlinger::openDuplicateOutput时
会更新mPlaybackThreads,mPlaybackThreads.add(*output, thread);
2. 具体使用哪个thread
// frameworks/av/media/libaudioclient/AudioTrack.cpp
AudioTrack::set(...) // set函数里面调用createTrack_l
AudioTrack::createTrack_l() {
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
// 获取audioflinger
sp<IAudioTrack> track = audioFlinger->createTrack(input, output, &status);
// input里面存放set设置的具体参数
mAudioTrack = track;
// mAudioTrack赋值之后后面就会调用start等接口……
}
// frameworks/av/services/audioflinger/AudioFlinger.cpp
createTrack实现步骤如下:
/*
1. 获取output
2. 获取thread
3. 在当前thread创建track
*/
sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
CreateTrackOutput& output,
status_t *status) {
AudioSystem::getOutputForAttr(&localAttr, &output.outputId,
sessionId, &streamType, clientPid, clientUid,
&input.config, input.flags,&output.selectedDeviceId,
&portId, &secondaryOutputs);
/* 这里会调用audiopolicymanager的很多函数,最终调用openoutput,这里会一直
调用到hal */
PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
// 找到当前播放的thread
track = thread->createTrack_l(......);
}
step1: 获取output
这里有一个问题:output都是哪里来的?
Audio_policy_configuration.xml中每个mixport都是一个output。
status_t AudioPolicyManager::getOutputForAttr:
/*
1. getOutputForAttrInt获取output io_handle信息,device信息
2. 通过output io_handle信息获取outputdescriptor: outputDesc = mOutputs.valueFor(*output)
3. client信息加入outputdescriptor: outputDesc->addClient(clientDesc);
*/
这里重点就是getOutputForAttrInt怎么获取那些信息的
AudioPolicyManager::getOutputForAttrInt(*resultAttr, *output, session, *attr, *stream, uid, *config, *flags, *selectedDeviceId,
bool *isRequestedDeviceForExclusiveUse, secondaryMixes, *outputType)
/*
1. getAudioAttributes(resultAttr, attr, *stream); // 传入attr&stream,获取resultAttr
// 这里如果srcAttr不是null直接 attr赋值 result,否则调用getAttributesForStreamType(srcStream)根据stream获取attr
2. getStreamTypeForAttributes(*resultAttr) // 这里 什么特别 ,就是 resultAttr->mStream返回
3. primaryMix = getOutputForAttr(*resultAttr, uid, *flags, primaryMix, secondaryMixes) // 这里就根据resultAttr获取primaryMix
4. 如果primaryMix不是null就会将usePrimaryOutputFromPolicyMixes设置为true
/* 如果使用usePrimaryOutputFromPolicyMixes
3.1 deviceDesc = getDevice(primaryMix->mDeviceType, primaryMix->mDeviceAddress, AUDIO_FORMAT_DEFAULT)
3.2 policyDesc = primaryMix->getOutput()
3.3 *output = policyDesc->mIoHandle;
3.4 *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
这里成功就回直接返回
*/
4. outputDevices = mEngine->getOutputDevicesForAttributes(*resultAttr, requestedDevice, false);
/*
4.1 strategy = getProductStrategyForAttributes(attributes); // 根据attri选择strategy
// 这里实际就是根据streamtype在audio_policy_engine_product_strategies.xml里面获取strategy
4.2 getDevicesForProductStrategy(strategy)
*/
5. getOutputForDevices(outputDevices, session, *stream, config,flags, resultAttr->flags);
/*
5.0 首先尝试创建direct openDirectOutput(stream, session, &directConfig, *flags, devices, &output);成功就直接返回
5.1 SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs);
5.2 output = selectOutput(outputs, *flags, config->format, channelMask, config->sample_rate);
*/
*/
step2: 拿到output之后获取thread
thread = checkPlaybackThread_l(output.outputId);
AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const {
return mPlaybackThreads.valueFor(output).get();
}
问题: mPlaybackThreads是哪里来的?
AudioFlinger::openOutput_l(audio_module_handle_t module,
audio_io_handle_t *output, // 这里output就是一个handle,只是一个id
audio_config_t *config,
audio_devices_t deviceType,
const String8& address,
audio_output_flags_t flags) {
status_t status = outHwDev->openOutputStream(&outputStream, *output, deviceType, flags, config, address.string());
if (status == NO_ERROR) {
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
// 创建OffloadThread并add进去, mPlaybackThreads.add(*output, thread);
} else if((flags & AUDIO_OUTPUT_FLAG_DIRECT) || !isValidPcmSinkFormat(config->format) || !isValidPcmSinkChannelMask(config->channel_mask)) {
// 创建DirectOutputThread 并add进去, mPlaybackThreads.add(*output, thread);
} else{
// 创建MixerThread并add进去, mPlaybackThreads.add(*output, thread);
}
}
}
step3: 在当前thread创建track:
thread->createTrack_l(......);
// frameworks/av/services/audioflinger/Threads.cpp
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(...) {
track = new Track(this, ......); // 这里会把共享内存当做参数传入,此处的共享内存是input传入的。也就是app调用audiotrack的set函数传入的。
mTracks.add(track); // add之后当调用audioflinger得read/write函数就会循环查找active tracks进行处理
}