1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/modules/mediastream/media_stream_constraints_util_audio.h"
6
7 #include <algorithm>
8 #include <cmath>
9 #include <memory>
10 #include <string>
11 #include <utility>
12
13 #include "base/bind_helpers.h"
14 #include "base/stl_util.h"
15 #include "base/test/scoped_feature_list.h"
16 #include "build/build_config.h"
17 #include "media/base/audio_parameters.h"
18 #include "media/webrtc/webrtc_switches.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h"
21 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
22 #include "third_party/blink/public/platform/web_string.h"
23 #include "third_party/blink/renderer/modules/mediastream/local_media_stream_audio_source.h"
24 #include "third_party/blink/renderer/modules/mediastream/mock_constraint_factory.h"
25 #include "third_party/blink/renderer/modules/mediastream/processed_local_audio_source.h"
26 #include "third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h"
27 #include "third_party/blink/renderer/platform/mediastream/media_constraints.h"
28 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
29 #include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h"
30 #include "third_party/webrtc/rtc_base/ref_counted_object.h"
31
32 namespace blink {
33
34 using blink::AudioCaptureSettings;
35 using blink::AudioProcessingProperties;
36 using EchoCancellationType = AudioProcessingProperties::EchoCancellationType;
37 using ProcessingType = AudioCaptureSettings::ProcessingType;
38
39 namespace {
40
41 using BoolSetFunction = void (blink::BooleanConstraint::*)(bool);
42 using StringSetFunction =
43 void (blink::StringConstraint::*)(const blink::WebString&);
44 using MockFactoryAccessor =
45 MediaTrackConstraintSetPlatform& (blink::MockConstraintFactory::*)();
46
47 const BoolSetFunction kBoolSetFunctions[] = {
48 &blink::BooleanConstraint::SetExact,
49 &blink::BooleanConstraint::SetIdeal,
50 };
51
52 const MockFactoryAccessor kFactoryAccessors[] = {
53 &blink::MockConstraintFactory::basic,
54 &blink::MockConstraintFactory::AddAdvanced};
55
56 const bool kBoolValues[] = {true, false};
57
58 const int kMinChannels = 1;
59
60 using AudioSettingsBoolMembers =
61 std::vector<bool (AudioCaptureSettings::*)() const>;
62 using AudioPropertiesBoolMembers =
63 std::vector<bool AudioProcessingProperties::*>;
64
65 const AudioPropertiesBoolMembers kAudioProcessingProperties = {
66 &AudioProcessingProperties::goog_audio_mirroring,
67 &AudioProcessingProperties::goog_auto_gain_control,
68 &AudioProcessingProperties::goog_experimental_echo_cancellation,
69 &AudioProcessingProperties::goog_noise_suppression,
70 &AudioProcessingProperties::goog_experimental_noise_suppression,
71 &AudioProcessingProperties::goog_highpass_filter,
72 &AudioProcessingProperties::goog_experimental_auto_gain_control};
73
74 template <typename T>
Contains(const std::vector<T> & vector,T value)75 static bool Contains(const std::vector<T>& vector, T value) {
76 return base::Contains(vector, value);
77 }
78
79 } // namespace
80
81 class MediaStreamConstraintsUtilAudioTestBase {
82 protected:
MakeSystemEchoCancellerDeviceExperimental()83 void MakeSystemEchoCancellerDeviceExperimental() {
84 media::AudioParameters experimental_system_echo_canceller_parameters(
85 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
86 media::CHANNEL_LAYOUT_STEREO,
87 media::AudioParameters::kAudioCDSampleRate, 1000);
88 experimental_system_echo_canceller_parameters.set_effects(
89 media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
90 capabilities_[1] = {"experimental_system_echo_canceller_device",
91 "fake_group3",
92 experimental_system_echo_canceller_parameters};
93 }
94
SetMediaStreamSource(const std::string & source)95 void SetMediaStreamSource(const std::string& source) {}
96
ResetFactory()97 void ResetFactory() {
98 constraint_factory_.Reset();
99 constraint_factory_.basic().media_stream_source.SetExact(
100 String::FromUTF8(GetMediaStreamSource()));
101 }
102
103 // If not overridden, this function will return device capture by default.
GetMediaStreamSource()104 virtual std::string GetMediaStreamSource() { return std::string(); }
IsDeviceCapture()105 bool IsDeviceCapture() { return GetMediaStreamSource().empty(); }
106
GetMediaStreamType()107 blink::mojom::MediaStreamType GetMediaStreamType() {
108 std::string media_source = GetMediaStreamSource();
109 if (media_source.empty())
110 return blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE;
111 else if (media_source == blink::kMediaStreamSourceTab)
112 return blink::mojom::MediaStreamType::GUM_TAB_AUDIO_CAPTURE;
113 return blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE;
114 }
115
GetProcessedLocalAudioSource(const AudioProcessingProperties & properties,bool disable_local_echo,bool render_to_associated_sink,int effects)116 std::unique_ptr<ProcessedLocalAudioSource> GetProcessedLocalAudioSource(
117 const AudioProcessingProperties& properties,
118 bool disable_local_echo,
119 bool render_to_associated_sink,
120 int effects) {
121 blink::MediaStreamDevice device;
122 device.id = "processed_source";
123 device.type = GetMediaStreamType();
124 if (render_to_associated_sink)
125 device.matched_output_device_id = std::string("some_device_id");
126 device.input.set_effects(effects);
127
128 return std::make_unique<ProcessedLocalAudioSource>(
129 nullptr /*web_frame*/, device, disable_local_echo, properties,
130 base::NullCallback(),
131 blink::scheduler::GetSingleThreadTaskRunnerForTesting());
132 }
133
GetProcessedLocalAudioSource(const AudioProcessingProperties & properties,bool disable_local_echo,bool render_to_associated_sink)134 std::unique_ptr<ProcessedLocalAudioSource> GetProcessedLocalAudioSource(
135 const AudioProcessingProperties& properties,
136 bool disable_local_echo,
137 bool render_to_associated_sink) {
138 return GetProcessedLocalAudioSource(
139 properties, disable_local_echo, render_to_associated_sink,
140 media::AudioParameters::PlatformEffectsMask::NO_EFFECTS);
141 }
142
143 std::unique_ptr<blink::LocalMediaStreamAudioSource>
GetLocalMediaStreamAudioSource(bool enable_system_echo_canceller,bool disable_local_echo,bool render_to_associated_sink,bool enable_experimental_echo_canceller=false,const int * requested_buffer_size=nullptr)144 GetLocalMediaStreamAudioSource(
145 bool enable_system_echo_canceller,
146 bool disable_local_echo,
147 bool render_to_associated_sink,
148 bool enable_experimental_echo_canceller = false,
149 const int* requested_buffer_size = nullptr) {
150 blink::MediaStreamDevice device;
151 device.type = GetMediaStreamType();
152
153 int effects = 0;
154 if (enable_system_echo_canceller)
155 effects |= media::AudioParameters::ECHO_CANCELLER;
156 if (enable_experimental_echo_canceller)
157 effects |= media::AudioParameters::EXPERIMENTAL_ECHO_CANCELLER;
158 device.input.set_effects(effects);
159
160 if (render_to_associated_sink)
161 device.matched_output_device_id = std::string("some_device_id");
162
163 return std::make_unique<blink::LocalMediaStreamAudioSource>(
164 /*blink::WebLocalFrame=*/nullptr, device, requested_buffer_size,
165 disable_local_echo,
166 blink::WebPlatformMediaStreamSource::ConstraintsRepeatingCallback(),
167 blink::scheduler::GetSingleThreadTaskRunnerForTesting());
168 }
169
SelectSettings(bool is_reconfigurable=false,base::Optional<AudioDeviceCaptureCapabilities> capabilities=base::nullopt)170 AudioCaptureSettings SelectSettings(
171 bool is_reconfigurable = false,
172 base::Optional<AudioDeviceCaptureCapabilities> capabilities =
173 base::nullopt) {
174 MediaConstraints constraints = constraint_factory_.CreateMediaConstraints();
175 if (capabilities) {
176 return SelectSettingsAudioCapture(*capabilities, constraints, false,
177 is_reconfigurable);
178 } else {
179 return SelectSettingsAudioCapture(capabilities_, constraints, false,
180 is_reconfigurable);
181 }
182 }
183
184 // When googExperimentalEchoCancellation is not explicitly set, its default
185 // value is always false on Android. On other platforms it behaves like other
186 // audio-processing properties.
CheckGoogExperimentalEchoCancellationDefault(const AudioProcessingProperties & properties,bool value)187 void CheckGoogExperimentalEchoCancellationDefault(
188 const AudioProcessingProperties& properties,
189 bool value) {
190 #if defined(OS_ANDROID)
191 EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
192 #else
193 EXPECT_EQ(value, properties.goog_experimental_echo_cancellation);
194 #endif
195 }
196
CheckBoolDefaultsDeviceCapture(const AudioSettingsBoolMembers & exclude_main_settings,const AudioPropertiesBoolMembers & exclude_audio_properties,const AudioCaptureSettings & result)197 void CheckBoolDefaultsDeviceCapture(
198 const AudioSettingsBoolMembers& exclude_main_settings,
199 const AudioPropertiesBoolMembers& exclude_audio_properties,
200 const AudioCaptureSettings& result) {
201 if (!Contains(exclude_main_settings,
202 &AudioCaptureSettings::disable_local_echo)) {
203 EXPECT_TRUE(result.disable_local_echo());
204 }
205 if (!Contains(exclude_main_settings,
206 &AudioCaptureSettings::render_to_associated_sink)) {
207 EXPECT_FALSE(result.render_to_associated_sink());
208 }
209
210 const auto& properties = result.audio_processing_properties();
211 if (!Contains(exclude_audio_properties,
212 &AudioProcessingProperties::goog_audio_mirroring)) {
213 EXPECT_FALSE(properties.goog_audio_mirroring);
214 }
215 if (!Contains(exclude_audio_properties,
216 &AudioProcessingProperties::goog_auto_gain_control)) {
217 EXPECT_EQ(properties.goog_auto_gain_control,
218 properties.goog_experimental_auto_gain_control);
219 if (!Contains(exclude_audio_properties,
220 &AudioProcessingProperties::
221 goog_experimental_auto_gain_control)) {
222 EXPECT_TRUE(properties.goog_auto_gain_control);
223 }
224 }
225 if (!Contains(
226 exclude_audio_properties,
227 &AudioProcessingProperties::goog_experimental_auto_gain_control)) {
228 EXPECT_EQ(properties.goog_auto_gain_control,
229 properties.goog_experimental_auto_gain_control);
230 if (!Contains(exclude_audio_properties,
231 &AudioProcessingProperties::goog_auto_gain_control)) {
232 EXPECT_TRUE(properties.goog_experimental_auto_gain_control);
233 }
234 }
235 if (!Contains(
236 exclude_audio_properties,
237 &AudioProcessingProperties::goog_experimental_echo_cancellation)) {
238 CheckGoogExperimentalEchoCancellationDefault(properties, true);
239 }
240 if (!Contains(exclude_audio_properties,
241 &AudioProcessingProperties::goog_noise_suppression)) {
242 EXPECT_TRUE(properties.goog_noise_suppression);
243 }
244 if (!Contains(
245 exclude_audio_properties,
246 &AudioProcessingProperties::goog_experimental_noise_suppression)) {
247 EXPECT_TRUE(properties.goog_experimental_noise_suppression);
248 }
249 if (!Contains(exclude_audio_properties,
250 &AudioProcessingProperties::goog_highpass_filter)) {
251 EXPECT_TRUE(properties.goog_highpass_filter);
252 }
253 }
254
CheckBoolDefaultsContentCapture(const AudioSettingsBoolMembers & exclude_main_settings,const AudioPropertiesBoolMembers & exclude_audio_properties,const AudioCaptureSettings & result)255 void CheckBoolDefaultsContentCapture(
256 const AudioSettingsBoolMembers& exclude_main_settings,
257 const AudioPropertiesBoolMembers& exclude_audio_properties,
258 const AudioCaptureSettings& result) {
259 if (!Contains(exclude_main_settings,
260 &AudioCaptureSettings::disable_local_echo)) {
261 EXPECT_EQ(GetMediaStreamSource() != blink::kMediaStreamSourceDesktop,
262 result.disable_local_echo());
263 }
264 if (!Contains(exclude_main_settings,
265 &AudioCaptureSettings::render_to_associated_sink)) {
266 EXPECT_FALSE(result.render_to_associated_sink());
267 }
268
269 const auto& properties = result.audio_processing_properties();
270 if (!Contains(exclude_audio_properties,
271 &AudioProcessingProperties::goog_audio_mirroring)) {
272 EXPECT_FALSE(properties.goog_audio_mirroring);
273 }
274 if (!Contains(exclude_audio_properties,
275 &AudioProcessingProperties::goog_auto_gain_control)) {
276 EXPECT_EQ(properties.goog_auto_gain_control,
277 properties.goog_experimental_auto_gain_control);
278 if (!Contains(exclude_audio_properties,
279 &AudioProcessingProperties::
280 goog_experimental_auto_gain_control)) {
281 EXPECT_FALSE(properties.goog_auto_gain_control);
282 }
283 }
284 if (!Contains(
285 exclude_audio_properties,
286 &AudioProcessingProperties::goog_experimental_auto_gain_control)) {
287 EXPECT_EQ(properties.goog_auto_gain_control,
288 properties.goog_experimental_auto_gain_control);
289 if (!Contains(exclude_audio_properties,
290 &AudioProcessingProperties::goog_auto_gain_control)) {
291 EXPECT_FALSE(properties.goog_experimental_auto_gain_control);
292 }
293 }
294 if (!Contains(
295 exclude_audio_properties,
296 &AudioProcessingProperties::goog_experimental_echo_cancellation)) {
297 EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
298 }
299 if (!Contains(exclude_audio_properties,
300 &AudioProcessingProperties::goog_noise_suppression)) {
301 EXPECT_FALSE(properties.goog_noise_suppression);
302 }
303 if (!Contains(
304 exclude_audio_properties,
305 &AudioProcessingProperties::goog_experimental_noise_suppression)) {
306 EXPECT_FALSE(properties.goog_experimental_noise_suppression);
307 }
308 if (!Contains(exclude_audio_properties,
309 &AudioProcessingProperties::goog_highpass_filter)) {
310 EXPECT_FALSE(properties.goog_highpass_filter);
311 }
312 }
313
CheckBoolDefaults(const AudioSettingsBoolMembers & exclude_main_settings,const AudioPropertiesBoolMembers & exclude_audio_properties,const AudioCaptureSettings & result)314 void CheckBoolDefaults(
315 const AudioSettingsBoolMembers& exclude_main_settings,
316 const AudioPropertiesBoolMembers& exclude_audio_properties,
317 const AudioCaptureSettings& result) {
318 if (IsDeviceCapture()) {
319 CheckBoolDefaultsDeviceCapture(exclude_main_settings,
320 exclude_audio_properties, result);
321 } else {
322 CheckBoolDefaultsContentCapture(exclude_main_settings,
323 exclude_audio_properties, result);
324 }
325 }
326
CheckEchoCancellationTypeDefault(const AudioCaptureSettings & result)327 void CheckEchoCancellationTypeDefault(const AudioCaptureSettings& result) {
328 const auto& properties = result.audio_processing_properties();
329 if (IsDeviceCapture()) {
330 EXPECT_EQ(properties.echo_cancellation_type,
331 EchoCancellationType::kEchoCancellationAec3);
332 } else {
333 EXPECT_EQ(properties.echo_cancellation_type,
334 EchoCancellationType::kEchoCancellationDisabled);
335 }
336 }
337
CheckProcessingType(const AudioCaptureSettings & result)338 void CheckProcessingType(const AudioCaptureSettings& result) {
339 ProcessingType expected_type = ProcessingType::kUnprocessed;
340 const auto& properties = result.audio_processing_properties();
341 bool properties_value = false;
342 // Skip audio mirroring and start directly from auto gain control.
343 for (size_t i = 1; i < kAudioProcessingProperties.size(); ++i)
344 properties_value |= properties.*kAudioProcessingProperties[i];
345
346 // If goog_audio_mirroring is true but all the other properties are false,
347 // we should be expecting kProcessed, however if any of the properties was
348 // true, we should expected kApmProcessed.
349 if (properties.goog_audio_mirroring && !properties_value)
350 expected_type = ProcessingType::kNoApmProcessed;
351 else if (properties_value)
352 expected_type = ProcessingType::kApmProcessed;
353
354 // Finally, if the chosen echo cancellation type is either AEC3 or AEC2, the
355 // only possible processing type to expect is kWebRtcProcessed.
356 if (properties.echo_cancellation_type ==
357 EchoCancellationType::kEchoCancellationAec3) {
358 expected_type = ProcessingType::kApmProcessed;
359 }
360 EXPECT_EQ(result.processing_type(), expected_type);
361 }
362
CheckDevice(const AudioDeviceCaptureCapability & expected_device,const AudioCaptureSettings & result)363 void CheckDevice(const AudioDeviceCaptureCapability& expected_device,
364 const AudioCaptureSettings& result) {
365 EXPECT_EQ(expected_device.DeviceID().Utf8(), result.device_id());
366 }
367
CheckDeviceDefaults(const AudioCaptureSettings & result)368 void CheckDeviceDefaults(const AudioCaptureSettings& result) {
369 if (IsDeviceCapture())
370 CheckDevice(*default_device_, result);
371 else
372 EXPECT_TRUE(result.device_id().empty());
373 }
374
CheckAllDefaults(const AudioSettingsBoolMembers & exclude_main_settings,const AudioPropertiesBoolMembers & exclude_audio_properties,const AudioCaptureSettings & result)375 void CheckAllDefaults(
376 const AudioSettingsBoolMembers& exclude_main_settings,
377 const AudioPropertiesBoolMembers& exclude_audio_properties,
378 const AudioCaptureSettings& result) {
379 CheckProcessingType(result);
380 CheckBoolDefaults(exclude_main_settings, exclude_audio_properties, result);
381 CheckEchoCancellationTypeDefault(result);
382 CheckDeviceDefaults(result);
383 }
384
CheckAudioProcessingPropertiesForIdealEchoCancellationType(const AudioCaptureSettings & result)385 void CheckAudioProcessingPropertiesForIdealEchoCancellationType(
386 const AudioCaptureSettings& result) {
387 const AudioProcessingProperties& properties =
388 result.audio_processing_properties();
389
390 EXPECT_EQ(EchoCancellationType::kEchoCancellationSystem,
391 properties.echo_cancellation_type);
392 EXPECT_TRUE(properties.goog_auto_gain_control);
393 CheckGoogExperimentalEchoCancellationDefault(properties, true);
394 EXPECT_TRUE(properties.goog_noise_suppression);
395 EXPECT_TRUE(properties.goog_experimental_noise_suppression);
396 EXPECT_TRUE(properties.goog_highpass_filter);
397 EXPECT_TRUE(properties.goog_experimental_auto_gain_control);
398
399 // The following are not audio processing.
400 EXPECT_FALSE(properties.goog_audio_mirroring);
401 EXPECT_EQ(GetMediaStreamSource() != blink::kMediaStreamSourceDesktop,
402 result.disable_local_echo());
403 EXPECT_FALSE(result.render_to_associated_sink());
404 CheckDevice(*system_echo_canceller_device_, result);
405 }
406
GetEchoCancellationTypeFromConstraintString(const blink::WebString & constraint_string)407 EchoCancellationType GetEchoCancellationTypeFromConstraintString(
408 const blink::WebString& constraint_string) {
409 if (constraint_string == kEchoCancellationTypeValues[0])
410 return EchoCancellationType::kEchoCancellationAec3;
411 if (constraint_string == kEchoCancellationTypeValues[1])
412 return EchoCancellationType::kEchoCancellationAec3;
413 if (constraint_string == kEchoCancellationTypeValues[2])
414 return EchoCancellationType::kEchoCancellationSystem;
415
416 ADD_FAILURE() << "Invalid echo cancellation type constraint: "
417 << constraint_string.Ascii();
418 return EchoCancellationType::kEchoCancellationDisabled;
419 }
420
CheckLatencyConstraint(const AudioDeviceCaptureCapability * device,double min_latency,double max_latency)421 void CheckLatencyConstraint(const AudioDeviceCaptureCapability* device,
422 double min_latency,
423 double max_latency) {
424 constraint_factory_.Reset();
425 constraint_factory_.basic().device_id.SetExact(device->DeviceID());
426 constraint_factory_.basic().echo_cancellation.SetExact(false);
427 constraint_factory_.basic().latency.SetExact(0.0);
428 auto result = SelectSettings();
429 EXPECT_FALSE(result.HasValue());
430
431 constraint_factory_.Reset();
432 constraint_factory_.basic().device_id.SetExact(device->DeviceID());
433 constraint_factory_.basic().echo_cancellation.SetExact(false);
434 constraint_factory_.basic().latency.SetMin(max_latency + 0.001);
435 result = SelectSettings();
436 EXPECT_FALSE(result.HasValue());
437
438 constraint_factory_.Reset();
439 constraint_factory_.basic().device_id.SetExact(device->DeviceID());
440 constraint_factory_.basic().echo_cancellation.SetExact(false);
441 constraint_factory_.basic().latency.SetMax(min_latency - 0.001);
442 result = SelectSettings();
443 EXPECT_FALSE(result.HasValue());
444
445 CheckLocalMediaStreamAudioSourceLatency(
446 device, 0.001, min_latency * device->Parameters().sample_rate());
447 CheckLocalMediaStreamAudioSourceLatency(
448 device, 1.0, max_latency * device->Parameters().sample_rate());
449 }
450
CheckLocalMediaStreamAudioSourceLatency(const AudioDeviceCaptureCapability * device,double requested_latency,int expected_buffer_size)451 void CheckLocalMediaStreamAudioSourceLatency(
452 const AudioDeviceCaptureCapability* device,
453 double requested_latency,
454 int expected_buffer_size) {
455 constraint_factory_.Reset();
456 constraint_factory_.basic().device_id.SetExact(device->DeviceID());
457 constraint_factory_.basic().echo_cancellation.SetExact(false);
458 constraint_factory_.basic().latency.SetIdeal(requested_latency);
459 auto result = SelectSettings();
460 EXPECT_TRUE(result.HasValue());
461
462 std::unique_ptr<blink::LocalMediaStreamAudioSource> local_source =
463 GetLocalMediaStreamAudioSource(
464 false /* enable_system_echo_canceller */,
465 false /* disable_local_echo */,
466 false /* render_to_associated_sink */,
467 false /* enable_experimental_echo_canceller */,
468 base::OptionalOrNullptr(result.requested_buffer_size()));
469 EXPECT_EQ(local_source->GetAudioParameters().frames_per_buffer(),
470 expected_buffer_size);
471 }
472
473 blink::MockConstraintFactory constraint_factory_;
474 AudioDeviceCaptureCapabilities capabilities_;
475 const AudioDeviceCaptureCapability* default_device_ = nullptr;
476 const AudioDeviceCaptureCapability* system_echo_canceller_device_ = nullptr;
477 const AudioDeviceCaptureCapability* four_channels_device_ = nullptr;
478 const AudioDeviceCaptureCapability* variable_latency_device_ = nullptr;
479 std::unique_ptr<ProcessedLocalAudioSource> system_echo_canceller_source_ =
480 nullptr;
481 const std::vector<media::Point> kMicPositions = {{8, 8, 8}, {4, 4, 4}};
482
483 // TODO(grunell): Store these as separate constants and compare against those
484 // in tests, instead of indexing the vector.
485 const std::vector<blink::WebString> kEchoCancellationTypeValues = {
486 blink::WebString::FromASCII("browser"),
487 blink::WebString::FromASCII("aec3"),
488 blink::WebString::FromASCII("system")};
489
490 private:
491 ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_;
492 };
493
494 class MediaStreamConstraintsUtilAudioTest
495 : public MediaStreamConstraintsUtilAudioTestBase,
496 public testing::TestWithParam<std::string> {
497 public:
SetUp()498 void SetUp() override {
499 ResetFactory();
500 if (IsDeviceCapture()) {
501 capabilities_.emplace_back(
502 "default_device", "fake_group1",
503 media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
504 media::CHANNEL_LAYOUT_STEREO,
505 media::AudioParameters::kAudioCDSampleRate,
506 1000));
507
508 media::AudioParameters system_echo_canceller_parameters(
509 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
510 media::CHANNEL_LAYOUT_STEREO,
511 media::AudioParameters::kAudioCDSampleRate, 1000);
512 system_echo_canceller_parameters.set_effects(
513 media::AudioParameters::ECHO_CANCELLER);
514 capabilities_.emplace_back("system_echo_canceller_device", "fake_group2",
515 system_echo_canceller_parameters);
516
517 capabilities_.emplace_back(
518 "4_channels_device", "fake_group3",
519 media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
520 media::CHANNEL_LAYOUT_4_0,
521 media::AudioParameters::kAudioCDSampleRate,
522 1000));
523
524 capabilities_.emplace_back(
525 "8khz_sample_rate_device", "fake_group4",
526 media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
527 media::CHANNEL_LAYOUT_STEREO,
528 blink::AudioProcessing::kSampleRate8kHz,
529 1000));
530
531 capabilities_.emplace_back(
532 "variable_latency_device", "fake_group5",
533 media::AudioParameters(
534 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
535 media::CHANNEL_LAYOUT_STEREO,
536 media::AudioParameters::kAudioCDSampleRate, 512,
537 media::AudioParameters::HardwareCapabilities(128, 4096)));
538
539 default_device_ = &capabilities_[0];
540 system_echo_canceller_device_ = &capabilities_[1];
541 four_channels_device_ = &capabilities_[2];
542 variable_latency_device_ = &capabilities_[4];
543 } else {
544 // For content capture, use a single capability that admits all possible
545 // settings.
546 capabilities_.emplace_back();
547 }
548 }
549
GetMediaStreamSource()550 std::string GetMediaStreamSource() override { return GetParam(); }
551 };
552
553 class MediaStreamConstraintsRemoteAPMTest
554 : public MediaStreamConstraintsUtilAudioTestBase,
555 public testing::TestWithParam<bool> {
SetUp()556 void SetUp() override {
557 if (UseRemoteAPMFlag()) {
558 scoped_feature_list_.InitAndEnableFeature(
559 features::kWebRtcApmInAudioService);
560 } else {
561 scoped_feature_list_.InitAndDisableFeature(
562 features::kWebRtcApmInAudioService);
563 }
564
565 // Setup the capabilities.
566 ResetFactory();
567 if (IsDeviceCapture()) {
568 capabilities_.emplace_back(
569 "default_device", "fake_group1",
570 media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
571 media::CHANNEL_LAYOUT_STEREO,
572 media::AudioParameters::kAudioCDSampleRate,
573 1000));
574 default_device_ = &capabilities_[0];
575 }
576 }
577
UseRemoteAPMFlag()578 bool UseRemoteAPMFlag() { return GetParam(); }
579
580 private:
581 base::test::ScopedFeatureList scoped_feature_list_;
582 };
583
584 // The Unconstrained test checks the default selection criteria.
TEST_P(MediaStreamConstraintsUtilAudioTest,Unconstrained)585 TEST_P(MediaStreamConstraintsUtilAudioTest, Unconstrained) {
586 auto result = SelectSettings();
587
588 // All settings should have default values.
589 EXPECT_TRUE(result.HasValue());
590 CheckAllDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
591 result);
592 }
593
594 // This test checks all possible ways to set boolean constraints (except
595 // echo cancellation constraints, which are not mapped 1:1 to output audio
596 // processing properties).
TEST_P(MediaStreamConstraintsUtilAudioTest,SingleBoolConstraint)597 TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) {
598 AudioSettingsBoolMembers kMainSettings = {
599 &AudioCaptureSettings::disable_local_echo,
600 &AudioCaptureSettings::render_to_associated_sink};
601
602 const std::vector<blink::BooleanConstraint MediaTrackConstraintSetPlatform::*>
603 kMainBoolConstraints = {
604 &MediaTrackConstraintSetPlatform::disable_local_echo,
605 &MediaTrackConstraintSetPlatform::render_to_associated_sink};
606
607 ASSERT_EQ(kMainSettings.size(), kMainBoolConstraints.size());
608 for (auto set_function : kBoolSetFunctions) {
609 for (auto accessor : kFactoryAccessors) {
610 // Ideal advanced is ignored by the SelectSettings algorithm.
611 // Using array elements instead of pointer values due to the comparison
612 // failing on some build configurations.
613 if (set_function == kBoolSetFunctions[1] &&
614 accessor == kFactoryAccessors[1]) {
615 continue;
616 }
617 for (size_t i = 0; i < kMainSettings.size(); ++i) {
618 for (bool value : kBoolValues) {
619 ResetFactory();
620 (((constraint_factory_.*accessor)().*kMainBoolConstraints[i]).*
621 set_function)(value);
622 auto result = SelectSettings();
623 EXPECT_TRUE(result.HasValue());
624 EXPECT_EQ(value, (result.*kMainSettings[i])());
625 CheckAllDefaults({kMainSettings[i]}, AudioPropertiesBoolMembers(),
626 result);
627 }
628 }
629 }
630 }
631
632 const std::vector<blink::BooleanConstraint MediaTrackConstraintSetPlatform::*>
633 kAudioProcessingConstraints = {
634 &MediaTrackConstraintSetPlatform::goog_audio_mirroring,
635 &MediaTrackConstraintSetPlatform::goog_auto_gain_control,
636 &MediaTrackConstraintSetPlatform::goog_experimental_echo_cancellation,
637 &MediaTrackConstraintSetPlatform::goog_noise_suppression,
638 &MediaTrackConstraintSetPlatform::goog_experimental_noise_suppression,
639 &MediaTrackConstraintSetPlatform::goog_highpass_filter,
640 &MediaTrackConstraintSetPlatform::goog_experimental_auto_gain_control,
641 };
642
643 ASSERT_EQ(kAudioProcessingProperties.size(),
644 kAudioProcessingConstraints.size());
645 for (auto set_function : kBoolSetFunctions) {
646 for (auto accessor : kFactoryAccessors) {
647 // Ideal advanced is ignored by the SelectSettings algorithm.
648 // Using array elements instead of pointer values due to the comparison
649 // failing on some build configurations.
650 if (set_function == kBoolSetFunctions[1] &&
651 accessor == kFactoryAccessors[1]) {
652 continue;
653 }
654 for (size_t i = 0; i < kAudioProcessingProperties.size(); ++i) {
655 for (bool value : kBoolValues) {
656 ResetFactory();
657 (((constraint_factory_.*accessor)().*kAudioProcessingConstraints[i]).*
658 set_function)(value);
659 auto result = SelectSettings();
660 EXPECT_TRUE(result.HasValue());
661 EXPECT_EQ(value, result.audio_processing_properties().*
662 kAudioProcessingProperties[i]);
663 CheckAllDefaults(AudioSettingsBoolMembers(),
664 {kAudioProcessingProperties[i]}, result);
665 }
666 }
667 }
668 }
669 }
670
TEST_P(MediaStreamConstraintsUtilAudioTest,SampleSize)671 TEST_P(MediaStreamConstraintsUtilAudioTest, SampleSize) {
672 ResetFactory();
673 constraint_factory_.basic().sample_size.SetExact(16);
674 auto result = SelectSettings();
675 EXPECT_TRUE(result.HasValue());
676
677 ResetFactory();
678 constraint_factory_.basic().sample_size.SetExact(0);
679 result = SelectSettings();
680 EXPECT_FALSE(result.HasValue());
681
682 // Only set a min value for the constraint.
683 ResetFactory();
684 constraint_factory_.basic().sample_size.SetMin(16);
685 result = SelectSettings();
686 EXPECT_TRUE(result.HasValue());
687
688 ResetFactory();
689 constraint_factory_.basic().sample_size.SetMin(17);
690 result = SelectSettings();
691 EXPECT_FALSE(result.HasValue());
692
693 // Only set a max value for the constraint.
694 ResetFactory();
695 constraint_factory_.basic().sample_size.SetMax(16);
696 result = SelectSettings();
697 EXPECT_TRUE(result.HasValue());
698
699 ResetFactory();
700 constraint_factory_.basic().sample_size.SetMax(15);
701 result = SelectSettings();
702 EXPECT_FALSE(result.HasValue());
703
704 // Define a bounded range for the constraint.
705 ResetFactory();
706 constraint_factory_.basic().sample_size.SetMin(10);
707 constraint_factory_.basic().sample_size.SetMax(20);
708 result = SelectSettings();
709 EXPECT_TRUE(result.HasValue());
710
711 ResetFactory();
712 constraint_factory_.basic().sample_size.SetMin(-10);
713 constraint_factory_.basic().sample_size.SetMax(10);
714 result = SelectSettings();
715 EXPECT_FALSE(result.HasValue());
716
717 ResetFactory();
718 constraint_factory_.basic().sample_size.SetMin(20);
719 constraint_factory_.basic().sample_size.SetMax(30);
720 result = SelectSettings();
721 EXPECT_FALSE(result.HasValue());
722
723 // Test ideal constraints.
724 ResetFactory();
725 constraint_factory_.basic().sample_size.SetIdeal(16);
726 result = SelectSettings();
727 EXPECT_TRUE(result.HasValue());
728
729 ResetFactory();
730 constraint_factory_.basic().sample_size.SetIdeal(0);
731 result = SelectSettings();
732 EXPECT_TRUE(result.HasValue());
733 }
734
TEST_P(MediaStreamConstraintsUtilAudioTest,Channels)735 TEST_P(MediaStreamConstraintsUtilAudioTest, Channels) {
736 int channel_count = kMinChannels;
737 AudioCaptureSettings result;
738
739 // Test set exact channelCount.
740 for (; channel_count <= media::limits::kMaxChannels; ++channel_count) {
741 ResetFactory();
742 constraint_factory_.basic().channel_count.SetExact(channel_count);
743 result = SelectSettings();
744
745 if (!IsDeviceCapture()) {
746 // The source capture configured above is actually using a channel count
747 // set to 2 channels.
748 if (channel_count <= 2)
749 EXPECT_TRUE(result.HasValue());
750 else
751 EXPECT_FALSE(result.HasValue());
752 continue;
753 }
754
755 if (channel_count == 3 || channel_count > 4) {
756 EXPECT_FALSE(result.HasValue());
757 continue;
758 }
759
760 EXPECT_TRUE(result.HasValue());
761 if (channel_count == 4)
762 EXPECT_EQ(result.device_id(), "4_channels_device");
763 else
764 EXPECT_EQ(result.device_id(), "default_device");
765 }
766
767 // Only set a min value for the constraint.
768 ResetFactory();
769 constraint_factory_.basic().channel_count.SetMin(media::limits::kMaxChannels +
770 1);
771 result = SelectSettings();
772 EXPECT_FALSE(result.HasValue());
773
774 constraint_factory_.basic().channel_count.SetMin(kMinChannels);
775 result = SelectSettings();
776 EXPECT_TRUE(result.HasValue());
777
778 // Only set a max value for the constraint.
779 ResetFactory();
780 constraint_factory_.basic().channel_count.SetMax(kMinChannels - 1);
781 result = SelectSettings();
782 EXPECT_FALSE(result.HasValue());
783
784 constraint_factory_.basic().channel_count.SetMax(kMinChannels);
785 result = SelectSettings();
786 EXPECT_TRUE(result.HasValue());
787
788 // Define a bounded range for the constraint.
789 ResetFactory();
790 constraint_factory_.basic().channel_count.SetMin(kMinChannels);
791 constraint_factory_.basic().channel_count.SetMax(media::limits::kMaxChannels);
792 result = SelectSettings();
793 EXPECT_TRUE(result.HasValue());
794
795 constraint_factory_.basic().channel_count.SetMin(kMinChannels - 10);
796 constraint_factory_.basic().channel_count.SetMax(kMinChannels - 1);
797 result = SelectSettings();
798 EXPECT_FALSE(result.HasValue());
799
800 constraint_factory_.basic().channel_count.SetMin(media::limits::kMaxChannels +
801 1);
802 constraint_factory_.basic().channel_count.SetMax(media::limits::kMaxChannels +
803 10);
804 result = SelectSettings();
805 EXPECT_FALSE(result.HasValue());
806
807 // Test ideal constraints.
808 for (; channel_count <= media::limits::kMaxChannels; ++channel_count) {
809 ResetFactory();
810 constraint_factory_.basic().channel_count.SetExact(channel_count);
811 result = SelectSettings();
812
813 EXPECT_TRUE(result.HasValue());
814 if (IsDeviceCapture()) {
815 if (channel_count == 4)
816 EXPECT_EQ(result.device_id(), "4_channels_device");
817 else
818 EXPECT_EQ(result.device_id(), "default_device");
819 }
820 }
821 }
822
TEST_P(MediaStreamConstraintsUtilAudioTest,ChannelsWithSource)823 TEST_P(MediaStreamConstraintsUtilAudioTest, ChannelsWithSource) {
824 if (!IsDeviceCapture())
825 return;
826
827 std::unique_ptr<blink::LocalMediaStreamAudioSource> source =
828 GetLocalMediaStreamAudioSource(false /* enable_system_echo_canceller */,
829 false /* disable_local_echo */,
830 false /* render_to_associated_sink */);
831 int channel_count = kMinChannels;
832 for (; channel_count <= media::limits::kMaxChannels; ++channel_count) {
833 ResetFactory();
834 constraint_factory_.basic().channel_count.SetExact(channel_count);
835 auto result = SelectSettingsAudioCapture(
836 source.get(), constraint_factory_.CreateMediaConstraints());
837 if (channel_count == 2)
838 EXPECT_TRUE(result.HasValue());
839 else
840 EXPECT_FALSE(result.HasValue());
841 }
842 }
843
TEST_P(MediaStreamConstraintsUtilAudioTest,SampleRate)844 TEST_P(MediaStreamConstraintsUtilAudioTest, SampleRate) {
845 AudioCaptureSettings result;
846 int exact_sample_rate = blink::AudioProcessing::kSampleRate8kHz;
847 int min_sample_rate = blink::AudioProcessing::kSampleRate8kHz;
848 // |max_sample_rate| is different based on architecture, namely due to a
849 // difference on Android.
850 int max_sample_rate =
851 std::max(static_cast<int>(media::AudioParameters::kAudioCDSampleRate),
852 blink::kAudioProcessingSampleRate);
853 int ideal_sample_rate = blink::AudioProcessing::kSampleRate8kHz;
854 if (!IsDeviceCapture()) {
855 exact_sample_rate = media::AudioParameters::kAudioCDSampleRate;
856 min_sample_rate =
857 std::min(static_cast<int>(media::AudioParameters::kAudioCDSampleRate),
858 blink::kAudioProcessingSampleRate);
859 ideal_sample_rate = media::AudioParameters::kAudioCDSampleRate;
860 }
861
862 // Test set exact sampleRate.
863 ResetFactory();
864 constraint_factory_.basic().sample_rate.SetExact(exact_sample_rate);
865 result = SelectSettings();
866 EXPECT_TRUE(result.HasValue());
867 if (IsDeviceCapture())
868 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
869
870 constraint_factory_.basic().sample_rate.SetExact(11111);
871 result = SelectSettings();
872 EXPECT_FALSE(result.HasValue());
873
874 // Only set a min value for the constraint.
875 ResetFactory();
876 constraint_factory_.basic().sample_rate.SetMin(max_sample_rate);
877 result = SelectSettings();
878 EXPECT_TRUE(result.HasValue());
879 if (IsDeviceCapture())
880 EXPECT_EQ(result.device_id(), "default_device");
881
882 constraint_factory_.basic().sample_rate.SetMin(max_sample_rate + 1);
883 result = SelectSettings();
884 EXPECT_FALSE(result.HasValue());
885
886 // Only set a max value for the constraint.
887 ResetFactory();
888 constraint_factory_.basic().sample_rate.SetMax(min_sample_rate);
889 result = SelectSettings();
890 EXPECT_TRUE(result.HasValue());
891 if (IsDeviceCapture())
892 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
893
894 constraint_factory_.basic().sample_rate.SetMax(min_sample_rate - 1);
895 result = SelectSettings();
896 EXPECT_FALSE(result.HasValue());
897
898 // Define a bounded range for the constraint.
899 ResetFactory();
900 constraint_factory_.basic().sample_rate.SetMin(min_sample_rate);
901 constraint_factory_.basic().sample_rate.SetMax(max_sample_rate);
902 result = SelectSettings();
903 EXPECT_TRUE(result.HasValue());
904 if (IsDeviceCapture())
905 EXPECT_EQ(result.device_id(), "default_device");
906
907 constraint_factory_.basic().sample_rate.SetMin(min_sample_rate - 1000);
908 constraint_factory_.basic().sample_rate.SetMax(min_sample_rate - 1);
909 result = SelectSettings();
910 EXPECT_FALSE(result.HasValue());
911
912 constraint_factory_.basic().sample_rate.SetMin(max_sample_rate + 1);
913 constraint_factory_.basic().sample_rate.SetMax(max_sample_rate + 1000);
914 result = SelectSettings();
915 EXPECT_FALSE(result.HasValue());
916
917 // Test ideal constraints.
918 ResetFactory();
919 constraint_factory_.basic().sample_rate.SetIdeal(ideal_sample_rate);
920 result = SelectSettings();
921 EXPECT_TRUE(result.HasValue());
922 if (IsDeviceCapture())
923 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
924
925 constraint_factory_.basic().sample_rate.SetIdeal(ideal_sample_rate);
926 result = SelectSettings();
927 EXPECT_TRUE(result.HasValue());
928 if (IsDeviceCapture())
929 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
930
931 if (IsDeviceCapture()) {
932 constraint_factory_.basic().sample_rate.SetIdeal(
933 blink::AudioProcessing::kSampleRate48kHz + 1000);
934 result = SelectSettings();
935 EXPECT_TRUE(result.HasValue());
936 EXPECT_EQ(result.device_id(), "default_device");
937 }
938 }
939
TEST_P(MediaStreamConstraintsUtilAudioTest,SampleRateWithSource)940 TEST_P(MediaStreamConstraintsUtilAudioTest, SampleRateWithSource) {
941 if (!IsDeviceCapture())
942 return;
943
944 std::unique_ptr<blink::LocalMediaStreamAudioSource> source =
945 GetLocalMediaStreamAudioSource(false /* enable_system_echo_canceller */,
946 false /* disable_local_echo */,
947 false /* render_to_associated_sink */);
948
949 // Test set exact sampleRate.
950 ResetFactory();
951 constraint_factory_.basic().sample_rate.SetExact(
952 media::AudioParameters::kAudioCDSampleRate);
953 auto result = SelectSettingsAudioCapture(
954 source.get(), constraint_factory_.CreateMediaConstraints());
955 EXPECT_TRUE(result.HasValue());
956
957 constraint_factory_.basic().sample_rate.SetExact(11111);
958 result = SelectSettingsAudioCapture(
959 source.get(), constraint_factory_.CreateMediaConstraints());
960 EXPECT_FALSE(result.HasValue());
961
962 // Test set min sampleRate.
963 ResetFactory();
964 constraint_factory_.basic().sample_rate.SetMin(
965 media::AudioParameters::kAudioCDSampleRate);
966 result = SelectSettingsAudioCapture(
967 source.get(), constraint_factory_.CreateMediaConstraints());
968 EXPECT_TRUE(result.HasValue());
969
970 constraint_factory_.basic().sample_rate.SetMin(
971 media::AudioParameters::kAudioCDSampleRate + 1);
972 result = SelectSettingsAudioCapture(
973 source.get(), constraint_factory_.CreateMediaConstraints());
974 EXPECT_FALSE(result.HasValue());
975
976 // Test set max sampleRate.
977 ResetFactory();
978 constraint_factory_.basic().sample_rate.SetMax(
979 media::AudioParameters::kAudioCDSampleRate);
980 result = SelectSettingsAudioCapture(
981 source.get(), constraint_factory_.CreateMediaConstraints());
982 EXPECT_TRUE(result.HasValue());
983
984 constraint_factory_.basic().sample_rate.SetMax(
985 media::AudioParameters::kAudioCDSampleRate - 1);
986 result = SelectSettingsAudioCapture(
987 source.get(), constraint_factory_.CreateMediaConstraints());
988 EXPECT_FALSE(result.HasValue());
989
990 // Test set ideal sampleRate.
991 ResetFactory();
992 constraint_factory_.basic().sample_rate.SetIdeal(
993 media::AudioParameters::kAudioCDSampleRate);
994 result = SelectSettingsAudioCapture(
995 source.get(), constraint_factory_.CreateMediaConstraints());
996 EXPECT_TRUE(result.HasValue());
997
998 constraint_factory_.basic().sample_rate.SetIdeal(
999 media::AudioParameters::kAudioCDSampleRate - 1);
1000 result = SelectSettingsAudioCapture(
1001 source.get(), constraint_factory_.CreateMediaConstraints());
1002 EXPECT_TRUE(result.HasValue());
1003 }
1004
TEST_P(MediaStreamConstraintsUtilAudioTest,Latency)1005 TEST_P(MediaStreamConstraintsUtilAudioTest, Latency) {
1006 // Test set exact sampleRate.
1007 ResetFactory();
1008 if (IsDeviceCapture())
1009 constraint_factory_.basic().latency.SetExact(0.125);
1010 else
1011 constraint_factory_.basic().latency.SetExact(0.01);
1012 auto result = SelectSettings();
1013 EXPECT_TRUE(result.HasValue());
1014 if (IsDeviceCapture())
1015 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
1016
1017 constraint_factory_.basic().latency.SetExact(
1018 static_cast<double>(blink::kFallbackAudioLatencyMs) / 1000);
1019 result = SelectSettings();
1020 EXPECT_TRUE(result.HasValue());
1021 if (IsDeviceCapture())
1022 EXPECT_EQ(result.device_id(), "default_device");
1023
1024 constraint_factory_.basic().latency.SetExact(0.0);
1025 result = SelectSettings();
1026 EXPECT_FALSE(result.HasValue());
1027
1028 // Test set min sampleRate.
1029 ResetFactory();
1030 if (IsDeviceCapture())
1031 constraint_factory_.basic().latency.SetMin(0.125);
1032 else
1033 constraint_factory_.basic().latency.SetMin(0.01);
1034 result = SelectSettings();
1035 EXPECT_TRUE(result.HasValue());
1036 if (IsDeviceCapture())
1037 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
1038
1039 constraint_factory_.basic().latency.SetMin(0.126);
1040 result = SelectSettings();
1041 EXPECT_FALSE(result.HasValue());
1042
1043 // Test set max sampleRate.
1044 ResetFactory();
1045 constraint_factory_.basic().latency.SetMax(0.1);
1046 result = SelectSettings();
1047 EXPECT_TRUE(result.HasValue());
1048 if (IsDeviceCapture())
1049 EXPECT_EQ(result.device_id(), "default_device");
1050
1051 constraint_factory_.basic().latency.SetMax(0.001);
1052 result = SelectSettings();
1053 EXPECT_FALSE(result.HasValue());
1054
1055 // Test set bounded sampleRate range.
1056 ResetFactory();
1057 if (IsDeviceCapture()) {
1058 constraint_factory_.basic().latency.SetMin(0.1);
1059 constraint_factory_.basic().latency.SetMax(0.125);
1060 } else {
1061 constraint_factory_.basic().latency.SetMin(0.01);
1062 constraint_factory_.basic().latency.SetMax(0.1);
1063 }
1064 result = SelectSettings();
1065 EXPECT_TRUE(result.HasValue());
1066 if (IsDeviceCapture())
1067 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
1068
1069 constraint_factory_.basic().latency.SetMin(0.0001);
1070 constraint_factory_.basic().latency.SetMax(0.001);
1071 result = SelectSettings();
1072 EXPECT_FALSE(result.HasValue());
1073
1074 constraint_factory_.basic().latency.SetMin(0.126);
1075 constraint_factory_.basic().latency.SetMax(0.2);
1076 result = SelectSettings();
1077 EXPECT_FALSE(result.HasValue());
1078
1079 // Test set ideal sampleRate range.
1080 ResetFactory();
1081 if (IsDeviceCapture())
1082 constraint_factory_.basic().latency.SetIdeal(0.125);
1083 else
1084 constraint_factory_.basic().latency.SetIdeal(0.01);
1085 result = SelectSettings();
1086 EXPECT_TRUE(result.HasValue());
1087 if (IsDeviceCapture())
1088 EXPECT_EQ(result.device_id(), "8khz_sample_rate_device");
1089
1090 constraint_factory_.basic().latency.SetIdeal(0.0);
1091 result = SelectSettings();
1092 EXPECT_TRUE(result.HasValue());
1093 if (IsDeviceCapture())
1094 EXPECT_EQ(result.device_id(), "default_device");
1095 }
1096
TEST_P(MediaStreamConstraintsUtilAudioTest,LatencyWithSource)1097 TEST_P(MediaStreamConstraintsUtilAudioTest, LatencyWithSource) {
1098 if (!IsDeviceCapture())
1099 return;
1100
1101 std::unique_ptr<blink::LocalMediaStreamAudioSource> source =
1102 GetLocalMediaStreamAudioSource(false /* enable_system_echo_canceller */,
1103 false /* disable_local_echo */,
1104 false /* render_to_associated_sink */);
1105 // Test set exact sampleRate.
1106 ResetFactory();
1107 constraint_factory_.basic().latency.SetExact(0.01);
1108 auto result = SelectSettingsAudioCapture(
1109 source.get(), constraint_factory_.CreateMediaConstraints());
1110 EXPECT_TRUE(result.HasValue());
1111
1112 constraint_factory_.basic().latency.SetExact(0.1234);
1113 result = SelectSettingsAudioCapture(
1114 source.get(), constraint_factory_.CreateMediaConstraints());
1115 EXPECT_FALSE(result.HasValue());
1116
1117 // Test set min sampleRate.
1118 ResetFactory();
1119 constraint_factory_.basic().latency.SetMin(0.01);
1120 result = SelectSettings();
1121 EXPECT_TRUE(result.HasValue());
1122
1123 constraint_factory_.basic().latency.SetMin(0.2);
1124 result = SelectSettings();
1125 EXPECT_FALSE(result.HasValue());
1126
1127 // Test set max sampleRate.
1128 ResetFactory();
1129 constraint_factory_.basic().latency.SetMax(
1130 static_cast<double>(blink::kFallbackAudioLatencyMs) / 1000);
1131 result = SelectSettings();
1132 EXPECT_TRUE(result.HasValue());
1133
1134 constraint_factory_.basic().latency.SetMax(0.001);
1135 result = SelectSettings();
1136 EXPECT_FALSE(result.HasValue());
1137
1138 // Test set bounded sampleRate range.
1139 ResetFactory();
1140 constraint_factory_.basic().latency.SetMin(0.01);
1141 constraint_factory_.basic().latency.SetMax(0.1);
1142 result = SelectSettings();
1143 EXPECT_TRUE(result.HasValue());
1144
1145 constraint_factory_.basic().latency.SetMin(0.0001);
1146 constraint_factory_.basic().latency.SetMax(0.001);
1147 result = SelectSettings();
1148 EXPECT_FALSE(result.HasValue());
1149
1150 constraint_factory_.basic().latency.SetMin(0.2);
1151 constraint_factory_.basic().latency.SetMax(0.4);
1152 result = SelectSettings();
1153 EXPECT_FALSE(result.HasValue());
1154
1155 // Test set ideal sampleRate.
1156 ResetFactory();
1157 constraint_factory_.basic().latency.SetIdeal(0.01);
1158 result = SelectSettingsAudioCapture(
1159 source.get(), constraint_factory_.CreateMediaConstraints());
1160 EXPECT_TRUE(result.HasValue());
1161
1162 constraint_factory_.basic().latency.SetIdeal(0.1234);
1163 result = SelectSettingsAudioCapture(
1164 source.get(), constraint_factory_.CreateMediaConstraints());
1165 EXPECT_TRUE(result.HasValue());
1166 }
1167
1168 // DeviceID tests.
TEST_P(MediaStreamConstraintsUtilAudioTest,ExactArbitraryDeviceID)1169 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactArbitraryDeviceID) {
1170 const String kArbitraryDeviceID = "arbitrary";
1171 constraint_factory_.basic().device_id.SetExact(kArbitraryDeviceID);
1172 auto result = SelectSettings();
1173 // kArbitraryDeviceID is invalid for device capture, but it is considered
1174 // valid for content capture. For content capture, validation of device
1175 // capture is performed by the getUserMedia() implementation.
1176 if (IsDeviceCapture()) {
1177 EXPECT_FALSE(result.HasValue());
1178 EXPECT_EQ(std::string(constraint_factory_.basic().device_id.GetName()),
1179 std::string(result.failed_constraint_name()));
1180 } else {
1181 EXPECT_TRUE(result.HasValue());
1182 EXPECT_EQ(kArbitraryDeviceID.Utf8(), result.device_id());
1183 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1184 result);
1185 CheckEchoCancellationTypeDefault(result);
1186 }
1187 }
1188
1189 // DeviceID tests check various ways to deal with the device_id constraint.
TEST_P(MediaStreamConstraintsUtilAudioTest,IdealArbitraryDeviceID)1190 TEST_P(MediaStreamConstraintsUtilAudioTest, IdealArbitraryDeviceID) {
1191 const String kArbitraryDeviceID = "arbitrary";
1192 constraint_factory_.basic().device_id.SetIdeal(kArbitraryDeviceID);
1193 auto result = SelectSettings();
1194 EXPECT_TRUE(result.HasValue());
1195 // kArbitraryDeviceID is invalid for device capture, but it is considered
1196 // valid for content capture. For content capture, validation of device
1197 // capture is performed by the getUserMedia() implementation.
1198 if (IsDeviceCapture())
1199 CheckDeviceDefaults(result);
1200 else
1201 EXPECT_EQ(kArbitraryDeviceID.Utf8(), result.device_id());
1202 CheckProcessingType(result);
1203 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1204 result);
1205 CheckEchoCancellationTypeDefault(result);
1206 }
1207
TEST_P(MediaStreamConstraintsUtilAudioTest,ExactValidDeviceID)1208 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidDeviceID) {
1209 for (const auto& device : capabilities_) {
1210 constraint_factory_.basic().device_id.SetExact(device.DeviceID());
1211 auto result = SelectSettings();
1212 EXPECT_TRUE(result.HasValue());
1213 CheckDevice(device, result);
1214 CheckProcessingType(result);
1215 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1216 result);
1217 EchoCancellationType expected_echo_cancellation_type =
1218 EchoCancellationType::kEchoCancellationDisabled;
1219 if (IsDeviceCapture()) {
1220 const bool has_system_echo_cancellation =
1221 device.Parameters().effects() &
1222 media::AudioParameters::ECHO_CANCELLER;
1223 expected_echo_cancellation_type =
1224 has_system_echo_cancellation
1225 ? EchoCancellationType::kEchoCancellationSystem
1226 : EchoCancellationType::kEchoCancellationAec3;
1227 }
1228 EXPECT_EQ(expected_echo_cancellation_type,
1229 result.audio_processing_properties().echo_cancellation_type);
1230 }
1231 }
1232
TEST_P(MediaStreamConstraintsUtilAudioTest,ExactGroupID)1233 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactGroupID) {
1234 for (const auto& device : capabilities_) {
1235 constraint_factory_.basic().group_id.SetExact(device.GroupID());
1236 auto result = SelectSettings();
1237 EXPECT_TRUE(result.HasValue());
1238 CheckDevice(device, result);
1239 CheckProcessingType(result);
1240 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1241 result);
1242 EchoCancellationType expected_echo_cancellation_type =
1243 EchoCancellationType::kEchoCancellationDisabled;
1244 if (IsDeviceCapture()) {
1245 const bool has_system_echo_cancellation =
1246 device.Parameters().effects() &
1247 media::AudioParameters::ECHO_CANCELLER;
1248 expected_echo_cancellation_type =
1249 has_system_echo_cancellation
1250 ? EchoCancellationType::kEchoCancellationSystem
1251 : EchoCancellationType::kEchoCancellationAec3;
1252 }
1253 EXPECT_EQ(expected_echo_cancellation_type,
1254 result.audio_processing_properties().echo_cancellation_type);
1255 }
1256 }
1257
1258 // Tests the echoCancellation constraint with a device without system echo
1259 // cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest,EchoCancellationWithWebRtc)1260 TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithWebRtc) {
1261 for (auto set_function : kBoolSetFunctions) {
1262 for (auto accessor : kFactoryAccessors) {
1263 // Ideal advanced is ignored by the SelectSettings algorithm.
1264 // Using array elements instead of pointer values due to the comparison
1265 // failing on some build configurations.
1266 if (set_function == kBoolSetFunctions[1] &&
1267 accessor == kFactoryAccessors[1]) {
1268 continue;
1269 }
1270 for (bool value : kBoolValues) {
1271 ResetFactory();
1272 ((constraint_factory_.*accessor)().echo_cancellation.*
1273 set_function)(value);
1274 auto result = SelectSettings();
1275 EXPECT_TRUE(result.HasValue());
1276 const AudioProcessingProperties& properties =
1277 result.audio_processing_properties();
1278 // With device capture, the echo_cancellation constraint
1279 // enables/disables all audio processing by default.
1280 // With content capture, the echo_cancellation constraint controls
1281 // only the echo_cancellation properties. The other audio processing
1282 // properties default to false.
1283 const EchoCancellationType expected_echo_cancellation_type =
1284 value ? EchoCancellationType::kEchoCancellationAec3
1285 : EchoCancellationType::kEchoCancellationDisabled;
1286 EXPECT_EQ(expected_echo_cancellation_type,
1287 properties.echo_cancellation_type);
1288 const bool enable_webrtc_audio_processing =
1289 IsDeviceCapture() ? value : false;
1290 EXPECT_EQ(enable_webrtc_audio_processing,
1291 properties.goog_auto_gain_control);
1292 CheckGoogExperimentalEchoCancellationDefault(
1293 properties, enable_webrtc_audio_processing);
1294 EXPECT_EQ(enable_webrtc_audio_processing,
1295 properties.goog_noise_suppression);
1296 EXPECT_EQ(enable_webrtc_audio_processing,
1297 properties.goog_experimental_noise_suppression);
1298 EXPECT_EQ(enable_webrtc_audio_processing,
1299 properties.goog_highpass_filter);
1300 EXPECT_EQ(enable_webrtc_audio_processing,
1301 properties.goog_experimental_auto_gain_control);
1302
1303 // The following are not audio processing.
1304 EXPECT_FALSE(properties.goog_audio_mirroring);
1305 EXPECT_EQ(GetMediaStreamSource() != blink::kMediaStreamSourceDesktop,
1306 result.disable_local_echo());
1307 EXPECT_FALSE(result.render_to_associated_sink());
1308 CheckProcessingType(result);
1309 if (IsDeviceCapture()) {
1310 CheckDevice(*default_device_, result);
1311 } else {
1312 EXPECT_TRUE(result.device_id().empty());
1313 }
1314 }
1315 }
1316 }
1317 }
1318
1319 // Tests the echoCancellation constraint with a device with system echo
1320 // cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest,EchoCancellationWithSystem)1321 TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSystem) {
1322 // With content capture, there is no system echo cancellation, so
1323 // nothing to test.
1324 if (!IsDeviceCapture())
1325 return;
1326
1327 for (auto set_function : kBoolSetFunctions) {
1328 for (auto accessor : kFactoryAccessors) {
1329 // Ideal advanced is ignored by the SelectSettings algorithm.
1330 // Using array elements instead of pointer values due to the comparison
1331 // failing on some build configurations.
1332 if (set_function == kBoolSetFunctions[1] &&
1333 accessor == kFactoryAccessors[1]) {
1334 continue;
1335 }
1336 for (bool value : kBoolValues) {
1337 ResetFactory();
1338 constraint_factory_.basic().device_id.SetExact(
1339 system_echo_canceller_device_->DeviceID());
1340 ((constraint_factory_.*accessor)().echo_cancellation.*
1341 set_function)(value);
1342 auto result = SelectSettings();
1343 EXPECT_TRUE(result.HasValue());
1344 const AudioProcessingProperties& properties =
1345 result.audio_processing_properties();
1346 // With system echo cancellation, the echo_cancellation constraint
1347 // enables/disables all audio processing by default, WebRTC echo
1348 // cancellation is always disabled, and system echo cancellation is
1349 // disabled if the echo_cancellation constraint is false.
1350 const EchoCancellationType expected_echo_cancellation_type =
1351 value ? EchoCancellationType::kEchoCancellationSystem
1352 : EchoCancellationType::kEchoCancellationDisabled;
1353 EXPECT_EQ(expected_echo_cancellation_type,
1354 properties.echo_cancellation_type);
1355 EXPECT_EQ(value, properties.goog_auto_gain_control);
1356 CheckGoogExperimentalEchoCancellationDefault(properties, value);
1357 EXPECT_EQ(value, properties.goog_noise_suppression);
1358 EXPECT_EQ(value, properties.goog_experimental_noise_suppression);
1359 EXPECT_EQ(value, properties.goog_highpass_filter);
1360 EXPECT_EQ(value, properties.goog_experimental_auto_gain_control);
1361
1362 // The following are not audio processing.
1363 EXPECT_FALSE(properties.goog_audio_mirroring);
1364 EXPECT_EQ(GetMediaStreamSource() != blink::kMediaStreamSourceDesktop,
1365 result.disable_local_echo());
1366 EXPECT_FALSE(result.render_to_associated_sink());
1367 CheckProcessingType(result);
1368 CheckDevice(*system_echo_canceller_device_, result);
1369 }
1370 }
1371 }
1372 }
1373
1374 // Tests the googEchoCancellation constraint with a device without system echo
1375 // cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest,GoogEchoCancellationWithWebRtc)1376 TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithWebRtc) {
1377 for (auto set_function : kBoolSetFunctions) {
1378 for (auto accessor : kFactoryAccessors) {
1379 // Ideal advanced is ignored by the SelectSettings algorithm.
1380 // Using array elements instead of pointers due to the comparison failing
1381 // on compilers.
1382 if (set_function == kBoolSetFunctions[1] &&
1383 accessor == kFactoryAccessors[1]) {
1384 continue;
1385 }
1386 for (bool value : kBoolValues) {
1387 ResetFactory();
1388 ((constraint_factory_.*accessor)().goog_echo_cancellation.*
1389 set_function)(value);
1390 auto result = SelectSettings();
1391 EXPECT_TRUE(result.HasValue());
1392 const AudioProcessingProperties& properties =
1393 result.audio_processing_properties();
1394 // The goog_echo_cancellation constraint controls only the
1395 // echo_cancellation properties. The other audio processing properties
1396 // use the default values.
1397 const EchoCancellationType expected_echo_cancellation_type =
1398 value ? EchoCancellationType::kEchoCancellationAec3
1399 : EchoCancellationType::kEchoCancellationDisabled;
1400 EXPECT_EQ(expected_echo_cancellation_type,
1401 properties.echo_cancellation_type);
1402 CheckProcessingType(result);
1403 CheckBoolDefaults(AudioSettingsBoolMembers(),
1404 AudioPropertiesBoolMembers(), result);
1405 if (IsDeviceCapture()) {
1406 CheckDevice(*default_device_, result);
1407 } else {
1408 EXPECT_TRUE(result.device_id().empty());
1409 }
1410 }
1411 }
1412 }
1413 }
1414
1415 // Tests the googEchoCancellation constraint with a device with system echo
1416 // cancellation.
TEST_P(MediaStreamConstraintsUtilAudioTest,GoogEchoCancellationWithSystem)1417 TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSystem) {
1418 // With content capture, there is no system echo cancellation, so
1419 // nothing to test.
1420 if (!IsDeviceCapture())
1421 return;
1422
1423 for (auto set_function : kBoolSetFunctions) {
1424 for (auto accessor : kFactoryAccessors) {
1425 // Ideal advanced is ignored by the SelectSettings algorithm.
1426 // Using array elements instead of pointer values due to the comparison
1427 // failing on some build configurations.
1428 if (set_function == kBoolSetFunctions[1] &&
1429 accessor == kFactoryAccessors[1]) {
1430 continue;
1431 }
1432 for (bool value : kBoolValues) {
1433 ResetFactory();
1434 constraint_factory_.basic().device_id.SetExact(
1435 system_echo_canceller_device_->DeviceID());
1436 ((constraint_factory_.*accessor)().goog_echo_cancellation.*
1437 set_function)(value);
1438 auto result = SelectSettings();
1439 EXPECT_TRUE(result.HasValue());
1440 const AudioProcessingProperties& properties =
1441 result.audio_processing_properties();
1442 // With system echo cancellation, WebRTC echo cancellation is always
1443 // disabled, and system echo cancellation is disabled if
1444 // goog_echo_cancellation is false.
1445 const EchoCancellationType expected_echo_cancellation_type =
1446 value ? EchoCancellationType::kEchoCancellationSystem
1447 : EchoCancellationType::kEchoCancellationDisabled;
1448 EXPECT_EQ(expected_echo_cancellation_type,
1449 properties.echo_cancellation_type);
1450 CheckProcessingType(result);
1451 CheckBoolDefaults(AudioSettingsBoolMembers(),
1452 AudioPropertiesBoolMembers(), result);
1453 CheckDevice(*system_echo_canceller_device_, result);
1454 }
1455 }
1456 }
1457 }
1458
1459 // Test that having differing mandatory values for echoCancellation and
1460 // googEchoCancellation fails.
TEST_P(MediaStreamConstraintsUtilAudioTest,ContradictoryEchoCancellation)1461 TEST_P(MediaStreamConstraintsUtilAudioTest, ContradictoryEchoCancellation) {
1462 for (bool value : kBoolValues) {
1463 constraint_factory_.basic().echo_cancellation.SetExact(value);
1464 constraint_factory_.basic().goog_echo_cancellation.SetExact(!value);
1465 auto result = SelectSettings();
1466 EXPECT_FALSE(result.HasValue());
1467 EXPECT_EQ(result.failed_constraint_name(),
1468 constraint_factory_.basic().echo_cancellation.GetName());
1469 }
1470 }
1471
1472 // Test that having differing mandatory values for googAutoGainControl and
1473 // googAutoGainControl2 fails. This test is valid to correctly support the
1474 // old syntax.
TEST_P(MediaStreamConstraintsUtilAudioTest,ContradictoryAutoGainControl)1475 TEST_P(MediaStreamConstraintsUtilAudioTest, ContradictoryAutoGainControl) {
1476 // TODO(armax): fix this.
1477 for (bool value : kBoolValues) {
1478 constraint_factory_.basic().goog_auto_gain_control.SetExact(value);
1479 constraint_factory_.basic().goog_experimental_auto_gain_control.SetExact(
1480 !value);
1481 auto result = SelectSettings();
1482 EXPECT_FALSE(result.HasValue());
1483 EXPECT_EQ(result.failed_constraint_name(),
1484 constraint_factory_.basic()
1485 .goog_experimental_auto_gain_control.GetName());
1486 }
1487 }
1488
1489 // Tests that individual boolean audio-processing constraints override the
1490 // default value set by the echoCancellation constraint.
TEST_P(MediaStreamConstraintsUtilAudioTest,EchoCancellationAndSingleBoolConstraint)1491 TEST_P(MediaStreamConstraintsUtilAudioTest,
1492 EchoCancellationAndSingleBoolConstraint) {
1493 const std::vector<blink::BooleanConstraint MediaTrackConstraintSetPlatform::*>
1494 kAudioProcessingConstraints = {
1495 &MediaTrackConstraintSetPlatform::goog_audio_mirroring,
1496 &MediaTrackConstraintSetPlatform::goog_auto_gain_control,
1497 &MediaTrackConstraintSetPlatform::goog_experimental_echo_cancellation,
1498 &MediaTrackConstraintSetPlatform::goog_noise_suppression,
1499 &MediaTrackConstraintSetPlatform::goog_experimental_noise_suppression,
1500 &MediaTrackConstraintSetPlatform::goog_highpass_filter,
1501 &MediaTrackConstraintSetPlatform::goog_experimental_auto_gain_control,
1502 };
1503
1504 ASSERT_EQ(kAudioProcessingProperties.size(),
1505 kAudioProcessingConstraints.size());
1506 for (auto set_function : kBoolSetFunctions) {
1507 for (auto accessor : kFactoryAccessors) {
1508 // Ideal advanced is ignored by the SelectSettings algorithm.
1509 // Using array elements instead of pointer values due to the comparison
1510 // failing on some build configurations.
1511 if (set_function == kBoolSetFunctions[1] &&
1512 accessor == kFactoryAccessors[1]) {
1513 continue;
1514 }
1515 for (size_t i = 0; i < kAudioProcessingProperties.size(); ++i) {
1516 ResetFactory();
1517 ((constraint_factory_.*accessor)().echo_cancellation.*
1518 set_function)(false);
1519 (((constraint_factory_.*accessor)().*kAudioProcessingConstraints[i]).*
1520 set_function)(true);
1521 auto result = SelectSettings();
1522 EXPECT_TRUE(result.HasValue());
1523 CheckProcessingType(result);
1524 EXPECT_EQ(EchoCancellationType::kEchoCancellationDisabled,
1525 result.audio_processing_properties().echo_cancellation_type);
1526 EXPECT_TRUE(result.audio_processing_properties().*
1527 kAudioProcessingProperties[i]);
1528 for (size_t j = 0; j < kAudioProcessingProperties.size(); ++j) {
1529 if (i == j)
1530 continue;
1531 // goog_auto_gain_control and goog_experimental_auto_gain_control
1532 // should always match in value.
1533 if ((i == 1 && j == 6) || (i == 6 && j == 1)) {
1534 EXPECT_EQ(result.audio_processing_properties().*
1535 kAudioProcessingProperties[i],
1536 result.audio_processing_properties().*
1537 kAudioProcessingProperties[j]);
1538 continue;
1539 }
1540 EXPECT_FALSE(result.audio_processing_properties().*
1541 kAudioProcessingProperties[j]);
1542 }
1543 }
1544 }
1545 }
1546 }
1547
TEST_P(MediaStreamConstraintsUtilAudioTest,ReconfigurationSystemEchoCancellation)1548 TEST_P(MediaStreamConstraintsUtilAudioTest,
1549 ReconfigurationSystemEchoCancellation) {
1550 // This test is relevant only for device capture, where HW EC can be found.
1551 if (!IsDeviceCapture())
1552 return;
1553
1554 // Create a capability that is based on a already opened source with system
1555 // echo cancellation enabled.
1556 AudioProcessingProperties properties;
1557 properties.echo_cancellation_type =
1558 EchoCancellationType::kEchoCancellationSystem;
1559 std::unique_ptr<ProcessedLocalAudioSource> system_echo_canceller_source =
1560 GetProcessedLocalAudioSource(
1561 properties, false /* disable_local_echo */,
1562 false /* render_to_associated_sink */,
1563 media::AudioParameters::PlatformEffectsMask::ECHO_CANCELLER);
1564 AudioDeviceCaptureCapabilities capabilities = {
1565 AudioDeviceCaptureCapability(system_echo_canceller_source.get())};
1566 AudioDeviceCaptureCapability* system_echo_canceller_with_source =
1567 &capabilities[0];
1568
1569 constraint_factory_.Reset();
1570 constraint_factory_.basic().device_id.SetExact(
1571 system_echo_canceller_with_source->DeviceID());
1572 constraint_factory_.basic().echo_cancellation.SetExact(true);
1573 auto result = SelectSettings(true, capabilities);
1574 EXPECT_TRUE(result.HasValue());
1575
1576 constraint_factory_.Reset();
1577 constraint_factory_.basic().device_id.SetExact(
1578 system_echo_canceller_with_source->DeviceID());
1579 constraint_factory_.basic().echo_cancellation.SetExact(false);
1580 result = SelectSettings(true, capabilities);
1581 EXPECT_FALSE(result.HasValue());
1582 }
1583
1584 // Test advanced constraints sets that can be satisfied.
TEST_P(MediaStreamConstraintsUtilAudioTest,AdvancedCompatibleConstraints)1585 TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedCompatibleConstraints) {
1586 constraint_factory_.AddAdvanced().render_to_associated_sink.SetExact(true);
1587 constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
1588 auto result = SelectSettings();
1589 EXPECT_TRUE(result.HasValue());
1590 CheckDeviceDefaults(result);
1591 CheckProcessingType(result);
1592 CheckBoolDefaults({&AudioCaptureSettings::render_to_associated_sink},
1593 {&AudioProcessingProperties::goog_audio_mirroring}, result);
1594 CheckEchoCancellationTypeDefault(result);
1595 EXPECT_TRUE(result.render_to_associated_sink());
1596 EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
1597 }
1598
1599 // Test that an advanced constraint set that contradicts a previous constraint
1600 // set is ignored, but that further constraint sets that can be satisfied are
1601 // applied.
TEST_P(MediaStreamConstraintsUtilAudioTest,AdvancedConflictingMiddleConstraints)1602 TEST_P(MediaStreamConstraintsUtilAudioTest,
1603 AdvancedConflictingMiddleConstraints) {
1604 constraint_factory_.AddAdvanced().goog_highpass_filter.SetExact(true);
1605 auto& advanced2 = constraint_factory_.AddAdvanced();
1606 advanced2.goog_highpass_filter.SetExact(false);
1607 constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
1608 auto result = SelectSettings();
1609 EXPECT_TRUE(result.HasValue());
1610 CheckProcessingType(result);
1611 CheckDeviceDefaults(result);
1612 CheckBoolDefaults({},
1613 {&AudioProcessingProperties::goog_audio_mirroring,
1614 &AudioProcessingProperties::goog_highpass_filter},
1615 result);
1616 CheckEchoCancellationTypeDefault(result);
1617 EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
1618 EXPECT_TRUE(result.audio_processing_properties().goog_highpass_filter);
1619 }
1620
1621 // Test that an advanced constraint set that contradicts a previous constraint
1622 // set with a boolean constraint is ignored.
TEST_P(MediaStreamConstraintsUtilAudioTest,AdvancedConflictingLastConstraint)1623 TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedConflictingLastConstraint) {
1624 constraint_factory_.AddAdvanced().goog_highpass_filter.SetExact(true);
1625 constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
1626 auto result = SelectSettings();
1627 EXPECT_TRUE(result.HasValue());
1628 CheckProcessingType(result);
1629 CheckDeviceDefaults(result);
1630 CheckBoolDefaults({},
1631 {&AudioProcessingProperties::goog_audio_mirroring,
1632 &AudioProcessingProperties::goog_highpass_filter},
1633 result);
1634 CheckEchoCancellationTypeDefault(result);
1635 // The fourth advanced set is ignored because it contradicts the second set.
1636 EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
1637 EXPECT_TRUE(result.audio_processing_properties().goog_highpass_filter);
1638 }
1639
1640 // NoDevices tests verify that the case with no devices is handled correctly.
TEST_P(MediaStreamConstraintsUtilAudioTest,NoDevicesNoConstraints)1641 TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesNoConstraints) {
1642 // This test makes sense only for device capture.
1643 if (!IsDeviceCapture())
1644 return;
1645
1646 AudioDeviceCaptureCapabilities capabilities;
1647 auto result = SelectSettingsAudioCapture(
1648 capabilities, constraint_factory_.CreateMediaConstraints(), false);
1649 EXPECT_FALSE(result.HasValue());
1650 EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
1651 }
1652
TEST_P(MediaStreamConstraintsUtilAudioTest,NoDevicesWithConstraints)1653 TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesWithConstraints) {
1654 // This test makes sense only for device capture.
1655 if (!IsDeviceCapture())
1656 return;
1657
1658 AudioDeviceCaptureCapabilities capabilities;
1659 constraint_factory_.basic().sample_size.SetExact(16);
1660 auto result = SelectSettingsAudioCapture(
1661 capabilities, constraint_factory_.CreateMediaConstraints(), false);
1662 EXPECT_FALSE(result.HasValue());
1663 EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
1664 }
1665
1666 // Test functionality to support applyConstraints() for tracks attached to
1667 // sources that have no audio processing.
TEST_P(MediaStreamConstraintsUtilAudioTest,SourceWithNoAudioProcessing)1668 TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithNoAudioProcessing) {
1669 for (bool enable_properties : {true, false}) {
1670 std::unique_ptr<blink::LocalMediaStreamAudioSource> source =
1671 GetLocalMediaStreamAudioSource(
1672 enable_properties /* enable_system_echo_canceller */,
1673 enable_properties /* disable_local_echo */,
1674 enable_properties /* render_to_associated_sink */);
1675
1676 // These constraints are false in |source|.
1677 const std::vector<
1678 blink::BooleanConstraint MediaTrackConstraintSetPlatform::*>
1679 kConstraints = {
1680 &MediaTrackConstraintSetPlatform::echo_cancellation,
1681 &MediaTrackConstraintSetPlatform::disable_local_echo,
1682 &MediaTrackConstraintSetPlatform::render_to_associated_sink,
1683 };
1684
1685 for (size_t i = 0; i < kConstraints.size(); ++i) {
1686 constraint_factory_.Reset();
1687 (constraint_factory_.basic().*kConstraints[i])
1688 .SetExact(enable_properties);
1689 auto result = SelectSettingsAudioCapture(
1690 source.get(), constraint_factory_.CreateMediaConstraints());
1691 EXPECT_TRUE(result.HasValue());
1692
1693 constraint_factory_.Reset();
1694 (constraint_factory_.basic().*kConstraints[i])
1695 .SetExact(!enable_properties);
1696 result = SelectSettingsAudioCapture(
1697 source.get(), constraint_factory_.CreateMediaConstraints());
1698 EXPECT_FALSE(result.HasValue());
1699
1700 // Setting just ideal values should always succeed.
1701 constraint_factory_.Reset();
1702 (constraint_factory_.basic().*kConstraints[i]).SetIdeal(true);
1703 result = SelectSettingsAudioCapture(
1704 source.get(), constraint_factory_.CreateMediaConstraints());
1705 EXPECT_TRUE(result.HasValue());
1706
1707 constraint_factory_.Reset();
1708 (constraint_factory_.basic().*kConstraints[i]).SetIdeal(false);
1709 result = SelectSettingsAudioCapture(
1710 source.get(), constraint_factory_.CreateMediaConstraints());
1711 EXPECT_TRUE(result.HasValue());
1712 }
1713 }
1714 }
1715
1716 // Test functionality to support applyConstraints() for tracks attached to
1717 // sources that have audio processing.
TEST_P(MediaStreamConstraintsUtilAudioTest,SourceWithAudioProcessing)1718 TEST_P(MediaStreamConstraintsUtilAudioTest, SourceWithAudioProcessing) {
1719 // Processed audio sources are supported only for device capture.
1720 if (!IsDeviceCapture())
1721 return;
1722
1723 for (bool use_defaults : {true, false}) {
1724 AudioProcessingProperties properties;
1725 if (!use_defaults) {
1726 properties.echo_cancellation_type =
1727 EchoCancellationType::kEchoCancellationDisabled;
1728 properties.goog_audio_mirroring = !properties.goog_audio_mirroring;
1729 properties.goog_auto_gain_control = !properties.goog_auto_gain_control;
1730 properties.goog_experimental_echo_cancellation =
1731 !properties.goog_experimental_echo_cancellation;
1732 properties.goog_noise_suppression = !properties.goog_noise_suppression;
1733 properties.goog_experimental_noise_suppression =
1734 !properties.goog_experimental_noise_suppression;
1735 properties.goog_highpass_filter = !properties.goog_highpass_filter;
1736 properties.goog_experimental_auto_gain_control =
1737 !properties.goog_experimental_auto_gain_control;
1738 }
1739
1740 std::unique_ptr<ProcessedLocalAudioSource> source =
1741 GetProcessedLocalAudioSource(
1742 properties, use_defaults /* disable_local_echo */,
1743 use_defaults /* render_to_associated_sink */);
1744 const std::vector<
1745 blink::BooleanConstraint MediaTrackConstraintSetPlatform::*>
1746 kAudioProcessingConstraints = {
1747 &MediaTrackConstraintSetPlatform::goog_audio_mirroring,
1748 &MediaTrackConstraintSetPlatform::goog_auto_gain_control,
1749 &MediaTrackConstraintSetPlatform::
1750 goog_experimental_echo_cancellation,
1751 &MediaTrackConstraintSetPlatform::goog_noise_suppression,
1752 &MediaTrackConstraintSetPlatform::
1753 goog_experimental_noise_suppression,
1754 &MediaTrackConstraintSetPlatform::goog_highpass_filter,
1755 &MediaTrackConstraintSetPlatform::
1756 goog_experimental_auto_gain_control,
1757 };
1758 ASSERT_EQ(kAudioProcessingConstraints.size(),
1759 kAudioProcessingProperties.size());
1760
1761 for (size_t i = 0; i < kAudioProcessingConstraints.size(); ++i) {
1762 constraint_factory_.Reset();
1763 (constraint_factory_.basic().*kAudioProcessingConstraints[i])
1764 .SetExact(properties.*kAudioProcessingProperties[i]);
1765 auto result = SelectSettingsAudioCapture(
1766 source.get(), constraint_factory_.CreateMediaConstraints());
1767 EXPECT_TRUE(result.HasValue());
1768
1769 constraint_factory_.Reset();
1770 (constraint_factory_.basic().*kAudioProcessingConstraints[i])
1771 .SetExact(!(properties.*kAudioProcessingProperties[i]));
1772 result = SelectSettingsAudioCapture(
1773 source.get(), constraint_factory_.CreateMediaConstraints());
1774 EXPECT_FALSE(result.HasValue());
1775
1776 // Setting just ideal values should always succeed.
1777 constraint_factory_.Reset();
1778 (constraint_factory_.basic().*kAudioProcessingConstraints[i])
1779 .SetIdeal(true);
1780 result = SelectSettingsAudioCapture(
1781 source.get(), constraint_factory_.CreateMediaConstraints());
1782 EXPECT_TRUE(result.HasValue());
1783
1784 constraint_factory_.Reset();
1785 (constraint_factory_.basic().*kAudioProcessingConstraints[i])
1786 .SetIdeal(false);
1787 result = SelectSettingsAudioCapture(
1788 source.get(), constraint_factory_.CreateMediaConstraints());
1789 EXPECT_TRUE(result.HasValue());
1790 }
1791
1792 // Test same as above but for echo cancellation.
1793 constraint_factory_.Reset();
1794 constraint_factory_.basic().echo_cancellation.SetExact(
1795 properties.echo_cancellation_type ==
1796 EchoCancellationType::kEchoCancellationAec3);
1797 auto result = SelectSettingsAudioCapture(
1798 source.get(), constraint_factory_.CreateMediaConstraints());
1799 EXPECT_TRUE(result.HasValue());
1800
1801 constraint_factory_.Reset();
1802 constraint_factory_.basic().echo_cancellation.SetExact(
1803 properties.echo_cancellation_type !=
1804 EchoCancellationType::kEchoCancellationAec3);
1805 result = SelectSettingsAudioCapture(
1806 source.get(), constraint_factory_.CreateMediaConstraints());
1807 EXPECT_FALSE(result.HasValue());
1808
1809 constraint_factory_.Reset();
1810 constraint_factory_.basic().echo_cancellation.SetIdeal(true);
1811 result = SelectSettingsAudioCapture(
1812 source.get(), constraint_factory_.CreateMediaConstraints());
1813 EXPECT_TRUE(result.HasValue());
1814
1815 constraint_factory_.Reset();
1816 constraint_factory_.basic().echo_cancellation.SetIdeal(false);
1817 result = SelectSettingsAudioCapture(
1818 source.get(), constraint_factory_.CreateMediaConstraints());
1819 EXPECT_TRUE(result.HasValue());
1820
1821 // These constraints are false in |source|.
1822 const std::vector<
1823 blink::BooleanConstraint MediaTrackConstraintSetPlatform::*>
1824 kAudioBrowserConstraints = {
1825 &MediaTrackConstraintSetPlatform::disable_local_echo,
1826 &MediaTrackConstraintSetPlatform::render_to_associated_sink,
1827 };
1828 for (size_t i = 0; i < kAudioBrowserConstraints.size(); ++i) {
1829 constraint_factory_.Reset();
1830 (constraint_factory_.basic().*kAudioBrowserConstraints[i])
1831 .SetExact(use_defaults);
1832 auto result = SelectSettingsAudioCapture(
1833 source.get(), constraint_factory_.CreateMediaConstraints());
1834 EXPECT_TRUE(result.HasValue());
1835
1836 constraint_factory_.Reset();
1837 (constraint_factory_.basic().*kAudioBrowserConstraints[i])
1838 .SetExact(!use_defaults);
1839 result = SelectSettingsAudioCapture(
1840 source.get(), constraint_factory_.CreateMediaConstraints());
1841 EXPECT_FALSE(result.HasValue());
1842
1843 constraint_factory_.Reset();
1844 (constraint_factory_.basic().*kAudioBrowserConstraints[i]).SetIdeal(true);
1845 result = SelectSettingsAudioCapture(
1846 source.get(), constraint_factory_.CreateMediaConstraints());
1847 EXPECT_TRUE(result.HasValue());
1848
1849 constraint_factory_.Reset();
1850 (constraint_factory_.basic().*kAudioBrowserConstraints[i])
1851 .SetIdeal(false);
1852 result = SelectSettingsAudioCapture(
1853 source.get(), constraint_factory_.CreateMediaConstraints());
1854 EXPECT_TRUE(result.HasValue());
1855 }
1856
1857 // Test same as above for echo cancellation.
1858 constraint_factory_.Reset();
1859 constraint_factory_.basic().echo_cancellation.SetExact(use_defaults);
1860 result = SelectSettingsAudioCapture(
1861 source.get(), constraint_factory_.CreateMediaConstraints());
1862 EXPECT_TRUE(result.HasValue());
1863
1864 constraint_factory_.Reset();
1865 constraint_factory_.basic().echo_cancellation.SetExact(!use_defaults);
1866 result = SelectSettingsAudioCapture(
1867 source.get(), constraint_factory_.CreateMediaConstraints());
1868 EXPECT_FALSE(result.HasValue());
1869
1870 constraint_factory_.Reset();
1871 constraint_factory_.basic().echo_cancellation.SetIdeal(true);
1872 result = SelectSettingsAudioCapture(
1873 source.get(), constraint_factory_.CreateMediaConstraints());
1874 EXPECT_TRUE(result.HasValue());
1875
1876 constraint_factory_.Reset();
1877 constraint_factory_.basic().echo_cancellation.SetIdeal(false);
1878 result = SelectSettingsAudioCapture(
1879 source.get(), constraint_factory_.CreateMediaConstraints());
1880 EXPECT_TRUE(result.HasValue());
1881 }
1882 }
1883
TEST_P(MediaStreamConstraintsUtilAudioTest,UsedAndUnusedSources)1884 TEST_P(MediaStreamConstraintsUtilAudioTest, UsedAndUnusedSources) {
1885 // The distinction of used and unused sources is relevant only for device
1886 // capture.
1887 if (!IsDeviceCapture())
1888 return;
1889
1890 AudioProcessingProperties properties;
1891 std::unique_ptr<ProcessedLocalAudioSource> processed_source =
1892 GetProcessedLocalAudioSource(properties, false /* disable_local_echo */,
1893 false /* render_to_associated_sink */);
1894
1895 const String kUnusedDeviceID = "unused_device";
1896 const String kGroupID = "fake_group";
1897 AudioDeviceCaptureCapabilities capabilities;
1898 capabilities.emplace_back(processed_source.get());
1899 capabilities.emplace_back(kUnusedDeviceID, kGroupID,
1900 media::AudioParameters::UnavailableDeviceParams());
1901
1902 {
1903 constraint_factory_.Reset();
1904 constraint_factory_.basic().echo_cancellation.SetExact(false);
1905
1906 auto result = SelectSettingsAudioCapture(
1907 capabilities, constraint_factory_.CreateMediaConstraints(),
1908 false /* should_disable_hardware_noise_suppression */);
1909 EXPECT_TRUE(result.HasValue());
1910 EXPECT_EQ(result.device_id(), kUnusedDeviceID.Utf8());
1911 EXPECT_EQ(result.audio_processing_properties().echo_cancellation_type,
1912 EchoCancellationType::kEchoCancellationDisabled);
1913 }
1914
1915 {
1916 constraint_factory_.Reset();
1917 constraint_factory_.basic().echo_cancellation.SetExact(true);
1918 auto result = SelectSettingsAudioCapture(
1919 capabilities, constraint_factory_.CreateMediaConstraints(),
1920 false /* should_disable_hardware_noise_suppression */);
1921 EXPECT_TRUE(result.HasValue());
1922 EXPECT_EQ(result.device_id(), processed_source->device().id);
1923 EXPECT_EQ(result.audio_processing_properties().echo_cancellation_type,
1924 EchoCancellationType::kEchoCancellationAec3);
1925 }
1926 }
1927
TEST_P(MediaStreamConstraintsUtilAudioTest,ExperimetanlEcWithSource)1928 TEST_P(MediaStreamConstraintsUtilAudioTest, ExperimetanlEcWithSource) {
1929 std::unique_ptr<blink::LocalMediaStreamAudioSource> source =
1930 GetLocalMediaStreamAudioSource(
1931 false /* enable_system_echo_canceller */,
1932 false /* disable_local_echo */, false /* render_to_associated_sink */,
1933 true /* enable_experimental_echo_canceller */);
1934
1935 constraint_factory_.Reset();
1936 constraint_factory_.basic().echo_cancellation.SetExact(false);
1937
1938 auto result = SelectSettingsAudioCapture(
1939 source.get(), constraint_factory_.CreateMediaConstraints());
1940 EXPECT_TRUE(result.HasValue());
1941 }
1942
TEST_P(MediaStreamConstraintsRemoteAPMTest,Channels)1943 TEST_P(MediaStreamConstraintsRemoteAPMTest, Channels) {
1944 if (!IsDeviceCapture())
1945 return;
1946
1947 AudioCaptureSettings result;
1948 ResetFactory();
1949 constraint_factory_.basic().channel_count.SetExact(1);
1950 constraint_factory_.basic().echo_cancellation.SetExact(true);
1951 result = SelectSettings();
1952
1953 if (media::IsWebRtcApmInAudioServiceEnabled() && GetParam())
1954 EXPECT_FALSE(result.HasValue());
1955 else
1956 EXPECT_TRUE(result.HasValue());
1957 }
1958
TEST_P(MediaStreamConstraintsRemoteAPMTest,SampleRate)1959 TEST_P(MediaStreamConstraintsRemoteAPMTest, SampleRate) {
1960 if (!IsDeviceCapture())
1961 return;
1962
1963 AudioCaptureSettings result;
1964 ResetFactory();
1965 constraint_factory_.basic().sample_rate.SetExact(
1966 media::AudioParameters::kAudioCDSampleRate);
1967 constraint_factory_.basic().echo_cancellation.SetExact(true);
1968 result = SelectSettings();
1969
1970 if (media::IsWebRtcApmInAudioServiceEnabled() && GetParam())
1971 EXPECT_TRUE(result.HasValue());
1972 else
1973 EXPECT_FALSE(result.HasValue());
1974 }
1975
TEST_P(MediaStreamConstraintsUtilAudioTest,LatencyConstraint)1976 TEST_P(MediaStreamConstraintsUtilAudioTest, LatencyConstraint) {
1977 if (!IsDeviceCapture())
1978 return;
1979
1980 // The minimum is 10ms because the AudioParameters used in
1981 // GetLocalMediaStreamAudioSource() device.input come from the default
1982 // constructor to blink::MediaStreamDevice, which sets them to
1983 // AudioParameters::UnavailableDeviceParams(), which uses a 10ms buffer size.
1984 double default_device_min =
1985 10 / static_cast<double>(base::Time::kMillisecondsPerSecond);
1986 double default_device_max =
1987 1000 / static_cast<double>(media::AudioParameters::kAudioCDSampleRate);
1988
1989 CheckLatencyConstraint(default_device_, default_device_min,
1990 default_device_max);
1991 CheckLocalMediaStreamAudioSourceLatency(
1992 default_device_, 0.003,
1993 default_device_min * media::AudioParameters::kAudioCDSampleRate);
1994 CheckLocalMediaStreamAudioSourceLatency(
1995 default_device_, 0.015,
1996 default_device_min * media::AudioParameters::kAudioCDSampleRate);
1997 CheckLocalMediaStreamAudioSourceLatency(default_device_, 0.022, 1000);
1998 CheckLocalMediaStreamAudioSourceLatency(default_device_, 0.04, 1000);
1999
2000 double variable_latency_device_min =
2001 128 / static_cast<double>(media::AudioParameters::kAudioCDSampleRate);
2002 double variable_latency_device_max =
2003 4096 / static_cast<double>(media::AudioParameters::kAudioCDSampleRate);
2004
2005 CheckLatencyConstraint(variable_latency_device_, variable_latency_device_min,
2006 variable_latency_device_max);
2007
2008 // Values here are the closest match to the requested latency as returned by
2009 // media::AudioLatency::GetExactBufferSize().
2010 CheckLocalMediaStreamAudioSourceLatency(variable_latency_device_, 0.001, 128);
2011 CheckLocalMediaStreamAudioSourceLatency(variable_latency_device_, 0.011, 512);
2012 #if defined(OS_WIN)
2013 // Windows only uses exactly the minimum or else multiples of the
2014 // hardware_buffer_size (512 for the variable_latency_device_).
2015 CheckLocalMediaStreamAudioSourceLatency(variable_latency_device_, 0.020,
2016 1024);
2017 #else
2018 CheckLocalMediaStreamAudioSourceLatency(variable_latency_device_, 0.020, 896);
2019 #endif
2020 CheckLocalMediaStreamAudioSourceLatency(variable_latency_device_, 0.2, 4096);
2021 }
2022
2023 INSTANTIATE_TEST_SUITE_P(All,
2024 MediaStreamConstraintsUtilAudioTest,
2025 testing::Values("",
2026 blink::kMediaStreamSourceTab,
2027 blink::kMediaStreamSourceSystem,
2028 blink::kMediaStreamSourceDesktop));
2029 INSTANTIATE_TEST_SUITE_P(All,
2030 MediaStreamConstraintsRemoteAPMTest,
2031 testing::Bool());
2032
2033 } // namespace blink
2034