上一篇文章介绍了怎么通过MediaRecorderlu录制音频,详见(https://blog.csdn.net/cheriyou_/article/details/105544086
在创建MediaRecorder之后第一步就是设置AudioSource,那么audiosource具体是做什么用的?今天就来研究下。
1. 首先看看setAudioSource的过程
1
2
3
4
5
6
7
8status_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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26sp<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的用法
1
2
3
4
5
6
7
8
9
10
11
12status_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信息
1
2
3
4
5
6
7
8
9// 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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// 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
1
2
3
4
5
6
7
8
9
10audio_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。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21sp<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
1
2
3
4
5
6
7
8
9
10
11
12// 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对应的格式
1
2
3
4
5
6<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信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25<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内容请搜索靠谱客的其他文章。
发表评论 取消回复