Audio笔记之AudioSystem::getOutput
来源:互联网 发布:php重载 编辑:程序博客网 时间:2024/05/29 16:48
在创建track之前,需要根据应用传下来的的参数获取对输出线程output,这个output应该是在AudioFling进行初始化的时候就已经运行起来了。
createTrack只是将track添加到指定的输出线程output,该线程会使用track传递下来的数据进行mix,然后写到输出设备中。
因此如何获得该输出线程output至关重要,
status_t AudioTrack::set( audio_stream_type_t streamType, uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, int frameCountInt, audio_output_flags_t flags, callback_t cbf, void* user, int notificationFrames, const sp<IMemory>& sharedBuffer, bool threadCanCallJava, int sessionId, transfer_type transferType, const audio_offload_info_t *offloadInfo, int uid) { ..... //根据规则获得对应的输出线程output,output其实只是该线程的一个编号, //所有的输出线程都保存在AudioFling中,后续使用的时候可以根据这个编号 //来进行查找 audio_io_handle_t output = AudioSystem::getOutput( streamType, sampleRate, format, channelMask, flags, offloadInfo); if (output == 0) { ALOGE("Could not get audio output for stream type %d", streamType); return BAD_VALUE; } mVolume[LEFT] = 1.0f; mVolume[RIGHT] = 1.0f; mSendLevel = 0.0f; mFrameCount = frameCount; mReqFrameCount = frameCount; mNotificationFramesReq = notificationFrames; mNotificationFramesAct = 0; mSessionId = sessionId; if (uid == -1 || (IPCThreadState::self()->getCallingPid() != getpid())) { mClientUid = IPCThreadState::self()->getCallingUid(); } else { mClientUid = uid; } mAuxEffectId = 0; mFlags = flags; mCbf = cbf; if (cbf != NULL) { mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/); } // create the IAudioTrack status_t status = createTrack_l(streamType, sampleRate, format, frameCount, flags, sharedBuffer, output, 0 /*epoch*/); }audio_io_handle_t AudioSystem::getOutput(audio_stream_type_t stream, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags){ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return 0; return aps->getOutput(stream, samplingRate, format, channelMask, flags);}audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags){ if (mpAudioPolicy == NULL) { return 0; } ALOGV("getOutput()"); Mutex::Autolock _l(mLock); return mpAudioPolicy->get_output(mpAudioPolicy, stream, samplingRate, format, channelMask, flags);}//输出线程的查找路径:StreamType->Strategy->Device->Outputaudio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream, uint32_t samplingRate, uint32_t format, uint32_t channelMask, AudioSystem::output_flags flags){ audio_io_handle_t output = 0; uint32_t latency = 0; //步骤一、根据StreamType找到Strategy,对应关系一直不变 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); //步骤二、根据Strategy找到Device, audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); ALOGV("getOutput() stream %d, samplingRate %d, format %d, channelMask %x, flags %x", stream, samplingRate, format, channelMask, flags);#ifdef AUDIO_POLICY_TEST if (mCurOutput != 0) { ALOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channelMask %x, mDirectOutput %d", mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput); if (mTestOutputs[mCurOutput] == 0) { ALOGV("getOutput() opening test output"); AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(NULL); outputDesc->mDevice = mTestDevice; outputDesc->mSamplingRate = mTestSamplingRate; outputDesc->mFormat = mTestFormat; outputDesc->mChannelMask = mTestChannels; outputDesc->mLatency = mTestLatencyMs; outputDesc->mFlags = (audio_output_flags_t)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0); outputDesc->mRefCount[stream] = 0; mTestOutputs[mCurOutput] = mpClientInterface->openOutput(0, &outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, &outputDesc->mChannelMask, &outputDesc->mLatency, outputDesc->mFlags); if (mTestOutputs[mCurOutput]) { AudioParameter outputCmd = AudioParameter(); outputCmd.addInt(String8("set_id"),mCurOutput); mpClientInterface->setParameters(mTestOutputs[mCurOutput],outputCmd.toString()); addOutput(mTestOutputs[mCurOutput], outputDesc); } } return mTestOutputs[mCurOutput]; }#endif //AUDIO_POLICY_TEST // open a direct output if required by specified parameters IOProfile *profile = getProfileForDirectOutput(device, samplingRate, format, channelMask, (audio_output_flags_t)flags); if (profile != NULL) { AudioOutputDescriptor *outputDesc = NULL; for (size_t i = 0; i < mOutputs.size(); i++) { AudioOutputDescriptor *desc = mOutputs.valueAt(i); if (!desc->isDuplicated() && (profile == desc->mProfile)) { outputDesc = desc; // reuse direct output if currently open and configured with same parameters if ((samplingRate == outputDesc->mSamplingRate) && (format == outputDesc->mFormat) && (channelMask == outputDesc->mChannelMask)) { outputDesc->mDirectOpenCount++; ALOGV("getOutput() reusing direct output %d", output); return mOutputs.keyAt(i); } } } // close direct output if currently open and configured with different parameters if (outputDesc != NULL) { closeOutput(outputDesc->mId); } outputDesc = new AudioOutputDescriptor(profile); outputDesc->mDevice = device; outputDesc->mSamplingRate = samplingRate; outputDesc->mFormat = (audio_format_t)format; outputDesc->mChannelMask = (audio_channel_mask_t)channelMask; outputDesc->mLatency = 0; outputDesc->mFlags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);; outputDesc->mRefCount[stream] = 0; outputDesc->mStopTime[stream] = 0; outputDesc->mDirectOpenCount = 1; output = mpClientInterface->openOutput(profile->mModule->mHandle, &outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, &outputDesc->mChannelMask, &outputDesc->mLatency, outputDesc->mFlags); // only accept an output with the requested parameters if (output == 0 || (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) || (format != 0 && format != outputDesc->mFormat) || (channelMask != 0 && channelMask != outputDesc->mChannelMask)) { ALOGV("getOutput() failed opening direct output: output %d samplingRate %d %d," "format %d %d, channelMask %04x %04x", output, samplingRate, outputDesc->mSamplingRate, format, outputDesc->mFormat, channelMask, outputDesc->mChannelMask); if (output != 0) { mpClientInterface->closeOutput(output); } delete outputDesc; return 0; } addOutput(output, outputDesc); mPreviousOutputs = mOutputs; ALOGV("getOutput() returns new direct output %d", output); return output; } // ignoring channel mask due to downmix capability in mixer // open a non direct output // get which output is suitable for the specified stream. The actual routing change will happen // when startOutput() will be called //步骤三、根据device找到outputs SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); //步骤四、现在最优的output output = selectOutput(outputs, flags); ALOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d," "format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags); ALOGV("getOutput() returns output %d", output); return output;}AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy( AudioSystem::stream_type stream) { // stream to strategy mapping switch (stream) { case AudioSystem::VOICE_CALL: // 电话来了 case AudioSystem::BLUETOOTH_SCO: // 蓝牙耳机接通了 return STRATEGY_PHONE; case AudioSystem::RING: // 铃声响了 case AudioSystem::NOTIFICATION: // 通知,例如界面中最上面一栏中有消息了 case AudioSystem::ALARM: // 警告,电池没电时的警告? case AudioSystem::ENFORCED_AUDIBLE: return STRATEGY_SONIFICATION; case AudioSystem::DTMF: // 可参考链接:http://baike.baidu.com/view/171916.htm return STRATEGY_DTMF; default: LOGE("unknown stream type"); case AudioSystem::SYSTEM: // 系统声音采用 media strategy, 例如,如果正在播放音乐的时候按键, // mute 掉音乐,并切换 output 的话,将导致 很差的用户体验。 // 其中可以得到以下信息: // 1、按键声音属于 system stream type 。 // 2、策略的改变将会导致 output 的切换 // 3、优先级高的策略 start 时会 mute 掉优先级低的策略 // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs // while key clicks are played produces a poor result case AudioSystem::TTS: // TTS 就是 Text To Speech case AudioSystem::MUSIC: return STRATEGY_MEDIA; case AudioSystem::ENFORCED_AUDIBLE: return STRATEGY_ENFORCED_AUDIBLE; }}//根据设备的优先级,获得Strategy对应的设备,如果都没找到,则使用boot时设置的默认设备,//否则无法找到匹配的设备。当前所有可用的设备都保存在变量mAvailableOutputDevices中,//mAvailableOutputDevices只在初始化和AudioPolicyManagerBase::setOutputDevice中赋值,//每当系统发生设备插拔事件时,就会调用该函数来更新mAvailableOutputDevices的值//综上可用看出通过Strategy可以关联特定的设备audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache){ uint32_t device = AUDIO_DEVICE_NONE; if (fromCache) { ALOGVV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]); return mDeviceForStrategy[strategy]; } switch (strategy) { case STRATEGY_SONIFICATION_RESPECTFUL: if (isInCall()) { device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); } else if (isStreamActiveRemotely(AudioSystem::MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { // while media is playing on a remote device, use the the sonification behavior. // Note that we test this usecase before testing if media is playing because // the isStreamActive() method only informs about the activity of a stream, not // if it's for local playback. Note also that we use the same delay between both tests device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); } else if (isStreamActive(AudioSystem::MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) { // while media is playing (or has recently played), use the same device device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); } else { // when media is not playing anymore, fall back on the sonification behavior device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); } break; case STRATEGY_DTMF: if (!isInCall()) { // when off call, DTMF strategy follows the same rules as MEDIA strategy device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/); break; } // when in call, DTMF and PHONE strategies follow the same rules // FALL THROUGH case STRATEGY_PHONE: // for phone strategy, we first consider the forced use and then the available devices by order // of priority switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { case AudioSystem::FORCE_BT_SCO: if (!isInCall() || strategy != STRATEGY_DTMF) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break; } device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; if (device) break; // if SCO device is requested but no SCO device is available, fall back to default case // FALL THROUGH default: // FORCE_NONE // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP if (mHasA2dp && !isInCall() && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) && (getA2dpOutput() != 0) && !mA2dpSuspended) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; if (device) break; } device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET; if (device) break; if (mPhoneState != AudioSystem::MODE_IN_CALL) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; if (device) break; } device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_EARPIECE; if (device) break; device = mDefaultOutputDevice; if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE"); } break; case AudioSystem::FORCE_SPEAKER: // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to // A2DP speaker when forcing to speaker output if (mHasA2dp && !isInCall() && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) && (getA2dpOutput() != 0) && !mA2dpSuspended) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; if (device) break; } if (mPhoneState != AudioSystem::MODE_IN_CALL) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; if (device) break; } device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER; if (device) break; device = mDefaultOutputDevice; if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER"); } break; } break; case STRATEGY_SONIFICATION: // If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by // handleIncallSonification(). if (isInCall()) { device = getDeviceForStrategy(STRATEGY_PHONE, false /*fromCache*/); break; } // FALL THROUGH case STRATEGY_ENFORCED_AUDIBLE: // strategy STRATEGY_ENFORCED_AUDIBLE uses same routing policy as STRATEGY_SONIFICATION // except: // - when in call where it doesn't default to STRATEGY_PHONE behavior // - in countries where not enforced in which case it follows STRATEGY_MEDIA if ((strategy == STRATEGY_SONIFICATION) || (mForceUse[AudioSystem::FOR_SYSTEM] == AudioSystem::FORCE_SYSTEM_ENFORCED)) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER; if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() speaker device not found for STRATEGY_SONIFICATION"); } } // The second device used for sonification is the same as the device used by media strategy // FALL THROUGH case STRATEGY_MEDIA: { uint32_t device2 = AUDIO_DEVICE_NONE; if (strategy != STRATEGY_SONIFICATION) { // no sonification on remote submix (e.g. WFD) device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_REMOTE_SUBMIX; } if ((device2 == AUDIO_DEVICE_NONE) && mHasA2dp && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) && (getA2dpOutput() != 0) && !mA2dpSuspended) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; } if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; } } if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY; } if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; } if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { // no sonification on aux digital (e.g. HDMI) device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL; } if ((device2 == AUDIO_DEVICE_NONE) && (mForceUse[AudioSystem::FOR_DOCK] == AudioSystem::FORCE_ANALOG_DOCK)) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER; } // device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION or // STRATEGY_ENFORCED_AUDIBLE, AUDIO_DEVICE_NONE otherwise device |= device2; if (device) break; device = mDefaultOutputDevice; if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_MEDIA"); } } break; default: ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); break; } ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); return device;}//寻找当前支持该device的所有输出线程,有可能多个输出线程都支持该设备。对应到profile,就是一个//profile支持多个device,而device可能会出现在多个不同的profile中。该步骤可以表述为:device->outputsSortedVector<audio_io_handle_t> AudioPolicyManagerBase::getOutputsForDevice(audio_devices_t device, DefaultKeyedVector<audio_io_handle_t, AudioOutputDescriptor *> openOutputs){ SortedVector<audio_io_handle_t> outputs; ALOGVV("getOutputsForDevice() device %04x", device); for (size_t i = 0; i < openOutputs.size(); i++) { ALOGVV("output %d isDuplicated=%d device=%04x", i, openOutputs.valueAt(i)->isDuplicated(), openOutputs.valueAt(i)->supportedDevices()); if ((device & openOutputs.valueAt(i)->supportedDevices()) == device) { ALOGVV("getOutputsForDevice() found output %d", openOutputs.keyAt(i)); outputs.add(openOutputs.keyAt(i)); } } return outputs;}audio_io_handle_t AudioPolicyManagerBase::selectOutput(const SortedVector<audio_io_handle_t>& outputs, AudioSystem::output_flags flags){ // select one output among several that provide a path to a particular device or set of // devices (the list was previously build by getOutputsForDevice()). // The priority is as follows: // 1: the output with the highest number of requested policy flags // 2: the primary output // 3: the first output in the list if (outputs.size() == 0) { return 0; } if (outputs.size() == 1) { return outputs[0]; } int maxCommonFlags = 0; audio_io_handle_t outputFlags = 0; audio_io_handle_t outputPrimary = 0; for (size_t i = 0; i < outputs.size(); i++) { AudioOutputDescriptor *outputDesc = mOutputs.valueFor(outputs[i]); if (!outputDesc->isDuplicated()) { int commonFlags = (int)AudioSystem::popCount(outputDesc->mProfile->mFlags & flags); if (commonFlags > maxCommonFlags) { outputFlags = outputs[i]; maxCommonFlags = commonFlags; ALOGV("selectOutput() commonFlags for output %d, %04x", outputs[i], commonFlags); } if (outputDesc->mProfile->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY) { outputPrimary = outputs[i]; } } } if (outputFlags != 0) { return outputFlags; } if (outputPrimary != 0) { return outputPrimary; } return outputs[0];}
0 0
- Audio笔记之AudioSystem::getOutput
- Android Audio AudioSystem::getOutputSamplingRate
- Android Audio AudioSystem::getOutputSamplingRate
- Audio流程分析二(AudioSystem)
- Android Audio代码分析4 - AudioSystem::getOutputSamplingRate
- Android 7.0 Audio: AudioSystem相关类浅析
- audiosystem之audio_track_cblk_t
- audiosystem之audio_track_cblk_t
- Audio笔记之AudioMixer
- Audio笔记之MixerThread
- Audio笔记之FastMixer
- Audio笔记之AudioTrack
- Audio笔记之AudioTrackThread
- Audio笔记之AudioEffect
- Audio笔记之SoftAAC2
- Audio笔记之ServiceManager
- Audio笔记之MixerThread
- Audio笔记之AudioMixer
- [统计学习]Rocchio算法
- HDU 3333 树状数组离线
- UVa 10267 Graphical Editor
- SQL*PLUS命令的使用大全
- String与StringBuffer和StringBuilder区别之一
- Audio笔记之AudioSystem::getOutput
- 《现代操作系统—中文第三版》读书笔记之——调度算法
- BestCoder Round #21 1002
- 动态规划算法
- 终于解决了贴吧手机版的一个重大BUG
- 电子书格式探秘
- mac搭建svn服务器
- 我的Python爬虫(三):数据的实时监控
- mac搭建svn服务器