我是靠谱客的博主 爱笑早晨,最近开发中收集的这篇文章主要介绍Android-MediaRecorder之setAudioSource,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  上一篇文章介绍了怎么通过MediaRecorderlu录制音频,详见(https://blog.csdn.net/cheriyou_/article/details/105544086

在创建MediaRecorder之后第一步就是设置AudioSource,那么audiosource具体是做什么用的?今天就来研究下。

1. 首先看看setAudioSource的过程

status_t MediaRecorder::setAudioSource(int as)

MediaRecorderClient::setAudioSource(int as)

status_t StagefrightRecorder::setAudioSource(audio_source_t as) {
    mAudioSource = as; // 在此把app设置流类型赋值给mAudioSource
}

  从上面的代码可以看出,AudioSource最终就是设置给了StagefrightRecorder的mAudioSource。然后,StagefrightRecorder中会根据mAudioSource去创建audioSource……下面接着看代码。

2. StagefrightRecorder::createAudioSource()

sp<MediaCodecSource> StagefrightRecorder::createAudioSource() {
    sp<AudioSource> audioSource = AVFactory::get()->createAudioSource(mAudioSource, ......); 
    // 根据type创建audioSource
    
    sp<MediaCodecSource> audioEncoder = MediaCodecSource::Create(mLooper, format, audioSource); 
    // 创建audioEncoder(mediacodec)时把audioSource当做参数传入
    mAudioSourceNode = audioSource; // 把audioSource赋值给mAudioSourceNode
}

 AudioSource* AVFactory::createAudioSource(audio_source_t inputSource, ......){
     return new AudioSource(inputSource, ......);
 }

 // frameworks/av/media/libstagefright/AudioSource.cpp
 AudioSource::AudioSource(audio_source_t inputSource,  ......){
     mRecord = new AudioRecord(inputSource, ......);
 }

 //frameworks/av/media/libaudioclient/AudioRecord.cpp
 AudioRecord::AudioRecord(audio_source_t inputSource,  ......){
     (void)set(inputSource,  ......);
 }

 status_t AudioRecord::set(audio_source_t inputSource,......){
     mAttributes.source = inputSource; // 此处把inputSource赋值给mAttributes.source
 }

     整个create过程实际就是把audioSource设置给了mAttributes.source。

  看到这里有一个疑问,mAttributes是什么?有什么作用?继续往下看。

3. mAttributes的用法

 status_t AudioRecord::createRecord_l(const Modulo<uint32_t> &epoch, const String16& opPackageName)
{
   input.attr = mAttributes; // 把mAttributes赋值给input.attr
     record = audioFlinger->createRecord(input,output,&status); // 然后根据input创建record
     mAudioRecord = record;
}

 sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& input,CreateRecordOutput& output,status_t *status)
{
     lStatus = AudioSystem::getInputForAttr(&input.attr, &output.inputId,input.riid,sessionId,.......);
     // 获取到input等信息之后再创建record,此处略
}

  可以看到,这里先把mAttributes赋值给了input.attr,然后在getInputForAttr时把input.attr传入。下面看看getInputForAttr怎么获取input信息的。

4. getInputForAttr怎么获取的input信息

// frameworks/av/media/libaudioclient/AudioSystem.cpp
AudioSystem::getInputForAttr ---->  aps->getInputForAttr(attr, input, riid, session, pid, uid, ......);
// frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,audio_io_handle_t *input,......)
{
    audio_attributes_t attributes = *attr;
    device = mEngine->getInputDeviceForAttributes(attributes, &policyMix); // 根据inputSource获取device
    *input = getInputForDevice(device, session, attributes, config, flags, policyMix); // 根据device获取input
}

    整个过程分为两步,第一步是根据inputsource获取device,第二步是根据device获取input。继续往下看。

5. 根据inputsource获取device

// frameworks/av/services/audiopolicy/enginedefault/src/Engine.cpp
sp<DeviceDescriptor> Engine::getInputDeviceForAttributes(const audio_attributes_t &attr,sp<AudioPolicyMix> *mix) const{
    sp<DeviceDescriptor> device = findPreferredDevice(inputs, attr.source, availableInputDevices);
    device = policyMixes.getDeviceAndMixForInputSource(attr.source, availableInputDevices, mix);
    audio_devices_t deviceType =  getDeviceForInputSource(attr.source);
    return availableInputDevices.getDevice(deviceType,String8(address.c_str()),AUDIO_FORMAT_DEFAULT);
}
audio_devices_t Engine::getDeviceForInputSource(audio_source_t inputSource) const{
    // 此函数直接根据inputSource对应devicetype
    switch (inputSource) {
    case AUDIO_SOURCE_DEFAULT:
    case AUDIO_SOURCE_MIC:
    if (property_get_bool("vendor.audio.enable.mirrorlink", false) &&
        (availableDeviceTypes & AUDIO_DEVICE_IN_REMOTE_SUBMIX)) {
        device = AUDIO_DEVICE_IN_REMOTE_SUBMIX;
    } else if (......
    }
    .......  
}

     这里没什么特别的,就是规定好的一一对应。

6. 根据device获取input

audio_io_handle_t AudioPolicyManager::getInputForDevice(const sp<DeviceDescriptor> &device,......){
    profileFormat = config->format;
    // 先获取profile
    profile = getInputProfile(device, profileSamplingRate, profileFormat, profileChannelMask,profileFlags); 
    // 然后创建inputDesc
    sp<AudioInputDescriptor> inputDesc = new AudioInputDescriptor(profile, mpClientInterface); 
    // 最后open input
    status_t status = inputDesc->open(&lConfig, device, halInputSource, profileFlags, &input); 
    return input;
}

     这里又分了三个步骤,我们重点看下第一个步骤,怎么根据device获取profile。

sp<IOProfile> AudioPolicyManager::getInputProfile(const sp<DeviceDescriptor> &device,uint32_t& samplingRate, ......){
    // audio_policy_configuration.xml此函数的信息都在这个xml里面获取。
    for (const auto& hwModule : mHwModules) { 
    // 遍历所有mHwModules,mHwModules是从audio_policy_configuration.xml里面解析到的。具体有: primary/a2dp/usb等module
        for (const auto& profile : hwModule->getInputProfiles()) {
        // 遍历所有的InputProfiles,也是从audio_policy_configuration.xml中解析到的。
              if (profile->isCompatibleProfile(DeviceVector(device), samplingRate, // 找一个最合适的profile
                   &samplingRate  /*updatedSamplingRate*/,
                   format,
                   &format,       /*updatedFormat*/
                   channelMask,
                   &channelMask   /*updatedChannelMask*/,
                   (audio_output_flags_t) flags,
                   true /*exactMatchRequiredForInputFlags*/,
                   true,
                   rue)) {
                return profile;
            }
        }
    }
}

  到这里整个过程基本就结束了,接下来就是创建input,track等,没什么特别的,此处不再赘述。

 

   最后看看audio_policy_configuration.xml这个文件的内容:

1. 看devices对应的route

// eg: device = AUDIO_DEVICE_IN_BUILTIN_MIC ("Built-In Mic")
</devicePorts>
 <routes>
                <route type="mix" sink="fast input"
                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In,Wired Headset Mic"/>
                <route type="mix" sink="voip_tx"
                       sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In,Wired Headset Mic"/>
                <route type="mix" sink="record_24"
                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic"/>
               <route type="mix" sink="mmap_no_irq_in" 
                       sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,USB Device In,USB Headset In"/> 
// 这里可以看到Built-In Mic一共对应了四个route

2. 看devices对应的格式

<devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
      <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
            samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
            channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
</devicePort>
// 这里可以看到device对应的采样率、声道等信息

3. 看route对应的profile信息

<mixPort name="fast input" role="sink" maxOpenCount="2" maxActiveCount="2" flags="AUDIO_INPUT_FLAG_FAST">
        <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
              channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
</mixPort>
<mixPort name="record_24" role="sink" maxOpenCount="2" maxActiveCount="2">
        <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED"
               samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
               channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
       <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT"
              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
              channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
       <profile name="" format="AUDIO_FORMAT_PCM_FLOAT"
              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000,96000,192000"
              channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3,AUDIO_CHANNEL_INDEX_MASK_4"/>
</mixPort>
<mixPort name="voice_rx" role="sink">
      <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
              samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>
 </mixPort>
<mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
       <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
              samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
              channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK,AUDIO_CHANNEL_INDEX_MASK_3"/>
</mixPort>

demo:

例如,app设置的信息如下: inputsource: AUDIO_SOURCE_MIC, samplingRate: 16000, channelMask: 2, bitdepth: 16

则获取的profile就是:

<mixPort name="voice_rx" role="sink">

<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"

samplingRates="8000,16000,48000" channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO"/>

</mixPort>

获取方法就是在上面三个步骤之后获取一个匹配度最高的。

 

到这里今天的内容就结束了了,emmm……写完才发现自己犯了一个错,还没讲整个audio的大框架就开始讲细节,从下往上看其实很难看全看懂,从上往下看就容易的多。下次就分享下audio的框架, 敬请期待。

最后

以上就是爱笑早晨为你收集整理的Android-MediaRecorder之setAudioSource的全部内容,希望文章能够帮你解决Android-MediaRecorder之setAudioSource所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部