Android-AudioFlinger thread讲解

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进行处理
}

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值