再论COM组件
重要的Activate方法
Activate方法
Activate支持的接口
源码分析
h:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\media\engine\webrtc_voice_engine.cc
WebRtcVoiceEngine::Init
void WebRtcVoiceEngine::Init() {***RTC_CHECK(adm());webrtc::adm_helpers::Init(adm());***}
这时候进入到
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\media\engine\adm_helpers.cc
void Init(AudioDeviceModule* adm) 方法
webrtc::adm_helpers::Init
void Init(AudioDeviceModule* adm) {RTC_DCHECK(adm);RTC_CHECK_EQ(0, adm->Init()) << "Failed to initialize the ADM.";// Playout device.{if (adm->SetPlayoutDevice(AUDIO_DEVICE_ID) != 0) {RTC_LOG(LS_ERROR) << "Unable to set playout device.";return;}if (adm->InitSpeaker() != 0) {RTC_LOG(LS_ERROR) << "Unable to access speaker.";}// Set number of channelsbool available = false;if (adm->StereoPlayoutIsAvailable(&available) != 0) {RTC_LOG(LS_ERROR) << "Failed to query stereo playout.";}if (adm->SetStereoPlayout(available) != 0) {RTC_LOG(LS_ERROR) << "Failed to set stereo playout mode.";}}// Recording device.{if (adm->SetRecordingDevice(AUDIO_DEVICE_ID) != 0) {RTC_LOG(LS_ERROR) << "Unable to set recording device.";return;}if (adm->InitMicrophone() != 0) {RTC_LOG(LS_ERROR) << "Unable to access microphone.";}// Set number of channelsbool available = false;if (adm->StereoRecordingIsAvailable(&available) != 0) {RTC_LOG(LS_ERROR) << "Failed to query stereo recording.";}if (adm->SetStereoRecording(available) != 0) {RTC_LOG(LS_ERROR) << "Failed to set stereo recording mode.";}}}
AudioDeviceModuleImpl::Init
int32_t AudioDeviceModuleImpl::Init() {RTC_LOG(INFO) << __FUNCTION__;if (initialized_)return 0;RTC_CHECK(audio_device_);AudioDeviceGeneric::InitStatus status = audio_device_->Init();RTC_HISTOGRAM_ENUMERATION("WebRTC.Audio.InitializationResult", static_cast<int>(status),static_cast<int>(AudioDeviceGeneric::InitStatus::NUM_STATUSES));if (status != AudioDeviceGeneric::InitStatus::OK) {RTC_LOG(LS_ERROR) << "Audio device initialization failed.";return -1;}initialized_ = true;return 0;}
重点是音频设备初始化 AudioDeviceGeneric::InitStatus status = audiodevice->Init();
AudioDeviceGeneric::InitStatus AudioDeviceWindowsCore::Init()
AudioDeviceGeneric::InitStatus AudioDeviceWindowsCore::Init() {MutexLock lock(&mutex_);if (_initialized) {return InitStatus::OK;}// Enumerate all audio rendering and capturing endpoint devices.// Note that, some of these will not be able to select by the user.// The complete collection is for internal use only._EnumerateEndpointDevicesAll(eRender);_EnumerateEndpointDevicesAll(eCapture);_initialized = true;return InitStatus::OK;}
调用堆栈

列出设备_EnumerateEndpointDevicesAll
AudioDeviceWindowsCore::_EnumerateEndpointDevicesAll
列出某个种类的设备,采集还是播放的设备。
int32_t AudioDeviceWindowsCore::_EnumerateEndpointDevicesAll(***HRESULT hr = S_OK;IMMDeviceCollection* pCollection = NULL;IMMDevice* pEndpoint = NULL;IPropertyStore* pProps = NULL;IAudioEndpointVolume* pEndpointVolume = NULL;LPWSTR pwszID = NULL;// Generate a collection of audio endpoint devices in the system.// Get states for *all* endpoint devices.// Output: IMMDeviceCollection interface.hr = _ptrEnumerator->EnumAudioEndpoints(dataFlow, // data-flow direction (input parameter)DEVICE_STATE_ACTIVE | DEVICE_STATE_DISABLED | DEVICE_STATE_UNPLUGGED,&pCollection); // release interface when doneEXIT_ON_ERROR(hr);***// Retrieve a count of the devices in the device collection.hr = pCollection->GetCount(&count);***// Each loop prints the name of an endpoint device.for (ULONG i = 0; i < count; i++) {RTC_LOG(LS_VERBOSE) << "Endpoint " << i << ":";// Get pointer to endpoint number i.// Output: IMMDevice interface.// 拿到一个具体的设备hr = pCollection->Item(i, &pEndpoint);CONTINUE_ON_ERROR(hr);// Get the endpoint ID string (uniquely identifies the device among all// audio endpoint devices)hr = pEndpoint->GetId(&pwszID);CONTINUE_ON_ERROR(hr);RTC_LOG(LS_VERBOSE) << "ID string : " << pwszID;// Retrieve an interface to the device's property store.// Output: IPropertyStore interface. 获取设备属性hr = pEndpoint->OpenPropertyStore(STGM_READ, &pProps);CONTINUE_ON_ERROR(hr);// use the IPropertyStore interface...PROPVARIANT varName;// Initialize container for property value.PropVariantInit(&varName);// Get the endpoint's friendly-name property.// Example: "Speakers (Realtek High Definition Audio)"hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName);CONTINUE_ON_ERROR(hr);RTC_LOG(LS_VERBOSE) << "friendly name: \"" << varName.pwszVal << "\"";// 获取设备的状态// Get the endpoint's current device stateDWORD dwState;hr = pEndpoint->GetState(&dwState);CONTINUE_ON_ERROR(hr);if (dwState & DEVICE_STATE_ACTIVE)RTC_LOG(LS_VERBOSE) << "state (0x" << rtc::ToHex(dwState)<< ") : *ACTIVE*";if (dwState & DEVICE_STATE_DISABLED)RTC_LOG(LS_VERBOSE) << "state (0x" << rtc::ToHex(dwState)<< ") : DISABLED";if (dwState & DEVICE_STATE_NOTPRESENT)RTC_LOG(LS_VERBOSE) << "state (0x" << rtc::ToHex(dwState)<< ") : NOTPRESENT";if (dwState & DEVICE_STATE_UNPLUGGED)RTC_LOG(LS_VERBOSE) << "state (0x" << rtc::ToHex(dwState)<< ") : UNPLUGGED";// Check the hardware volume capabilities.DWORD dwHwSupportMask = 0;hr = pEndpoint->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL,(void**)&pEndpointVolume);CONTINUE_ON_ERROR(hr);// 获取掩码从而得知支持什么控制hr = pEndpointVolume->QueryHardwareSupport(&dwHwSupportMask);CONTINUE_ON_ERROR(hr);if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_VOLUME)// The audio endpoint device supports a hardware volume controlRTC_LOG(LS_VERBOSE) << "hwmask (0x" << rtc::ToHex(dwHwSupportMask)<< ") : HARDWARE_SUPPORT_VOLUME";if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_MUTE)// The audio endpoint device supports a hardware mute controlRTC_LOG(LS_VERBOSE) << "hwmask (0x" << rtc::ToHex(dwHwSupportMask)<< ") : HARDWARE_SUPPORT_MUTE";if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_METER)// The audio endpoint device supports a hardware peak meterRTC_LOG(LS_VERBOSE) << "hwmask (0x" << rtc::ToHex(dwHwSupportMask)<< ") : HARDWARE_SUPPORT_METER";// Check the channel count (#channels in the audio stream that enters or// leaves the audio endpoint device)UINT nChannelCount(0);hr = pEndpointVolume->GetChannelCount(&nChannelCount);CONTINUE_ON_ERROR(hr);RTC_LOG(LS_VERBOSE) << "#channels : " << nChannelCount;if (dwHwSupportMask & ENDPOINT_HARDWARE_SUPPORT_VOLUME) {// Get the volume range.float fLevelMinDB(0.0);float fLevelMaxDB(0.0);float fVolumeIncrementDB(0.0);hr = pEndpointVolume->GetVolumeRange(&fLevelMinDB, &fLevelMaxDB,&fVolumeIncrementDB);******// Get information about the current step in the volume range.// This method represents the volume level of the audio stream that enters// or leaves the audio endpoint device as an index or "step" in a range of// discrete volume levels. Output value nStepCount is the number of steps// in the range. Output value nStep is the step index of the current// volume level. If the number of steps is n = nStepCount, then step index// nStep can assume values from 0 (minimum volume) to n ?1 (maximum// volume).UINT nStep(0);UINT nStepCount(0); // 获取音量步长hr = pEndpointVolume->GetVolumeStepInfo(&nStep, &nStepCount);CONTINUE_ON_ERROR(hr);RTC_LOG(LS_VERBOSE) << "volume steps : " << nStep << " (nStep), "<< nStepCount << " (nStepCount)";}****}
