summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/webrtc/MediaEngineWebRTCAudio.cpp')
-rw-r--r--dom/media/webrtc/MediaEngineWebRTCAudio.cpp125
1 files changed, 115 insertions, 10 deletions
diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
index 220dcf3bd8..c072717e00 100644
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -148,7 +148,7 @@ nsresult MediaEngineWebRTCMicrophoneSource::Reconfigure(
}
AudioProcessing::Config AudioInputProcessing::ConfigForPrefs(
- const MediaEnginePrefs& aPrefs) {
+ const MediaEnginePrefs& aPrefs) const {
AudioProcessing::Config config;
config.pipeline.multi_channel_render = true;
@@ -207,6 +207,19 @@ AudioProcessing::Config AudioInputProcessing::ConfigForPrefs(
config.high_pass_filter.enabled = aPrefs.mHPFOn;
+ if (mPlatformProcessingSetParams &
+ CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION) {
+ config.echo_canceller.enabled = false;
+ }
+ if (mPlatformProcessingSetParams &
+ CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL) {
+ config.gain_controller1.enabled = config.gain_controller2.enabled = false;
+ }
+ if (mPlatformProcessingSetParams &
+ CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION) {
+ config.noise_suppression.enabled = false;
+ }
+
return config;
}
@@ -412,11 +425,45 @@ void AudioInputProcessing::Disconnect(MediaTrackGraph* aGraph) {
aGraph->AssertOnGraphThread();
}
+void AudioInputProcessing::NotifySetRequestedInputProcessingParamsResult(
+ MediaTrackGraph* aGraph, cubeb_input_processing_params aRequestedParams,
+ const Result<cubeb_input_processing_params, int>& aResult) {
+ aGraph->AssertOnGraphThread();
+ if (aRequestedParams != RequestedInputProcessingParams(aGraph)) {
+ // This is a result from an old request, wait for a more recent one.
+ return;
+ }
+ if (aResult.isOk()) {
+ if (mPlatformProcessingSetParams == aResult.inspect()) {
+ // No change.
+ return;
+ }
+ mPlatformProcessingSetError = Nothing();
+ mPlatformProcessingSetParams = aResult.inspect();
+ LOG("AudioInputProcessing %p platform processing params are now %s.", this,
+ CubebUtils::ProcessingParamsToString(mPlatformProcessingSetParams)
+ .get());
+ } else {
+ mPlatformProcessingSetError = Some(aResult.inspectErr());
+ mPlatformProcessingSetParams = CUBEB_INPUT_PROCESSING_PARAM_NONE;
+ LOG("AudioInputProcessing %p platform processing params failed to apply. "
+ "Applying input processing config in libwebrtc.",
+ this);
+ }
+ ApplySettingsInternal(aGraph, mSettings);
+}
+
bool AudioInputProcessing::IsPassThrough(MediaTrackGraph* aGraph) const {
aGraph->AssertOnGraphThread();
// The high-pass filter is not taken into account when activating the
// pass through, since it's not controllable from content.
- return !(mSettings.mAecOn || mSettings.mAgcOn || mSettings.mNoiseOn);
+ auto config = AppliedConfig(aGraph);
+ auto aec = [](const auto& config) { return config.echo_canceller.enabled; };
+ auto agc = [](const auto& config) {
+ return config.gain_controller1.enabled || config.gain_controller2.enabled;
+ };
+ auto ns = [](const auto& config) { return config.noise_suppression.enabled; };
+ return !(aec(config) || agc(config) || ns(config));
}
void AudioInputProcessing::PassThroughChanged(MediaTrackGraph* aGraph) {
@@ -438,7 +485,7 @@ void AudioInputProcessing::PassThroughChanged(MediaTrackGraph* aGraph) {
}
}
-uint32_t AudioInputProcessing::GetRequestedInputChannelCount() {
+uint32_t AudioInputProcessing::GetRequestedInputChannelCount() const {
return mSettings.mChannels;
}
@@ -668,6 +715,10 @@ void AudioInputProcessing::ProcessOutputData(AudioProcessingTrack* aTrack,
return;
}
+ if (aChunk.mDuration == 0) {
+ return;
+ }
+
TrackRate sampleRate = aTrack->mSampleRate;
uint32_t framesPerPacket = GetPacketSize(sampleRate); // in frames
// Downmix from aChannels to MAX_CHANNELS if needed.
@@ -868,6 +919,7 @@ void AudioInputProcessing::PacketizeAndProcess(AudioProcessingTrack* aTrack,
!(mPacketCount % 50)) {
AudioProcessingStats stats = mAudioProcessing->GetStatistics();
char msg[1024];
+ msg[0] = '\0';
size_t offset = 0;
#define AddIfValue(format, member) \
if (stats.member.has_value()) { \
@@ -962,14 +1014,61 @@ void AudioInputProcessing::DeviceChanged(MediaTrackGraph* aGraph) {
aGraph, aGraph->CurrentDriver(), this);
}
+cubeb_input_processing_params
+AudioInputProcessing::RequestedInputProcessingParams(
+ MediaTrackGraph* aGraph) const {
+ aGraph->AssertOnGraphThread();
+ if (!mPlatformProcessingEnabled) {
+ return CUBEB_INPUT_PROCESSING_PARAM_NONE;
+ }
+ if (mPlatformProcessingSetError) {
+ return CUBEB_INPUT_PROCESSING_PARAM_NONE;
+ }
+ cubeb_input_processing_params params = CUBEB_INPUT_PROCESSING_PARAM_NONE;
+ if (mSettings.mAecOn) {
+ params |= CUBEB_INPUT_PROCESSING_PARAM_ECHO_CANCELLATION;
+ }
+ if (mSettings.mAgcOn) {
+ params |= CUBEB_INPUT_PROCESSING_PARAM_AUTOMATIC_GAIN_CONTROL;
+ }
+ if (mSettings.mNoiseOn) {
+ params |= CUBEB_INPUT_PROCESSING_PARAM_NOISE_SUPPRESSION;
+ }
+ return params;
+}
+
void AudioInputProcessing::ApplySettings(MediaTrackGraph* aGraph,
CubebUtils::AudioDeviceID aDeviceID,
const MediaEnginePrefs& aSettings) {
TRACE("AudioInputProcessing::ApplySettings");
aGraph->AssertOnGraphThread();
+ // CUBEB_ERROR_NOT_SUPPORTED means the backend does not support platform
+ // processing. In that case, leave the error in place so we don't request
+ // processing anew.
+ if (mPlatformProcessingSetError.valueOr(CUBEB_OK) !=
+ CUBEB_ERROR_NOT_SUPPORTED) {
+ mPlatformProcessingSetError = Nothing();
+ }
+
// Read previous state from mSettings.
uint32_t oldChannelCount = GetRequestedInputChannelCount();
+
+ ApplySettingsInternal(aGraph, aSettings);
+
+ if (oldChannelCount != GetRequestedInputChannelCount()) {
+ RequestedInputChannelCountChanged(aGraph, aDeviceID);
+ }
+}
+
+void AudioInputProcessing::ApplySettingsInternal(
+ MediaTrackGraph* aGraph, const MediaEnginePrefs& aSettings) {
+ TRACE("AudioInputProcessing::ApplySettingsInternal");
+ aGraph->AssertOnGraphThread();
+
+ mPlatformProcessingEnabled = aSettings.mUsePlatformProcessing;
+
+ // Read previous state from the applied config.
bool wasPassThrough = IsPassThrough(aGraph);
mSettings = aSettings;
@@ -977,14 +1076,20 @@ void AudioInputProcessing::ApplySettings(MediaTrackGraph* aGraph,
mAudioProcessing->ApplyConfig(ConfigForPrefs(aSettings));
}
- if (oldChannelCount != GetRequestedInputChannelCount()) {
- RequestedInputChannelCountChanged(aGraph, aDeviceID);
- }
if (wasPassThrough != IsPassThrough(aGraph)) {
PassThroughChanged(aGraph);
}
}
+webrtc::AudioProcessing::Config AudioInputProcessing::AppliedConfig(
+ MediaTrackGraph* aGraph) const {
+ aGraph->AssertOnGraphThread();
+ if (mAudioProcessing) {
+ return mAudioProcessing->GetConfig();
+ }
+ return ConfigForPrefs(mSettings);
+}
+
void AudioInputProcessing::End() {
mEnded = true;
mSegment.Clear();
@@ -1078,7 +1183,6 @@ void AudioInputProcessing::EnsureAudioProcessing(AudioProcessingTrack* aTrack) {
void AudioInputProcessing::ResetAudioProcessing(MediaTrackGraph* aGraph) {
aGraph->AssertOnGraphThread();
MOZ_ASSERT(IsPassThrough(aGraph) || !mEnabled);
- MOZ_ASSERT(mPacketizerInput);
LOG_FRAME(
"(Graph %p, Driver %p) AudioInputProcessing %p Resetting audio "
@@ -1091,9 +1195,10 @@ void AudioInputProcessing::ResetAudioProcessing(MediaTrackGraph* aGraph) {
mAudioProcessing->Initialize();
}
- MOZ_ASSERT(static_cast<uint32_t>(mSegment.GetDuration()) +
- mPacketizerInput->FramesAvailable() ==
- mPacketizerInput->mPacketSize);
+ MOZ_ASSERT_IF(mPacketizerInput,
+ static_cast<uint32_t>(mSegment.GetDuration()) +
+ mPacketizerInput->FramesAvailable() ==
+ mPacketizerInput->mPacketSize);
// It's ok to clear all the internal buffer here since we won't use mSegment
// in pass-through mode or when audio processing is disabled.