nsresult MediaEngineWebRTCMicrophoneSource::UpdateSingleSource( const AllocationHandle* aHandle, const NormalizedConstraints& aNetConstraints, const MediaEnginePrefs& aPrefs, const nsString& aDeviceId, const char** aOutBadConstraint) { FlattenedConstraints c(aNetConstraints); MediaEnginePrefs prefs = aPrefs; prefs.mAecOn = c.mEchoCancellation.Get(prefs.mAecOn); prefs.mAgcOn = c.mAutoGainControl.Get(prefs.mAgcOn); prefs.mNoiseOn = c.mNoiseSuppression.Get(prefs.mNoiseOn); uint32_t maxChannels = 1; if (mAudioInput->GetMaxAvailableChannels(maxChannels) != 0) { return NS_ERROR_FAILURE; } // Check channelCount violation if (static_cast<int32_t>(maxChannels) < c.mChannelCount.mMin || static_cast<int32_t>(maxChannels) > c.mChannelCount.mMax) { *aOutBadConstraint = "channelCount"; return NS_ERROR_FAILURE; } // Clamp channelCount to a valid value if (prefs.mChannels <= 0) { prefs.mChannels = static_cast<int32_t>(maxChannels); } prefs.mChannels = c.mChannelCount.Get(std::min(prefs.mChannels, static_cast<int32_t>(maxChannels))); // Clamp channelCount to a valid value prefs.mChannels = std::max(1, std::min(prefs.mChannels, static_cast<int32_t>(maxChannels))); LOG(("Audio config: aec: %d, agc: %d, noise: %d, delay: %d, channels: %d", prefs.mAecOn ? prefs.mAec : -1, prefs.mAgcOn ? prefs.mAgc : -1, prefs.mNoiseOn ? prefs.mNoise : -1, prefs.mPlayoutDelay, prefs.mChannels)); mPlayoutDelay = prefs.mPlayoutDelay; switch (mState) { case kReleased: MOZ_ASSERT(aHandle); if (sChannelsOpen == 0) { if (!InitEngine()) { LOG(("Audio engine is not initalized")); return NS_ERROR_FAILURE; } } else { // Until we fix (or wallpaper) support for multiple mic input // (Bug 1238038) fail allocation for a second device return NS_ERROR_FAILURE; } if (mAudioInput->SetRecordingDevice(mCapIndex)) { return NS_ERROR_FAILURE; } mAudioInput->SetUserChannelCount(prefs.mChannels); if (!AllocChannel()) { FreeChannel(); LOG(("Audio device is not initalized")); return NS_ERROR_FAILURE; } LOG(("Audio device %d allocated", mCapIndex)); { // Update with the actual applied channelCount in order // to store it in settings. uint32_t channelCount = 0; mAudioInput->GetChannelCount(channelCount); MOZ_ASSERT(channelCount > 0); prefs.mChannels = channelCount; } break; case kStarted: if (prefs == mLastPrefs) { return NS_OK; } if (prefs.mChannels != mLastPrefs.mChannels) { MOZ_ASSERT(mSources.Length() > 0); auto& source = mSources.LastElement(); mAudioInput->SetUserChannelCount(prefs.mChannels); // Get validated number of channel uint32_t channelCount = 0; mAudioInput->GetChannelCount(channelCount); MOZ_ASSERT(channelCount > 0 && mLastPrefs.mChannels > 0); // Check if new validated channels is the same as previous if (static_cast<uint32_t>(mLastPrefs.mChannels) != channelCount && !source->OpenNewAudioCallbackDriver(mListener)) { return NS_ERROR_FAILURE; } // Update settings prefs.mChannels = channelCount; } if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) { MonitorAutoLock lock(mMonitor); if (mSources.IsEmpty()) { LOG(("Audio device %d reallocated", mCapIndex)); } else { LOG(("Audio device %d allocated shared", mCapIndex)); } } break; default: LOG(("Audio device %d in ignored state %d", mCapIndex, mState)); break; } if (sChannelsOpen > 0) { int error; error = mVoEProcessing->SetEcStatus(prefs.mAecOn, (webrtc::EcModes)prefs.mAec); if (error) { LOG(("%s Error setting Echo Status: %d ",__FUNCTION__, error)); // Overhead of capturing all the time is very low (<0.1% of an audio only call) if (prefs.mAecOn) { error = mVoEProcessing->SetEcMetricsStatus(true); if (error) { LOG(("%s Error setting Echo Metrics: %d ",__FUNCTION__, error)); } } } error = mVoEProcessing->SetAgcStatus(prefs.mAgcOn, (webrtc::AgcModes)prefs.mAgc); if (error) { LOG(("%s Error setting AGC Status: %d ",__FUNCTION__, error)); } error = mVoEProcessing->SetNsStatus(prefs.mNoiseOn, (webrtc::NsModes)prefs.mNoise); if (error) { LOG(("%s Error setting NoiseSuppression Status: %d ",__FUNCTION__, error)); } } mSkipProcessing = !(prefs.mAecOn || prefs.mAgcOn || prefs.mNoiseOn); if (mSkipProcessing) { mSampleFrequency = MediaEngine::USE_GRAPH_RATE; mAudioOutputObserver = nullptr; } else { // make sure we route a copy of the mixed audio output of this MSG to the // AEC mAudioOutputObserver = new AudioOutputObserver(); } SetLastPrefs(prefs); return NS_OK; }
nsresult MediaEngineWebRTCMicrophoneSource::UpdateSingleSource( const AllocationHandle* aHandle, const NormalizedConstraints& aNetConstraints, const MediaEnginePrefs& aPrefs, const nsString& aDeviceId, const char** aOutBadConstraint) { FlattenedConstraints c(aNetConstraints); MediaEnginePrefs prefs = aPrefs; prefs.mAecOn = c.mEchoCancellation.Get(prefs.mAecOn); prefs.mAgcOn = c.mAutoGainControl.Get(prefs.mAgcOn); prefs.mNoiseOn = c.mNoiseSuppression.Get(prefs.mNoiseOn); LOG(("Audio config: aec: %d, agc: %d, noise: %d, delay: %d", prefs.mAecOn ? prefs.mAec : -1, prefs.mAgcOn ? prefs.mAgc : -1, prefs.mNoiseOn ? prefs.mNoise : -1, prefs.mPlayoutDelay)); mPlayoutDelay = prefs.mPlayoutDelay; switch (mState) { case kReleased: MOZ_ASSERT(aHandle); if (sChannelsOpen == 0) { if (!InitEngine()) { LOG(("Audio engine is not initalized")); return NS_ERROR_FAILURE; } } else { // Until we fix (or wallpaper) support for multiple mic input // (Bug 1238038) fail allocation for a second device return NS_ERROR_FAILURE; } if (!AllocChannel()) { LOG(("Audio device is not initalized")); return NS_ERROR_FAILURE; } if (mAudioInput->SetRecordingDevice(mCapIndex)) { FreeChannel(); return NS_ERROR_FAILURE; } LOG(("Audio device %d allocated", mCapIndex)); break; case kStarted: if (prefs == mLastPrefs) { return NS_OK; } if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) { MonitorAutoLock lock(mMonitor); if (mSources.IsEmpty()) { LOG(("Audio device %d reallocated", mCapIndex)); } else { LOG(("Audio device %d allocated shared", mCapIndex)); } } break; default: LOG(("Audio device %d in ignored state %d", mCapIndex, mState)); break; } if (sChannelsOpen > 0) { int error; error = mVoEProcessing->SetEcStatus(prefs.mAecOn, (webrtc::EcModes)prefs.mAec); if (error) { LOG(("%s Error setting Echo Status: %d ",__FUNCTION__, error)); // Overhead of capturing all the time is very low (<0.1% of an audio only call) if (prefs.mAecOn) { error = mVoEProcessing->SetEcMetricsStatus(true); if (error) { LOG(("%s Error setting Echo Metrics: %d ",__FUNCTION__, error)); } } } error = mVoEProcessing->SetAgcStatus(prefs.mAgcOn, (webrtc::AgcModes)prefs.mAgc); if (error) { LOG(("%s Error setting AGC Status: %d ",__FUNCTION__, error)); } error = mVoEProcessing->SetNsStatus(prefs.mNoiseOn, (webrtc::NsModes)prefs.mNoise); if (error) { LOG(("%s Error setting NoiseSuppression Status: %d ",__FUNCTION__, error)); } } mSkipProcessing = !(prefs.mAecOn || prefs.mAgcOn || prefs.mNoiseOn); if (mSkipProcessing) { mSampleFrequency = MediaEngine::USE_GRAPH_RATE; } SetLastPrefs(prefs); return NS_OK; }