Android Audio代码分析12 - stream type续
2011-10-14 14:02
531 查看
前几天在看stream type的时候,调用函数AudioSystem::getOutput的地方并没有继续往下看。
今天深入看看。
*****************************************源码*************************************************
**********************************************************************************************
#######################说明################################
###########################################################
&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
根据stream type找到对应的strategy。
根据strategy找到对应的device type。
根据device type找到对应的alsa_handle_t对象。
根据配置和device type找到设备名称,并打开设备获取一个snd_pcm_t对象。
将snd_pcm_t对象保存到alsa_handle_t对象对象中。
我们之前已经看过write操作,
其实就是往snd_pcm_t对象的stopped_areas或者running_areas成员中copy数据;
或者直接调用snd_pcm_t对象的fast_ops的writei函数写数据。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
今天深入看看。
*****************************************源码*************************************************
status_t AudioTrack::set( int streamType, uint32_t sampleRate, int format, int channels, int frameCount, uint32_t flags, callback_t cbf, void* user, int notificationFrames, const sp<IMemory>& sharedBuffer, bool threadCanCallJava, int sessionId) { LOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(), sharedBuffer->size()); if (mAudioTrack != 0) { LOGE("Track already in use"); return INVALID_OPERATION; } int afSampleRate; if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) { return NO_INIT; } uint32_t afLatency; if (AudioSystem::getOutputLatency(&afLatency, streamType) != NO_ERROR) { return NO_INIT; } // handle default values first. if (streamType == AudioSystem::DEFAULT) { streamType = AudioSystem::MUSIC; } if (sampleRate == 0) { sampleRate = afSampleRate; } // these below should probably come from the audioFlinger too... if (format == 0) { format = AudioSystem::PCM_16_BIT; } if (channels == 0) { channels = AudioSystem::CHANNEL_OUT_STEREO; } // validate parameters if (!AudioSystem::isValidFormat(format)) { LOGE("Invalid format"); return BAD_VALUE; } // force direct flag if format is not linear PCM if (!AudioSystem::isLinearPCM(format)) { flags |= AudioSystem::OUTPUT_FLAG_DIRECT; } if (!AudioSystem::isOutputChannel(channels)) { LOGE("Invalid channel mask"); return BAD_VALUE; } uint32_t channelCount = AudioSystem::popCount(channels); audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType, sampleRate, format, channels, (AudioSystem::output_flags)flags); if (output == 0) { LOGE("Could not get audio output for stream type %d", streamType); return BAD_VALUE; } mVolume[LEFT] = 1.0f; mVolume[RIGHT] = 1.0f; mSendLevel = 0; mFrameCount = frameCount; mNotificationFramesReq = notificationFrames; mSessionId = sessionId; mAuxEffectId = 0; // create the IAudioTrack status_t status = createTrack(streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, output, true); if (status != NO_ERROR) { return status; } if (cbf != 0) { mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); if (mAudioTrackThread == 0) { LOGE("Could not create callback thread"); return NO_INIT; } } mStatus = NO_ERROR; mStreamType = streamType; mFormat = format; mChannels = channels; mChannelCount = channelCount; mSharedBuffer = sharedBuffer; mMuted = false; mActive = 0; mCbf = cbf; mUserData = user; mLoopCount = 0; mMarkerPosition = 0; mMarkerReached = false; mNewPosition = 0; mUpdatePeriod = 0; mFlags = flags; return NO_ERROR; }
**********************************************************************************************
#######################说明################################
// +++++++++++++++++++++++++AudioSystem::getOutput+++++++++++++++++++++++++++++++++++++++ audio_io_handle_t AudioSystem::getOutput(stream_type stream, uint32_t samplingRate, uint32_t format, uint32_t channels, output_flags flags) { audio_io_handle_t output = 0; // Do not use stream to output map cache if the direct output // flag is set or if we are likely to use a direct output // (e.g voice call stream @ 8kHz could use BT SCO device and be routed to // a direct output on some platforms). // TODO: the output cache and stream to output mapping implementation needs to // be reworked for proper operation with direct outputs. This code is too specific // to the first use case we want to cover (Voice Recognition and Voice Dialer over // Bluetooth SCO if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0 && ((stream != AudioSystem::VOICE_CALL && stream != AudioSystem::BLUETOOTH_SCO) || channels != AudioSystem::CHANNEL_OUT_MONO || (samplingRate != 8000 && samplingRate != 16000))) { Mutex::Autolock _l(gLock); output = AudioSystem::gStreamOutputMap.valueFor(stream); LOGV_IF((output != 0), "getOutput() read %d from cache for stream %d", output, stream); } if (output == 0) { const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return 0; output = aps->getOutput(stream, samplingRate, format, channels, flags); if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) { Mutex::Autolock _l(gLock); AudioSystem::gStreamOutputMap.add(stream, output); } // +++++++++++++++++++++++++++++AudioPolicyService::getOutput+++++++++++++++++++++++++++++++++++ audio_io_handle_t AudioPolicyService::getOutput(AudioSystem::stream_type stream, uint32_t samplingRate, uint32_t format, uint32_t channels, AudioSystem::output_flags flags) { if (mpPolicyManager == NULL) { return 0; } LOGV("getOutput() tid %d", gettid()); Mutex::Autolock _l(mLock); return mpPolicyManager->getOutput(stream, samplingRate, format, channels, flags); // +++++++++++++++++++++++++++++AudioPolicyManagerBase::getOutput+++++++++++++++++++++++++++++++++++ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type stream, uint32_t samplingRate, uint32_t format, uint32_t channels, AudioSystem::output_flags flags) { audio_io_handle_t output = 0; uint32_t latency = 0; // 此处根据stream获取策略 routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); // 这儿再根据策略获取device // 这句代码和上句代码结合起来,就是根据stream的类型,获取对应的device uint32_t device = getDeviceForStrategy(strategy); LOGV("getOutput() stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags); #ifdef AUDIO_POLICY_TEST // 定义了AUDIO_POLICY_TEST的时候,会去打开一个output if (mCurOutput != 0) { LOGV("getOutput() test output mCurOutput %d, samplingRate %d, format %d, channels %x, mDirectOutput %d", mCurOutput, mTestSamplingRate, mTestFormat, mTestChannels, mDirectOutput); if (mTestOutputs[mCurOutput] == 0) { LOGV("getOutput() opening test output"); AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); outputDesc->mDevice = mTestDevice; outputDesc->mSamplingRate = mTestSamplingRate; outputDesc->mFormat = mTestFormat; outputDesc->mChannels = mTestChannels; outputDesc->mLatency = mTestLatencyMs; outputDesc->mFlags = (AudioSystem::output_flags)(mDirectOutput ? AudioSystem::OUTPUT_FLAG_DIRECT : 0); outputDesc->mRefCount[stream] = 0; mTestOutputs[mCurOutput] = mpClientInterface->openOutput(&outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, &outputDesc->mChannels, &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 // Direct模式的话,会去打开一个output // open a direct output if required by specified parameters if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) { LOGV("getOutput() opening direct output device %x", device); AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); outputDesc->mDevice = device; outputDesc->mSamplingRate = samplingRate; outputDesc->mFormat = format; outputDesc->mChannels = channels; outputDesc->mLatency = 0; outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT); outputDesc->mRefCount[stream] = 0; output = mpClientInterface->openOutput(&outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, &outputDesc->mChannels, &outputDesc->mLatency, outputDesc->mFlags); // only accept an output with the requeted parameters if (output == 0 || (samplingRate != 0 && samplingRate != outputDesc->mSamplingRate) || (format != 0 && format != outputDesc->mFormat) || (channels != 0 && channels != outputDesc->mChannels)) { LOGV("getOutput() failed opening direct output: samplingRate %d, format %d, channels %d", samplingRate, format, channels); if (output != 0) { mpClientInterface->closeOutput(output); } delete outputDesc; return 0; } addOutput(output, outputDesc); return output; } if (channels != 0 && channels != AudioSystem::CHANNEL_OUT_MONO && channels != AudioSystem::CHANNEL_OUT_STEREO) { return 0; } // open a non direct output // stream模式的话,直接取成员变量的值 // 下面看看用于取值的这几个成员变量赋值的地方 // get which output is suitable for the specified stream. The actual routing change will happen // when startOutput() will be called uint32_t a2dpDevice = device & AudioSystem::DEVICE_OUT_ALL_A2DP; if (AudioSystem::popCount((AudioSystem::audio_devices)device) == 2) { #ifdef WITH_A2DP if (a2dpUsedForSonification() && a2dpDevice != 0) { // if playing on 2 devices among which one is A2DP, use duplicated output LOGV("getOutput() using duplicated output"); LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device in multiple %x selected but A2DP output not opened", device); // mA2dpOutput和mDuplicatedOutput的赋值都在函数AudioPolicyManagerBase::handleA2dpConnection中 output = mDuplicatedOutput; // +++++++++++++++++++++++++++++AudioPolicyManagerBase::handleA2dpConnection+++++++++++++++++++++++++++++++++++ status_t AudioPolicyManagerBase::handleA2dpConnection(AudioSystem::audio_devices device, const char *device_address) { // when an A2DP device is connected, open an A2DP and a duplicated output LOGV("opening A2DP output for device %s", device_address); AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); outputDesc->mDevice = device; // 这个函数在下面有看 mA2dpOutput = mpClientInterface->openOutput(&outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, &outputDesc->mChannels, &outputDesc->mLatency, outputDesc->mFlags); if (mA2dpOutput) { // add A2DP output descriptor addOutput(mA2dpOutput, outputDesc); //TODO: configure audio effect output stage here // set initial stream volume for A2DP device applyStreamVolumes(mA2dpOutput, device); if (a2dpUsedForSonification()) { // mA2dpOutput和mHardwareOutput是已经打开的两个output mDuplicatedOutput = mpClientInterface->openDuplicateOutput(mA2dpOutput, mHardwareOutput); // +++++++++++++++++++++++++++++AudioPolicyService::openDuplicateOutput+++++++++++++++++++++++++++++++++++ audio_io_handle_t AudioPolicyService::openDuplicateOutput(audio_io_handle_t output1, audio_io_handle_t output2) { sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); if (af == 0) { LOGW("openDuplicateOutput() could not get AudioFlinger"); return 0; } return af->openDuplicateOutput(output1, output2); // +++++++++++++++++++++++++++++++AudioFlinger::openDuplicateOutput+++++++++++++++++++++++++++++++++ int AudioFlinger::openDuplicateOutput(int output1, int output2) { Mutex::Autolock _l(mLock); MixerThread *thread1 = checkMixerThread_l(output1); MixerThread *thread2 = checkMixerThread_l(output2); // ++++++++++++++++++++++++++++++AudioFlinger::checkMixerThread_l++++++++++++++++++++++++++++++++++ // checkMixerThread_l() must be called with AudioFlinger::mLock held AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(int output) const { PlaybackThread *thread = checkPlaybackThread_l(output); if (thread != NULL) { if (thread->type() == PlaybackThread::DIRECT) { thread = NULL; } } // +++++++++++++++++++++++++++++++AudioFlinger::checkPlaybackThread_l+++++++++++++++++++++++++++++++++ // checkPlaybackThread_l() must be called with AudioFlinger::mLock held AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(int output) const { PlaybackThread *thread = NULL; if (mPlaybackThreads.indexOfKey(output) >= 0) { // AudioFlinger::openOutput函数中会向mPlaybackThreads中追加成员 thread = (PlaybackThread *)mPlaybackThreads.valueFor(output).get(); } return thread; } // -------------------------------AudioFlinger::checkPlaybackThread_l--------------------------------- return (MixerThread *)thread; } // ------------------------------AudioFlinger::checkMixerThread_l---------------------------------- if (thread1 == NULL || thread2 == NULL) { LOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1, output2); return 0; } int id = nextUniqueId(); // 选一个thread作为主thread,来创建DuplicatingThread DuplicatingThread *thread = new DuplicatingThread(this, thread1, id); // ++++++++++++++++++++++++++++AudioFlinger::DuplicatingThread::DuplicatingThread++++++++++++++++++++++++++++++++++++ AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id) : MixerThread(audioFlinger, mainThread->getOutput(), id, mainThread->device()), mWaitTimeMs(UINT_MAX) { mType = PlaybackThread::DUPLICATING; addOutputTrack(mainThread); // +++++++++++++++++++++++++++++AudioFlinger::DuplicatingThread::addOutputTrack+++++++++++++++++++++++++++++++++++ void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread) { int frameCount = (3 * mFrameCount * mSampleRate) / thread->sampleRate(); OutputTrack *outputTrack = new OutputTrack((ThreadBase *)thread, this, mSampleRate, mFormat, mChannelCount, frameCount); if (outputTrack->cblk() != NULL) { thread->setStreamVolume(AudioSystem::NUM_STREAM_TYPES, 1.0f); mOutputTracks.add(outputTrack); LOGV("addOutputTrack() track %p, on thread %p", outputTrack, thread); updateWaitTime(); } // +++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::OutputTrack::OutputTrack+++++++++++++++++++++++++++++++++++ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( const wp<ThreadBase>& thread, DuplicatingThread *sourceThread, uint32_t sampleRate, int format, int channelCount, int frameCount) : Track(thread, NULL, AudioSystem::NUM_STREAM_TYPES, sampleRate, format, channelCount, frameCount, NULL, 0), mActive(false), mSourceThread(sourceThread) { PlaybackThread *playbackThread = (PlaybackThread *)thread.unsafe_get(); if (mCblk != NULL) { mCblk->flags |= CBLK_DIRECTION_OUT; mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); mCblk->volume[0] = mCblk->volume[1] = 0x1000; mOutBuffer.frameCount = 0; playbackThread->mTracks.add(this); LOGV("OutputTrack constructor mCblk %p, mBuffer %p, mCblk->buffers %p, mCblk->frameCount %d, mCblk->sampleRate %d, mCblk->channelCount %d mBufferEnd %p", mCblk, mBuffer, mCblk->buffers, mCblk->frameCount, mCblk->sampleRate, mCblk->channelCount, mBufferEnd); } else { LOGW("Error creating output track on thread %p", playbackThread); } } // -----------------------------AudioFlinger::PlaybackThread::OutputTrack::OutputTrack----------------------------------- } // -----------------------------AudioFlinger::DuplicatingThread::addOutputTrack----------------------------------- } // ----------------------------AudioFlinger::DuplicatingThread::DuplicatingThread------------------------------------ // 再将另外一个thread也添加进来 thread->addOutputTrack(thread2); mPlaybackThreads.add(id, thread); // notify client processes of the new output creation thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); return id; } // -------------------------------AudioFlinger::openDuplicateOutput--------------------------------- } // -----------------------------AudioPolicyService::openDuplicateOutput----------------------------------- } if (mDuplicatedOutput != 0 || !a2dpUsedForSonification()) { // If both A2DP and duplicated outputs are open, send device address to A2DP hardware // interface AudioParameter param; param.add(String8("a2dp_sink_address"), String8(device_address)); mpClientInterface->setParameters(mA2dpOutput, param.toString()); mA2dpDeviceAddress = String8(device_address, MAX_DEVICE_ADDRESS_LEN); if (a2dpUsedForSonification()) { // add duplicated output descriptor AudioOutputDescriptor *dupOutputDesc = new AudioOutputDescriptor(); dupOutputDesc->mOutput1 = mOutputs.valueFor(mHardwareOutput); dupOutputDesc->mOutput2 = mOutputs.valueFor(mA2dpOutput); dupOutputDesc->mSamplingRate = outputDesc->mSamplingRate; dupOutputDesc->mFormat = outputDesc->mFormat; dupOutputDesc->mChannels = outputDesc->mChannels; dupOutputDesc->mLatency = outputDesc->mLatency; addOutput(mDuplicatedOutput, dupOutputDesc); applyStreamVolumes(mDuplicatedOutput, device); } } else { LOGW("getOutput() could not open duplicated output for %d and %d", mHardwareOutput, mA2dpOutput); mpClientInterface->closeOutput(mA2dpOutput); mOutputs.removeItem(mA2dpOutput); mA2dpOutput = 0; delete outputDesc; return NO_INIT; } } else { LOGW("setDeviceConnectionState() could not open A2DP output for device %x", device); delete outputDesc; return NO_INIT; } AudioOutputDescriptor *hwOutputDesc = mOutputs.valueFor(mHardwareOutput); if (!a2dpUsedForSonification()) { // mute music on A2DP output if a notification or ringtone is playing uint32_t refCount = hwOutputDesc->strategyRefCount(STRATEGY_SONIFICATION); for (uint32_t i = 0; i < refCount; i++) { setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput); } } mA2dpSuspended = false; return NO_ERROR; } // -----------------------------AudioPolicyManagerBase::handleA2dpConnection----------------------------------- } else #endif { // if playing on 2 devices among which none is A2DP, use hardware output output = mHardwareOutput; // +++++++++++++++++++++++++++++++AudioPolicyManagerBase::AudioPolicyManagerBase+++++++++++++++++++++++++++++++++ mHardwareOutput在AudioPolicyManagerBase的构造函数中被赋值。 AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clientInterface) : #ifdef AUDIO_POLICY_TEST Thread(false), #endif //AUDIO_POLICY_TEST mPhoneState(AudioSystem::MODE_NORMAL), mRingerMode(0), mMusicStopTime(0), mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f), mTotalEffectsCpuLoad(0), mTotalEffectsMemory(0), mA2dpSuspended(false) { mpClientInterface = clientInterface; for (int i = 0; i < AudioSystem::NUM_FORCE_USE; i++) { mForceUse[i] = AudioSystem::FORCE_NONE; } // devices available by default are speaker, ear piece and microphone mAvailableOutputDevices = AudioSystem::DEVICE_OUT_EARPIECE | AudioSystem::DEVICE_OUT_SPEAKER; mAvailableInputDevices = AudioSystem::DEVICE_IN_BUILTIN_MIC; #ifdef WITH_A2DP mA2dpOutput = 0; mDuplicatedOutput = 0; mA2dpDeviceAddress = String8(""); #endif mScoDeviceAddress = String8(""); // open hardware output AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(); // 从下面的这个赋值可见,一般情况下,如果不使用A2DP的话,我们用的device其实是固定的:DEVICE_OUT_SPEAKER outputDesc->mDevice = (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER; // 从AudioPolicyManagerBase对象被创建的地方可知,mpClientInterface其实是AudioPolicyService对象。 mHardwareOutput = mpClientInterface->openOutput(&outputDesc->mDevice, &outputDesc->mSamplingRate, &outputDesc->mFormat, &outputDesc->mChannels, &outputDesc->mLatency, outputDesc->mFlags); if (mHardwareOutput == 0) { LOGE("Failed to initialize hardware output stream, samplingRate: %d, format %d, channels %d", outputDesc->mSamplingRate, outputDesc->mFormat, outputDesc->mChannels); } else { addOutput(mHardwareOutput, outputDesc); setOutputDevice(mHardwareOutput, (uint32_t)AudioSystem::DEVICE_OUT_SPEAKER, true); //TODO: configure audio effect output stage here } // +++++++++++++++++++++++++++++++AudioPolicyService::openOutput+++++++++++++++++++++++++++++++++ audio_io_handle_t AudioPolicyService::openOutput(uint32_t *pDevices, uint32_t *pSamplingRate, uint32_t *pFormat, uint32_t *pChannels, uint32_t *pLatencyMs, AudioSystem::output_flags flags) { sp<IAudioFlinger> af = AudioSystem::get_audio_flinger(); if (af == 0) { LOGW("openOutput() could not get AudioFlinger"); return 0; } return af->openOutput(pDevices, pSamplingRate, (uint32_t *)pFormat, pChannels, pLatencyMs, flags); // ++++++++++++++++++++++++++++++AudioFlinger::openOutput++++++++++++++++++++++++++++++++++ int AudioFlinger::openOutput(uint32_t *pDevices, uint32_t *pSamplingRate, uint32_t *pFormat, uint32_t *pChannels, uint32_t *pLatencyMs, uint32_t flags) { status_t status; PlaybackThread *thread = NULL; mHardwareStatus = AUDIO_HW_OUTPUT_OPEN; uint32_t samplingRate = pSamplingRate ? *pSamplingRate : 0; uint32_t format = pFormat ? *pFormat : 0; uint32_t channels = pChannels ? *pChannels : 0; uint32_t latency = pLatencyMs ? *pLatencyMs : 0; LOGV("openOutput(), Device %x, SamplingRate %d, Format %d, Channels %x, flags %x", pDevices ? *pDevices : 0, samplingRate, format, channels, flags); if (pDevices == NULL || *pDevices == 0) { return 0; } Mutex::Autolock _l(mLock); // 调用HAL层的接口,打开一个output stream。 // device类型,被作为参数传给了HAL // 这个函数前面已经看过,此处只把与device类型相关的东东再复习一下 // ++++++++++++++++++++++++++++AudioHardwareALSA::openOutputStream++++++++++++++++++++++++++++++++++++ AudioStreamOut * AudioHardwareALSA::openOutputStream(uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status) { ... // 从device 类型的定义可知,每种device类型占一个bit // 从函数getDeviceForStrategy的实现可知,我们根据stream类型最终取得的device肯定只有一种 // 此处检查device类型是不是只占了一个bit if (devices & (devices - 1)) { if (status) *status = err; LOGD("openOutputStream called with bad devices"); return out; } // Find the appropriate alsa device // ALSAHandleList中的内容其实是从一个数组中copy过来 // 数组中只是列出了一些初始信息,很多有用的东东是在后面赋值的 // 结构体中一个重要的东东module(alsa_device_t * )是在调用函数s_open中赋值的 // +++++++++++++++++++++++++++++_defaults+++++++++++++++++++++++++++++++++++ static alsa_handle_t _defaults[] = { { module : 0, devices : IMX51_OUT_DEFAULT, curDev : 0, curMode : 0, handle : 0, format : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT channels : 2, sampleRate : DEFAULT_SAMPLE_RATE, latency : 200000, // Desired Delay in usec bufferSize : 6144, // Desired Number of samples modPrivate : (void *)&setDefaultControls, }, { module : 0, devices : IMX51_IN_DEFAULT, curDev : 0, curMode : 0, handle : 0, format : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT channels : 2, sampleRate : DEFAULT_SAMPLE_RATE, latency : 250000, // Desired Delay in usec bufferSize : 6144, // Desired Number of samples modPrivate : (void *)&setDefaultControls, }, }; // -----------------------------_defaults----------------------------------- for(ALSAHandleList::iterator it = mDeviceList.begin(); it != mDeviceList.end(); ++it) // 根据device类型,找到占的坑 if (it->devices & devices) { // 在调s_open时,仍然将device类型作为参数传入 err = mALSADevice->open(&(*it), devices, mode()); if (err) break; // +++++++++++++++++++++++++++++s_open+++++++++++++++++++++++++++++++++++ static status_t s_open(alsa_handle_t *handle, uint32_t devices, int mode) { ... // device类型是在找device名称的时候 const char *devName = deviceName(handle, devices, mode, 1); // +++++++++++++++++++++++++++++deviceName+++++++++++++++++++++++++++++++++++ //card_device =0, return the card name, card_device=1, return the card device name const char *deviceName(alsa_handle_t *alsa_handle, uint32_t device, int mode, int card_device) { ... property_get("ro.HDMI_AUDIO_OUTPUT", value, ""); // device类型在此处作判断用 // 因此,device name的取得,很大程度上说依赖于配置文件的 if((device & AudioSystem::DEVICE_OUT_WIRED_HDMI) && havespdifdevice && (strcmp(value, "1") == 0)) { return spdifcardname; }else if(havesgtldevice) { return sgtlcardname; } return "default"; } // -----------------------------deviceName----------------------------------- // The PCM stream is opened in blocking mode, per ALSA defaults. The // AudioFlinger seems to assume blocking mode too, so asynchronous mode // should not be used. // 根据上面得到的device name,打开一个alsa设备 int err = snd_pcm_open(&handle->handle, devName, direction(handle), 0); if (err < 0) { LOGE("Failed to Initialize any ALSA %s device: %s", stream, strerror(err)); return NO_INIT; } ... // 将device类型保存到上面占地坑中 handle->curDev = devices; handle->curMode = mode; return err; } // -----------------------------s_open----------------------------------- if (devices & AudioSystem::DEVICE_OUT_WIRED_HDMI){ strcpy(mCurCard ,SPDIF); mMixer = mMixerSpdif; } else { strcpy(mCurCard,SGTL5000); mMixer = mMixerSgtl5000; } out = new AudioStreamOutALSA(this, &(*it)); err = out->set(format, channels, sampleRate); break; } if (status) *status = err; return out; } // ----------------------------AudioHardwareALSA::openOutputStream------------------------------------ AudioStreamOut *output = mAudioHardware->openOutputStream(*pDevices, (int *)&format, &channels, &samplingRate, &status); LOGV("openOutput() openOutputStream returned output %p, SamplingRate %d, Format %d, Channels %x, status %d", output, samplingRate, format, channels, status); mHardwareStatus = AUDIO_HW_IDLE; if (output != 0) { int id = nextUniqueId(); if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || (format != AudioSystem::PCM_16_BIT) || (channels != AudioSystem::CHANNEL_OUT_STEREO)) { // 如果是direct模式,创建一个DirectOutputThread thread = new DirectOutputThread(this, output, id, *pDevices); LOGV("openOutput() created direct output: ID %d thread %p", id, thread); } else { // stream模式的话,创建一个MixerThread thread = new MixerThread(this, output, id, *pDevices); LOGV("openOutput() created mixer output: ID %d thread %p", id, thread); #ifdef LVMX unsigned bitsPerSample = (format == AudioSystem::PCM_16_BIT) ? 16 : ((format == AudioSystem::PCM_8_BIT) ? 8 : 0); unsigned channelCount = (channels == AudioSystem::CHANNEL_OUT_STEREO) ? 2 : 1; int audioOutputType = LifeVibes::threadIdToAudioOutputType(thread->id()); LifeVibes::init_aot(audioOutputType, samplingRate, bitsPerSample, channelCount); LifeVibes::setDevice(audioOutputType, *pDevices); #endif } // 将上面创建的thread追加到playback thread列表,并将其与一个unique id关联起来 mPlaybackThreads.add(id, thread); if (pSamplingRate) *pSamplingRate = samplingRate; if (pFormat) *pFormat = format; if (pChannels) *pChannels = channels; if (pLatencyMs) *pLatencyMs = thread->latency(); // notify client processes of the new output creation thread->audioConfigChanged_l(AudioSystem::OUTPUT_OPENED); return id; } return 0; } // ------------------------------AudioFlinger::openOutput---------------------------------- } // -------------------------------AudioPolicyService::openOutput--------------------------------- updateDeviceForStrategy(); #ifdef AUDIO_POLICY_TEST AudioParameter outputCmd = AudioParameter(); outputCmd.addInt(String8("set_id"), 0); mpClientInterface->setParameters(mHardwareOutput, outputCmd.toString()); mTestDevice = AudioSystem::DEVICE_OUT_SPEAKER; mTestSamplingRate = 44100; mTestFormat = AudioSystem::PCM_16_BIT; mTestChannels = AudioSystem::CHANNEL_OUT_STEREO; mTestLatencyMs = 0; mCurOutput = 0; mDirectOutput = false; for (int i = 0; i < NUM_TEST_OUTPUTS; i++) { mTestOutputs[i] = 0; } const size_t SIZE = 256; char buffer[SIZE]; snprintf(buffer, SIZE, "AudioPolicyManagerTest"); run(buffer, ANDROID_PRIORITY_AUDIO); #endif //AUDIO_POLICY_TEST } AudioPolicyManagerBase对象是在AudioPolicyService的构造函数中创建的。 // ++++++++++++++++++++++++++++++AudioPolicyService::AudioPolicyService++++++++++++++++++++++++++++++++++ AudioPolicyService::AudioPolicyService() : BnAudioPolicyService() , mpPolicyManager(NULL) { char value[PROPERTY_VALUE_MAX]; // start tone playback thread mTonePlaybackThread = new AudioCommandThread(String8("")); // start audio commands thread mAudioCommandThread = new AudioCommandThread(String8("ApmCommandThread")); #if (defined GENERIC_AUDIO) || (defined AUDIO_POLICY_TEST) mpPolicyManager = new AudioPolicyManagerBase(this); LOGV("build for GENERIC_AUDIO - using generic audio policy"); #else // if running in emulation - use the emulator driver if (property_get("ro.kernel.qemu", value, 0)) { LOGV("Running in emulation - using generic audio policy"); mpPolicyManager = new AudioPolicyManagerBase(this); } else { LOGV("Using hardware specific audio policy"); // 正常的话,应该是走到这儿来。 // 这个函数以前看过,实际使用的应该是ALSA中的AudioPlicyManager // Alsa中的AudioPolicyManager继承自AudioPolicyManagerBase, // 并且基本上没做什么变化 mpPolicyManager = createAudioPolicyManager(this); } #endif // load properties property_get("ro.camera.sound.forced", value, "0"); mpPolicyManager->setSystemProperty("ro.camera.sound.forced", value); } // ------------------------------AudioPolicyService::AudioPolicyService---------------------------------- // -------------------------------AudioPolicyManagerBase::AudioPolicyManagerBase--------------------------------- } LOGV("getOutput() using output %d for 2 devices %x", output, device); } else { #ifdef WITH_A2DP if (a2dpDevice != 0) { // if playing on A2DP device, use a2dp output LOGW_IF((mA2dpOutput == 0), "getOutput() A2DP device %x selected but A2DP output not opened", device); output = mA2dpOutput; } else #endif { // if playing on not A2DP device, use hardware output output = mHardwareOutput; } } LOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d, format %d, channels %x, flags %x", stream, samplingRate, format, channels, flags); return output; } // -----------------------------AudioPolicyManagerBase::getOutput----------------------------------- } // -----------------------------AudioPolicyService::getOutput----------------------------------- } return output; } // -------------------------AudioSystem::getOutput---------------------------------------
###########################################################
&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
根据stream type找到对应的strategy。
根据strategy找到对应的device type。
根据device type找到对应的alsa_handle_t对象。
根据配置和device type找到设备名称,并打开设备获取一个snd_pcm_t对象。
将snd_pcm_t对象保存到alsa_handle_t对象对象中。
我们之前已经看过write操作,
其实就是往snd_pcm_t对象的stopped_areas或者running_areas成员中copy数据;
或者直接调用snd_pcm_t对象的fast_ops的writei函数写数据。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
相关文章推荐
- Android Audio代码分析12 - stream type续
- Android Audio代码分析2 - 函数getMinBufferSize (补充)
- Android Audio代码分析18 - setSampleRate函数
- Android Audio代码分析20 - queryEffects函数
- Android Audio代码分析10 - audio_track_cblk_t::framesReady函数
- Android Audio代码分析27 - Strategy 优先级
- Android Audio代码分析18 - setSampleRate函数
- Android Audio代码分析8 - AudioHardwareALSA::openOutputStream函数
- Android Audio代码分析10 - audio_track_cblk_t::framesReady函数
- Android Audio代码分析27 - Strategy 优先级
- Android Audio代码分析19 - setPosition函数
- Android Audio代码分析20 - queryEffects函数
- Android Audio代码分析24 - AudioEffect::setEnabled函数
- Android Audio代码分析5 - 函数getAudioSessionId
- Android Audio代码分析8 - AudioHardwareALSA::openOutputStream函数
- Android Audio代码分析19 - setPosition函数
- Android Audio代码分析21 - 创建AudioEffect对象
- Android Audio代码分析24 - AudioEffect::setEnabled函数
- Android Audio代码分析26 - Audio Strategy
- Android Audio代码分析21 - 创建AudioEffect对象