AudioRecord一个设备只创建一个线程

不要太相信方法名,尤其是那种看起来很简单的方法名。

在很多博客下面都已经讲过AudioRecord的创建流程,从android_media_AudioRecord.cpp--->AudioRecord--->AudidPolicyService--->AudioPolicyManager--->AudioFlinger

其中过程就不细讲,其中最关键的方法就是getInputForAttr()

前面的调用不提,最终会调用到AudioPolicyManager.cpp的getInputForAttr,这个方法先根据attr的source得到对应的device,然后再用这个device去获取Input,也就是AudioPolicyManager.cpp的getInputForDevice方法:


 audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor> &device,
                                                         audio_session_t session,
                                                         const audio_attributes_t &attributes,
                                                         const audio_config_base_t *config,
                                                         audio_input_flags_t flags,
                                                         const sp<AudioPolicyMix> &policyMix)
 {
     audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
     audio_source_t halInputSource = attributes.source;
     bool isSoundTrigger = false;
     // 特殊源处理(语音识别和电话等)
     if (attributes.source == AUDIO_SOURCE_HOTWORD) {
         ssize_t index = mSoundTriggerSessions.indexOfKey(session);
         if (index >= 0) {
             input = mSoundTriggerSessions.valueFor(session);
             isSoundTrigger = true;
             flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_HW_HOTWORD);
             ALOGV("SoundTrigger capture on session %d input %d", session, input);
         } else {
             halInputSource = AUDIO_SOURCE_VOICE_RECOGNITION;
         }
     } else if (attributes.source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
                audio_is_linear_pcm(config->format)) {
         flags = (audio_input_flags_t)(flags | AUDIO_INPUT_FLAG_VOIP_TX);
     }
 
     // find a compatible input profile (not necessarily identical in parameters)
     sp<IOProfile> profile;
     // sampling rate and flags may be updated by getInputProfile
     uint32_t profileSamplingRate = (config->sample_rate == 0) ?
             SAMPLE_RATE_HZ_DEFAULT : config->sample_rate;
     audio_format_t profileFormat;
     audio_channel_mask_t profileChannelMask = config->channel_mask;
     audio_input_flags_t profileFlags = flags;
     for (;;) {
         profileFormat = config->format; // reset each time through loop, in case it is updated
        // 通过采样率,采样格式等参数去和配置文件夹在的那个匹配来获取Profile
         profile = getInputProfile(device, profileSamplingRate, profileFormat, profileChannelMask,
                                   profileFlags);
         if (profile != 0) {
             break; // success
         } else if (profileFlags & AUDIO_INPUT_FLAG_RAW) {
             profileFlags = (audio_input_flags_t) (profileFlags & ~AUDIO_INPUT_FLAG_RAW); // retry
         } else if (profileFlags != AUDIO_INPUT_FLAG_NONE) {
             profileFlags = AUDIO_INPUT_FLAG_NONE; // retry
         } else { // fail
             ALOGW("%s could not find profile for device %s, sampling rate %u, format %#x, "
                   "channel mask 0x%X, flags %#x", __func__, device->toString().c_str(),
                   config->sample_rate, config->format, config->channel_mask, flags);
             return input;
         }
     }
     // Pick input sampling rate if not specified by client
     uint32_t samplingRate = config->sample_rate;
     if (samplingRate == 0) {
         samplingRate = profileSamplingRate;
     }
 
     if (profile->getModuleHandle() == 0) {
         ALOGE("getInputForAttr(): HW module %s not opened", profile->getModuleName());
         return input;
     }
     // canOpenNewIo:能打开新的IO,加个!,就是不能打开新的IO
     if (!profile->canOpenNewIo()) {
         for (size_t i = 0; i < mInputs.size(); ) {
             sp <AudioInputDescriptor> desc = mInputs.valueAt(i);
             if (desc->mProfile != profile) {
                 i++;
                 continue;
             }
             // if sound trigger, reuse input if used by other sound trigger on same session
             // else
             //    reuse input if active client app is not in IDLE state
             //
             RecordClientVector clients = desc->clientsList();
             bool doClose = false;
             for (const auto& client : clients) {
                 if (isSoundTrigger != client->isSoundTrigger()) {
                     continue;
                 }
                // 语音识别直接复用
                 if (client->isSoundTrigger()) {
                     if (session == client->session()) {
                         return desc->mIoHandle;
                     }
                     continue;
                 }
                // 如果客户端未处于空闲状态,直接重用这个输入
                 if (client->active() && client->appState() != APP_STATE_IDLE) {
                     return desc->mIoHandle;
                 }
                 doClose = true;
             }
             if (doClose) {
                 closeInput(desc->mIoHandle);
             } else {
                 i++;
             }
         }
     }
     // 创建新的输入对象
     sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile, mpClientInterface);
 
     audio_config_t lConfig = AUDIO_CONFIG_INITIALIZER;
     lConfig.sample_rate = profileSamplingRate;
     lConfig.channel_mask = profileChannelMask;
     lConfig.format = profileFormat;
     // 内部会调用audioFlinger来创建新的RecordThread
     status_t status = inputDesc->open(&lConfig, device, halInputSource, profileFlags, &input);
 
     // only accept input with the exact requested set of parameters
     if (status != NO_ERROR || input == AUDIO_IO_HANDLE_NONE ||
         (profileSamplingRate != lConfig.sample_rate) ||
         !audio_formats_match(profileFormat, lConfig.format) ||
         (profileChannelMask != lConfig.channel_mask)) {
         ALOGW("getInputForAttr() failed opening input: sampling rate %d"
               ", format %#x, channel mask %#x",
               profileSamplingRate, profileFormat, profileChannelMask);
         if (input != AUDIO_IO_HANDLE_NONE) {
             inputDesc->close();
         }
         return AUDIO_IO_HANDLE_NONE;
     }
 
     inputDesc->mPolicyMix = policyMix;
 
     addInput(input, inputDesc);
     mpClientInterface->onAudioPortListUpdate();
 
     return input;
 }


===============IOProfile.h======================
 bool canOpenNewIo() {
          if (maxOpenCount == 0 || curOpenCount < maxOpenCount) {
              return true;
          }
          return false;
      }

IOProfile(const String8 &name, audio_port_role_t role)
          : AudioPort(name, AUDIO_PORT_TYPE_MIX, role),
            maxOpenCount(1),
            curOpenCount(0),
            maxActiveCount(1),
            curActiveCount(0) {}
之前我看到canOpenNewIo以为是能否打开新的输入流,我一个设备可以打开多个输入流,所以到这一步肯定返回true,加上!就是false,我就直接略过了,琢磨了好几天还是没想通他怎么实现一个设备只有一个RecordThread的,就再次去看了下,emmmm,就是这个判断:

构造方法那写死了,最大可打开数是1,着只要打开过设备,那肯定会返回false,那第二个用这个设备的录音就肯定会进入这个判断,然后返回AudioInputDescriptor的IOhandle,然后创建一个 RecordClientDescriptor加入到AudioInputDescriptor进行管理。

再讲一下这个返回的IOhandle,它是getInputForAttr 的第二个参数,回到调用的最开始(就是AudioFlinger里面createRecord调用的那个output.inputId

用checkRecordThread_l(output.inputId)的时候就可以拿到AudioInputDescriptor里面创建的那个RecordThread

继续讲讲没啥用的后续过程:,通过checkRecordThread_l拿到RecordThread,然后创建一个RecordTrack,然后把这个track放到recordHandle里保存着,后面start的时候就可以直接对track操作,然后thread会处理这个改变后的track


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值