赞
踩
众(搞音频的(此处应该有个笑哭的表情)所周知的,要播放一个声音,创建AudioTrack之后,set函数设置参数的时候,会调用createTrack_l函数。
第一步:获取output
createTrack_l用binder去调用AudioFlinger的createTrack创建AudioFlinger::Track之前,首先会去调用getOutputForAttr:
- status = AudioSystem::getOutputForAttr(attr, &output,
- mSessionId, &streamType, mClientUid,
- &config,
- mFlags, &mRoutedDeviceId, &mPortId);
根据传入的audio_attributes_t等参数,带回output(这是个出参)!
这一调用,在AudioPolicyManager中得到落实。
AudioPolicyManager::getOutputForAttr:
//准备设置好attributes ... //根据attributes选中Strategy routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes); ... //根据Strategy选中device audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); ... //根据选定的device获取Output *output = getOutputForDevice(device, session, *stream, config->sample_rate, config->format, config->channel_mask, flags, &config->offload_info);
这个名字取得很有意思哈,一步步往下推进的感觉。
getOutputForAttr: attr>>strategy>>device>>output
其中,getDeviceForStrategy这一步真正决定了使用什么设备.
比如说,下面的例子是播放音乐(AUDIO_STREAM_MUSIC)的时候选中的Strategy:
//代码节选自Engine::getDeviceForStrategyInt case STRATEGY_MEDIA: { uint32_t device2 = AUDIO_DEVICE_NONE; ... //device2在前面没有被选中,而且没有设置这个setForceUse(setBluetoothA2dpOn(false)的时 候,会设置 //AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NO_BT_A2DP标记) if ((device2 == AUDIO_DEVICE_NONE) && (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) && (outputs.getA2dpOutput() != 0)) { //第一个优先项出现了.如果此时a2dp可用,直接到下面我用****标记的特殊情况 device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; } } //这次轮到了AudioSystem.FOR_MEDIA,AudioSystem.FORCE_SPEAKER这种情况,speaker胜出 if ((device2 == AUDIO_DEVICE_NONE) && (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; } //接下来就是依据优先级去选择设备了.规则就是 //选中一个就结束,直接去和特殊设备做共存 if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; } if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) { // no sonification on aux digital (e.g. HDMI) device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL; } if ((device2 == AUDIO_DEVICE_NONE) && (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; } if (device2 == AUDIO_DEVICE_NONE) { device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER; } *********************************************************************************** //特殊情况 int device3 = AUDIO_DEVICE_NONE; if (strategy == STRATEGY_MEDIA) { //如果arc,spdif,aux_line可用,赋值给device3 // ARC, SPDIF and AUX_LINE can co-exist with others. device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC; device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF); device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE); } //device2和arc,spdif,aux_line做一个共存 device2 |= device3; // 一般情况下,在这之前device还是AUDIO_DEVICE_NONE device |= device2; // If hdmi system audio mode is on, remove speaker out of output list. if ((strategy == STRATEGY_MEDIA) && (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] == AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) { device &= ~AUDIO_DEVICE_OUT_SPEAKER; } } break;
根据上面的代码,简单做个总结吧:
播放音乐选设备优先级如下
-
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES(普通蓝牙耳机)
- AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER(蓝牙小音箱)
- //此处属于setForceUse的强制插队
- (if FORCE_SPEAKER)AUDIO_DEVICE_OUT_SPEAKER(扬声器)
- AUDIO_DEVICE_OUT_WIRED_HEADPHONE(普通耳机,只能听,不能操控播放)
- AUDIO_DEVICE_OUT_LINE
- AUDIO_DEVICE_OUT_WIRED_HEADSET(线控耳机)
- AUDIO_DEVICE_OUT_USB_HEADSET(USB耳机)
- ...
- AUDIO_DEVICE_OUT_SPEAKER(扬声器)
选好设备就返回device,然后getOutputForDevice
AudioPolicyManager::getOutputForDevice
- //处理入参flags
- if ((flags & AUDIO_OUTPUT_FLAG_XXX) != 0) {
- flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_XXX);
- }
- //咱一般不是AUDIO_OUTPUT_FLAG_DIRECT,当然是
- goto non_direct_output;
- ...
- //播放音乐什么之类的,mediaplayer已经做完decodec.这里一般都是pcm
- if (audio_is_linear_pcm(format)) {
- //根据指定的stream类型获取匹配的output.实际的路由改变需要等到startOutput被调用的时候
- //注意这个函数是getOutputsForDevice,要获取的是一些output,而我们当前讨论的函数是获取一个output.这些outputs从mOutputs中来.那么mOutputs来自哪里?
- SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
- // 从匹配到的outputs(请注意,是复数)中选出一个output
- output =
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。