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
原创粉丝点击