概述
上一篇文章介绍了怎么通过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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复