Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(113)

Side by Side Diff: content/renderer/media/media_stream_constraints_util_audio_unittest.cc

Issue 2941553003: Reland "SelectSettings algorithm for audio constraints." (Closed)
Patch Set: fix test Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "content/renderer/media/media_stream_constraints_util_audio.h"
6
7 #include <cmath>
8 #include <string>
9 #include <utility>
10
11 #include "content/common/media/media_devices.mojom.h"
12 #include "content/renderer/media/mock_constraint_factory.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
15 #include "third_party/WebKit/public/platform/WebString.h"
16
17 namespace content {
18
19 namespace {
20
21 using BoolSetFunction = void (blink::BooleanConstraint::*)(bool);
22 using StringSetFunction =
23 void (blink::StringConstraint::*)(const blink::WebString&);
24 using MockFactoryAccessor =
25 blink::WebMediaTrackConstraintSet& (MockConstraintFactory::*)();
26
27 const BoolSetFunction kBoolSetFunctions[] = {
28 &blink::BooleanConstraint::SetExact, &blink::BooleanConstraint::SetIdeal,
29 };
30
31 const StringSetFunction kStringSetFunctions[] = {
32 &blink::StringConstraint::SetExact, &blink::StringConstraint::SetIdeal,
33 };
34
35 const MockFactoryAccessor kFactoryAccessors[] = {
36 &MockConstraintFactory::basic, &MockConstraintFactory::AddAdvanced};
37
38 const bool kBoolValues[] = {true, false};
39
40 using AudioSettingsBoolMembers =
41 std::vector<bool (AudioCaptureSettings::*)() const>;
42 using AudioPropertiesBoolMembers =
43 std::vector<bool AudioProcessingProperties::*>;
44
45 template <typename T>
46 static bool Contains(const std::vector<T>& vector, T value) {
47 auto it = std::find(vector.begin(), vector.end(), value);
48 return it != vector.end();
49 }
50
51 } // namespace
52
53 class MediaStreamConstraintsUtilAudioTest
54 : public testing::TestWithParam<std::string> {
55 public:
56 void SetUp() override {
57 ResetFactory();
58 if (!IsDeviceCapture())
59 return;
60
61 ::mojom::AudioInputDeviceCapabilitiesPtr device =
62 ::mojom::AudioInputDeviceCapabilities::New();
63 device->device_id = "default_device";
64 device->parameters = media::AudioParameters(
65 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
66 media::CHANNEL_LAYOUT_STEREO,
67 media::AudioParameters::kAudioCDSampleRate, 16, 1000);
68 capabilities_.push_back(std::move(device));
69
70 device = ::mojom::AudioInputDeviceCapabilities::New();
71 device->device_id = "mono_phone_device";
72 device->parameters = media::AudioParameters(
73 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
74 media::CHANNEL_LAYOUT_MONO,
75 media::AudioParameters::kTelephoneSampleRate, 16, 1000);
76 capabilities_.push_back(std::move(device));
77
78 device = ::mojom::AudioInputDeviceCapabilities::New();
79 device->device_id = "hw_echo_canceller_device";
80 device->parameters = media::AudioParameters(
81 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
82 media::CHANNEL_LAYOUT_STEREO,
83 media::AudioParameters::kAudioCDSampleRate, 24, 1000);
84 device->parameters.set_effects(media::AudioParameters::ECHO_CANCELLER);
85 capabilities_.push_back(std::move(device));
86
87 device = ::mojom::AudioInputDeviceCapabilities::New();
88 device->device_id = "octagonal_device";
89 device->parameters = media::AudioParameters(
90 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
91 media::CHANNEL_LAYOUT_OCTAGONAL, 100000, 8, 1000);
92 capabilities_.push_back(std::move(device));
93
94 device = ::mojom::AudioInputDeviceCapabilities::New();
95 device->device_id = "geometry device";
96 device->parameters = media::AudioParameters(
97 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
98 media::CHANNEL_LAYOUT_STEREO,
99 media::AudioParameters::kAudioCDSampleRate, 16, 1000);
100 device->parameters.set_mic_positions(kMicPositions);
101 capabilities_.push_back(std::move(device));
102
103 default_device_ = capabilities_[0].get();
104 mono_phone_device_ = capabilities_[1].get();
105 hw_echo_canceller_device_ = capabilities_[2].get();
106 octagonal_device_ = capabilities_[3].get();
107 geometry_device_ = capabilities_[4].get();
108 }
109
110 protected:
111 void SetMediaStreamSource(const std::string& source) {}
112
113 void ResetFactory() {
114 constraint_factory_.Reset();
115 constraint_factory_.basic().media_stream_source.SetExact(
116 blink::WebString::FromASCII(GetParam()));
117 }
118
119 std::string GetMediaStreamSource() { return GetParam(); }
120 bool IsDeviceCapture() { return GetMediaStreamSource().empty(); }
121
122 AudioCaptureSettings SelectSettings() {
123 blink::WebMediaConstraints constraints =
124 constraint_factory_.CreateWebMediaConstraints();
125 return SelectSettingsAudioCapture(capabilities_, constraints);
126 }
127
128 // When googExperimentalEchoCancellation is not explicitly set, its default
129 // value is always false on Android. On other platforms it behaves like other
130 // audio-processing properties.
131 void CheckGoogExperimentalEchoCancellationDefault(
132 const AudioProcessingProperties& properties,
133 bool value) {
134 #if defined(OS_ANDROID)
135 EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
136 #else
137 EXPECT_EQ(value, properties.goog_experimental_echo_cancellation);
138 #endif
139 }
140
141 void CheckBoolDefaultsDeviceCapture(
142 const AudioSettingsBoolMembers& exclude_main_settings,
143 const AudioPropertiesBoolMembers& exclude_audio_properties,
144 const AudioCaptureSettings& result) {
145 if (!Contains(exclude_main_settings,
146 &AudioCaptureSettings::hotword_enabled)) {
147 EXPECT_FALSE(result.hotword_enabled());
148 }
149 if (!Contains(exclude_main_settings,
150 &AudioCaptureSettings::disable_local_echo)) {
151 EXPECT_TRUE(result.disable_local_echo());
152 }
153 if (!Contains(exclude_main_settings,
154 &AudioCaptureSettings::render_to_associated_sink)) {
155 EXPECT_FALSE(result.render_to_associated_sink());
156 }
157
158 const auto& properties = result.audio_processing_properties();
159 if (!Contains(exclude_audio_properties,
160 &AudioProcessingProperties::enable_sw_echo_cancellation)) {
161 EXPECT_TRUE(properties.enable_sw_echo_cancellation);
162 }
163 if (!Contains(exclude_audio_properties,
164 &AudioProcessingProperties::disable_hw_echo_cancellation)) {
165 EXPECT_FALSE(properties.disable_hw_echo_cancellation);
166 }
167 if (!Contains(exclude_audio_properties,
168 &AudioProcessingProperties::goog_audio_mirroring)) {
169 EXPECT_FALSE(properties.goog_audio_mirroring);
170 }
171 if (!Contains(exclude_audio_properties,
172 &AudioProcessingProperties::goog_auto_gain_control)) {
173 EXPECT_TRUE(properties.goog_auto_gain_control);
174 }
175 if (!Contains(
176 exclude_audio_properties,
177 &AudioProcessingProperties::goog_experimental_echo_cancellation)) {
178 CheckGoogExperimentalEchoCancellationDefault(properties, true);
179 }
180 if (!Contains(exclude_audio_properties,
181 &AudioProcessingProperties::goog_typing_noise_detection)) {
182 EXPECT_TRUE(properties.goog_typing_noise_detection);
183 }
184 if (!Contains(exclude_audio_properties,
185 &AudioProcessingProperties::goog_noise_suppression)) {
186 EXPECT_TRUE(properties.goog_noise_suppression);
187 }
188 if (!Contains(
189 exclude_audio_properties,
190 &AudioProcessingProperties::goog_experimental_noise_suppression)) {
191 EXPECT_TRUE(properties.goog_experimental_noise_suppression);
192 }
193 if (!Contains(exclude_audio_properties,
194 &AudioProcessingProperties::goog_beamforming)) {
195 EXPECT_TRUE(properties.goog_beamforming);
196 }
197 if (!Contains(exclude_audio_properties,
198 &AudioProcessingProperties::goog_highpass_filter)) {
199 EXPECT_TRUE(properties.goog_highpass_filter);
200 }
201 if (!Contains(
202 exclude_audio_properties,
203 &AudioProcessingProperties::goog_experimental_auto_gain_control)) {
204 EXPECT_TRUE(properties.goog_experimental_auto_gain_control);
205 }
206 }
207
208 void CheckBoolDefaultsContentCapture(
209 const AudioSettingsBoolMembers& exclude_main_settings,
210 const AudioPropertiesBoolMembers& exclude_audio_properties,
211 const AudioCaptureSettings& result) {
212 if (!Contains(exclude_main_settings,
213 &AudioCaptureSettings::hotword_enabled)) {
214 EXPECT_FALSE(result.hotword_enabled());
215 }
216 if (!Contains(exclude_main_settings,
217 &AudioCaptureSettings::disable_local_echo)) {
218 EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
219 result.disable_local_echo());
220 }
221 if (!Contains(exclude_main_settings,
222 &AudioCaptureSettings::render_to_associated_sink)) {
223 EXPECT_FALSE(result.render_to_associated_sink());
224 }
225
226 const auto& properties = result.audio_processing_properties();
227 if (!Contains(exclude_audio_properties,
228 &AudioProcessingProperties::enable_sw_echo_cancellation)) {
229 EXPECT_FALSE(properties.enable_sw_echo_cancellation);
230 }
231 if (!Contains(exclude_audio_properties,
232 &AudioProcessingProperties::disable_hw_echo_cancellation)) {
233 EXPECT_FALSE(properties.disable_hw_echo_cancellation);
234 }
235 if (!Contains(exclude_audio_properties,
236 &AudioProcessingProperties::goog_audio_mirroring)) {
237 EXPECT_FALSE(properties.goog_audio_mirroring);
238 }
239 if (!Contains(exclude_audio_properties,
240 &AudioProcessingProperties::goog_auto_gain_control)) {
241 EXPECT_FALSE(properties.goog_auto_gain_control);
242 }
243 if (!Contains(
244 exclude_audio_properties,
245 &AudioProcessingProperties::goog_experimental_echo_cancellation)) {
246 EXPECT_FALSE(properties.goog_experimental_echo_cancellation);
247 }
248 if (!Contains(exclude_audio_properties,
249 &AudioProcessingProperties::goog_typing_noise_detection)) {
250 EXPECT_FALSE(properties.goog_typing_noise_detection);
251 }
252 if (!Contains(exclude_audio_properties,
253 &AudioProcessingProperties::goog_noise_suppression)) {
254 EXPECT_FALSE(properties.goog_noise_suppression);
255 }
256 if (!Contains(
257 exclude_audio_properties,
258 &AudioProcessingProperties::goog_experimental_noise_suppression)) {
259 EXPECT_FALSE(properties.goog_experimental_noise_suppression);
260 }
261 if (!Contains(exclude_audio_properties,
262 &AudioProcessingProperties::goog_beamforming)) {
263 EXPECT_FALSE(properties.goog_beamforming);
264 }
265 if (!Contains(exclude_audio_properties,
266 &AudioProcessingProperties::goog_highpass_filter)) {
267 EXPECT_FALSE(properties.goog_highpass_filter);
268 }
269 if (!Contains(
270 exclude_audio_properties,
271 &AudioProcessingProperties::goog_experimental_auto_gain_control)) {
272 EXPECT_FALSE(properties.goog_experimental_auto_gain_control);
273 }
274 }
275
276 void CheckBoolDefaults(
277 const AudioSettingsBoolMembers& exclude_main_settings,
278 const AudioPropertiesBoolMembers& exclude_audio_properties,
279 const AudioCaptureSettings& result) {
280 if (IsDeviceCapture()) {
281 CheckBoolDefaultsDeviceCapture(exclude_main_settings,
282 exclude_audio_properties, result);
283 } else {
284 CheckBoolDefaultsContentCapture(exclude_main_settings,
285 exclude_audio_properties, result);
286 }
287 }
288
289 void CheckDevice(const mojom::AudioInputDeviceCapabilities& expected_device,
290 const AudioCaptureSettings& result) {
291 EXPECT_EQ(expected_device.device_id, result.device_id());
292 EXPECT_EQ(expected_device.parameters.sample_rate(),
293 result.device_parameters().sample_rate());
294 EXPECT_EQ(expected_device.parameters.bits_per_sample(),
295 result.device_parameters().bits_per_sample());
296 EXPECT_EQ(expected_device.parameters.channels(),
297 result.device_parameters().channels());
298 EXPECT_EQ(expected_device.parameters.effects(),
299 result.device_parameters().effects());
300 }
301
302 void CheckDeviceDefaults(const AudioCaptureSettings& result) {
303 if (IsDeviceCapture())
304 CheckDevice(*default_device_, result);
305 else
306 EXPECT_TRUE(result.device_id().empty());
307 }
308
309 void CheckGeometryDefaults(const AudioCaptureSettings& result) {
310 EXPECT_TRUE(
311 result.audio_processing_properties().goog_array_geometry.empty());
312 }
313
314 void CheckAllDefaults(
315 const AudioSettingsBoolMembers& exclude_main_settings,
316 const AudioPropertiesBoolMembers& exclude_audio_properties,
317 const AudioCaptureSettings& result) {
318 CheckBoolDefaults(exclude_main_settings, exclude_audio_properties, result);
319 CheckDeviceDefaults(result);
320 CheckGeometryDefaults(result);
321 }
322
323 MockConstraintFactory constraint_factory_;
324 AudioDeviceCaptureCapabilities capabilities_;
325 const mojom::AudioInputDeviceCapabilities* default_device_ = nullptr;
326 const mojom::AudioInputDeviceCapabilities* mono_phone_device_ = nullptr;
327 const mojom::AudioInputDeviceCapabilities* hw_echo_canceller_device_ =
328 nullptr;
329 const mojom::AudioInputDeviceCapabilities* octagonal_device_ = nullptr;
330 const mojom::AudioInputDeviceCapabilities* geometry_device_ = nullptr;
331 const std::vector<media::Point> kMicPositions = {{8, 8, 8}, {4, 4, 4}};
332 };
333
334 // The Unconstrained test checks the default selection criteria.
335 TEST_P(MediaStreamConstraintsUtilAudioTest, Unconstrained) {
336 auto result = SelectSettings();
337
338 // All settings should have default values.
339 EXPECT_TRUE(result.HasValue());
340 CheckAllDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
341 result);
342 }
343
344 // This test checks all possible ways to set boolean constraints (except
345 // echo cancellation constraints, which are not mapped 1:1 to output audio
346 // processing properties).
347 TEST_P(MediaStreamConstraintsUtilAudioTest, SingleBoolConstraint) {
348 const AudioSettingsBoolMembers kMainSettings = {
349 &AudioCaptureSettings::hotword_enabled,
350 &AudioCaptureSettings::disable_local_echo,
351 &AudioCaptureSettings::render_to_associated_sink};
352
353 const std::vector<
354 blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
355 kMainBoolConstraints = {
356 &blink::WebMediaTrackConstraintSet::hotword_enabled,
357 &blink::WebMediaTrackConstraintSet::disable_local_echo,
358 &blink::WebMediaTrackConstraintSet::render_to_associated_sink};
359
360 ASSERT_EQ(kMainSettings.size(), kMainBoolConstraints.size());
361 for (auto set_function : kBoolSetFunctions) {
362 for (auto accessor : kFactoryAccessors) {
363 // Ideal advanced is ignored by the SelectSettings algorithm.
364 if (set_function == &blink::BooleanConstraint::SetIdeal &&
365 accessor == &MockConstraintFactory::AddAdvanced) {
366 continue;
367 }
368 for (size_t i = 0; i < kMainSettings.size(); ++i) {
369 for (bool value : kBoolValues) {
370 ResetFactory();
371 (((constraint_factory_.*accessor)().*kMainBoolConstraints[i]).*
372 set_function)(value);
373 auto result = SelectSettings();
374 EXPECT_TRUE(result.HasValue());
375 EXPECT_EQ(value, (result.*kMainSettings[i])());
376 CheckAllDefaults({kMainSettings[i]}, AudioPropertiesBoolMembers(),
377 result);
378 }
379 }
380 }
381 }
382
383 const AudioPropertiesBoolMembers kAudioProcessingProperties = {
384 &AudioProcessingProperties::goog_audio_mirroring,
385 &AudioProcessingProperties::goog_auto_gain_control,
386 &AudioProcessingProperties::goog_experimental_echo_cancellation,
387 &AudioProcessingProperties::goog_typing_noise_detection,
388 &AudioProcessingProperties::goog_noise_suppression,
389 &AudioProcessingProperties::goog_experimental_noise_suppression,
390 &AudioProcessingProperties::goog_beamforming,
391 &AudioProcessingProperties::goog_highpass_filter,
392 &AudioProcessingProperties::goog_experimental_auto_gain_control};
393
394 const std::vector<
395 blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
396 kAudioProcessingConstraints = {
397 &blink::WebMediaTrackConstraintSet::goog_audio_mirroring,
398 &blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
399 &blink::WebMediaTrackConstraintSet::
400 goog_experimental_echo_cancellation,
401 &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
402 &blink::WebMediaTrackConstraintSet::goog_noise_suppression,
403 &blink::WebMediaTrackConstraintSet::
404 goog_experimental_noise_suppression,
405 &blink::WebMediaTrackConstraintSet::goog_beamforming,
406 &blink::WebMediaTrackConstraintSet::goog_highpass_filter,
407 &blink::WebMediaTrackConstraintSet::
408 goog_experimental_auto_gain_control,
409 };
410
411 ASSERT_EQ(kAudioProcessingProperties.size(),
412 kAudioProcessingConstraints.size());
413 for (auto set_function : kBoolSetFunctions) {
414 for (auto accessor : kFactoryAccessors) {
415 // Ideal advanced is ignored by the SelectSettings algorithm.
416 if (set_function == &blink::BooleanConstraint::SetIdeal &&
417 accessor == &MockConstraintFactory::AddAdvanced) {
418 continue;
419 }
420 for (size_t i = 0; i < kAudioProcessingProperties.size(); ++i) {
421 for (bool value : kBoolValues) {
422 ResetFactory();
423 (((constraint_factory_.*accessor)().*kAudioProcessingConstraints[i]).*
424 set_function)(value);
425 auto result = SelectSettings();
426 EXPECT_TRUE(result.HasValue());
427 EXPECT_EQ(value, result.audio_processing_properties().*
428 kAudioProcessingProperties[i]);
429 CheckAllDefaults(AudioSettingsBoolMembers(),
430 {kAudioProcessingProperties[i]}, result);
431 }
432 }
433 }
434 }
435 }
436
437 // DeviceID tests.
438 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactArbitraryDeviceID) {
439 const std::string kArbitraryDeviceID = "arbitrary";
440 constraint_factory_.basic().device_id.SetExact(
441 blink::WebString::FromASCII(kArbitraryDeviceID));
442 auto result = SelectSettings();
443 // kArbitraryDeviceID is invalid for device capture, but it is considered
444 // valid for content capture. For content capture, validation of device
445 // capture is performed by the getUserMedia() implementation.
446 if (IsDeviceCapture()) {
447 EXPECT_FALSE(result.HasValue());
448 EXPECT_EQ(std::string(constraint_factory_.basic().device_id.GetName()),
449 std::string(result.failed_constraint_name()));
450 } else {
451 EXPECT_TRUE(result.HasValue());
452 EXPECT_EQ(kArbitraryDeviceID, result.device_id());
453 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
454 result);
455 CheckGeometryDefaults(result);
456 }
457 }
458
459 // DeviceID tests check various ways to deal with the device_id constraint.
460 TEST_P(MediaStreamConstraintsUtilAudioTest, IdealArbitraryDeviceID) {
461 const std::string kArbitraryDeviceID = "arbitrary";
462 constraint_factory_.basic().device_id.SetIdeal(
463 blink::WebString::FromASCII(kArbitraryDeviceID));
464 auto result = SelectSettings();
465 EXPECT_TRUE(result.HasValue());
466 // kArbitraryDeviceID is invalid for device capture, but it is considered
467 // valid for content capture. For content capture, validation of device
468 // capture is performed by the getUserMedia() implementation.
469 if (IsDeviceCapture())
470 CheckDeviceDefaults(result);
471 else
472 EXPECT_EQ(kArbitraryDeviceID, result.device_id());
473 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
474 result);
475 CheckGeometryDefaults(result);
476 }
477
478 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidDeviceID) {
479 for (const auto& device : capabilities_) {
480 constraint_factory_.basic().device_id.SetExact(
481 blink::WebString::FromASCII(device->device_id));
482 auto result = SelectSettings();
483 EXPECT_TRUE(result.HasValue());
484 CheckDevice(*device, result);
485 CheckBoolDefaults(AudioSettingsBoolMembers(),
486 {&AudioProcessingProperties::enable_sw_echo_cancellation},
487 result);
488 bool has_hw_echo_cancellation =
489 device->parameters.effects() & media::AudioParameters::ECHO_CANCELLER;
490 EXPECT_EQ(!has_hw_echo_cancellation,
491 result.audio_processing_properties().enable_sw_echo_cancellation);
492 if (&*device == geometry_device_) {
493 EXPECT_EQ(kMicPositions,
494 result.audio_processing_properties().goog_array_geometry);
495 } else {
496 CheckGeometryDefaults(result);
497 }
498 }
499 }
500
501 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidSampleRate) {
502 constraint_factory_.basic().sample_rate.SetExact(
503 media::AudioParameters::kTelephoneSampleRate);
504 auto result = SelectSettings();
505 EXPECT_TRUE(result.HasValue());
506 if (IsDeviceCapture()) {
507 CheckDevice(*mono_phone_device_, result);
508 } else {
509 // Content capture ignores the sample_rate constraint.
510 EXPECT_TRUE(result.device_id().empty());
511 }
512 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
513 result);
514 CheckGeometryDefaults(result);
515 }
516
517 // SampleRate, SampleSize, ChannelCount tests check that numeric device-related
518 // constraints are handled correctly.
519 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactInvalidSampleRate) {
520 constraint_factory_.basic().sample_rate.SetExact(666);
521 auto result = SelectSettings();
522 if (IsDeviceCapture()) {
523 EXPECT_FALSE(result.HasValue());
524 EXPECT_EQ(std::string(constraint_factory_.basic().sample_rate.GetName()),
525 std::string(result.failed_constraint_name()));
526 } else {
527 // Content capture ignores the sample_rate constraint.
528 EXPECT_TRUE(result.HasValue());
529 EXPECT_TRUE(result.device_id().empty());
530 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
531 result);
532 CheckGeometryDefaults(result);
533 }
534 }
535
536 TEST_P(MediaStreamConstraintsUtilAudioTest, MinValidSampleRate) {
537 constraint_factory_.basic().sample_rate.SetMin(80000);
538 auto result = SelectSettings();
539 EXPECT_TRUE(result.HasValue());
540 if (IsDeviceCapture()) {
541 // The octagonal device is the only one with a large-enough sample rate.
542 CheckDevice(*octagonal_device_, result);
543 } else {
544 // Content capture ignores the sample_rate constraint.
545 EXPECT_TRUE(result.device_id().empty());
546 }
547 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
548 result);
549 CheckGeometryDefaults(result);
550 }
551
552 TEST_P(MediaStreamConstraintsUtilAudioTest, MaxValidSampleRate) {
553 constraint_factory_.basic().sample_rate.SetMax(10000);
554 auto result = SelectSettings();
555 EXPECT_TRUE(result.HasValue());
556 if (IsDeviceCapture()) {
557 // The mono device is the only one with a small-enough sample rate.
558 CheckDevice(*mono_phone_device_, result);
559 } else {
560 // Content capture ignores the sample_rate constraint.
561 EXPECT_TRUE(result.device_id().empty());
562 }
563 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
564 result);
565 CheckGeometryDefaults(result);
566 }
567
568 TEST_P(MediaStreamConstraintsUtilAudioTest, RangeValidSampleRate) {
569 constraint_factory_.basic().sample_rate.SetMin(1000);
570 constraint_factory_.basic().sample_rate.SetMax(10000);
571 auto result = SelectSettings();
572 EXPECT_TRUE(result.HasValue());
573 if (IsDeviceCapture()) {
574 // The mono device is the only one with a sample rate in the range.
575 CheckDevice(*mono_phone_device_, result);
576 } else {
577 // Content capture ignores the sample_rate constraint.
578 EXPECT_TRUE(result.device_id().empty());
579 }
580 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
581 result);
582 CheckGeometryDefaults(result);
583 }
584
585 TEST_P(MediaStreamConstraintsUtilAudioTest, InvalidRangeSampleRate) {
586 constraint_factory_.basic().sample_rate.SetMin(9000);
587 constraint_factory_.basic().sample_rate.SetMax(10000);
588 auto result = SelectSettings();
589 if (IsDeviceCapture()) {
590 EXPECT_FALSE(result.HasValue());
591 EXPECT_EQ(std::string(constraint_factory_.basic().sample_rate.GetName()),
592 std::string(result.failed_constraint_name()));
593 } else {
594 // Content capture ignores the sample_rate constraint.
595 EXPECT_TRUE(result.HasValue());
596 EXPECT_TRUE(result.device_id().empty());
597 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
598 result);
599 CheckGeometryDefaults(result);
600 }
601 }
602
603 TEST_P(MediaStreamConstraintsUtilAudioTest, IdealSampleRate) {
604 constraint_factory_.basic().sample_rate.SetIdeal(10000);
605 auto result = SelectSettings();
606 EXPECT_TRUE(result.HasValue());
607 if (IsDeviceCapture()) {
608 // The mono device is the one a sample rate closest to ideal.
609 CheckDevice(*mono_phone_device_, result);
610 } else {
611 // Content capture ignores the sample_rate constraint.
612 EXPECT_TRUE(result.device_id().empty());
613 }
614 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
615 result);
616 CheckGeometryDefaults(result);
617 }
618
619 // Sample size tests.
620 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidSampleSize) {
621 constraint_factory_.basic().sample_size.SetExact(8);
622 auto result = SelectSettings();
623 EXPECT_TRUE(result.HasValue());
624 if (IsDeviceCapture()) {
625 CheckDevice(*octagonal_device_, result);
626 } else {
627 // Content capture ignores the sample_size constraint.
628 EXPECT_TRUE(result.device_id().empty());
629 }
630 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
631 result);
632 CheckGeometryDefaults(result);
633 }
634
635 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactInvalidSampleSize) {
636 constraint_factory_.basic().sample_size.SetExact(666);
637 auto result = SelectSettings();
638 if (IsDeviceCapture()) {
639 EXPECT_FALSE(result.HasValue());
640 EXPECT_EQ(std::string(constraint_factory_.basic().sample_size.GetName()),
641 std::string(result.failed_constraint_name()));
642 } else {
643 // Content capture ignores the sample_size constraint.
644 EXPECT_TRUE(result.HasValue());
645 EXPECT_TRUE(result.device_id().empty());
646 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
647 result);
648 CheckGeometryDefaults(result);
649 }
650 }
651
652 TEST_P(MediaStreamConstraintsUtilAudioTest, MinValidSampleSize) {
653 constraint_factory_.basic().sample_size.SetMin(20);
654 auto result = SelectSettings();
655 EXPECT_TRUE(result.HasValue());
656 if (IsDeviceCapture()) {
657 // The device with echo canceller is the only one with a sample size that
658 // is greater than the requested minimum.
659 CheckDevice(*hw_echo_canceller_device_, result);
660 CheckBoolDefaults(AudioSettingsBoolMembers(),
661 {&AudioProcessingProperties::enable_sw_echo_cancellation},
662 result);
663 } else {
664 // Content capture ignores the sample_size constraint.
665 EXPECT_TRUE(result.device_id().empty());
666 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
667 result);
668 }
669 CheckGeometryDefaults(result);
670 }
671
672 TEST_P(MediaStreamConstraintsUtilAudioTest, MaxValidSampleSize) {
673 constraint_factory_.basic().sample_size.SetMax(10);
674 auto result = SelectSettings();
675 EXPECT_TRUE(result.HasValue());
676 if (IsDeviceCapture()) {
677 // The octagonal device is the only one with a small-enough sample size.
678 CheckDevice(*octagonal_device_, result);
679 } else {
680 // Content capture ignores the sample_size constraint.
681 EXPECT_TRUE(result.device_id().empty());
682 }
683 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
684 result);
685 CheckGeometryDefaults(result);
686 }
687
688 TEST_P(MediaStreamConstraintsUtilAudioTest, RangeValidSampleSize) {
689 constraint_factory_.basic().sample_size.SetMin(3);
690 constraint_factory_.basic().sample_size.SetMax(15);
691 auto result = SelectSettings();
692 EXPECT_TRUE(result.HasValue());
693 if (IsDeviceCapture()) {
694 // The octagonal device is the only one with a sample size in the range.
695 CheckDevice(*octagonal_device_, result);
696 } else {
697 // Content capture ignores the sample_size constraint.
698 EXPECT_TRUE(result.device_id().empty());
699 }
700 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
701 result);
702 CheckGeometryDefaults(result);
703 }
704
705 TEST_P(MediaStreamConstraintsUtilAudioTest, InvalidRangeSampleSize) {
706 constraint_factory_.basic().sample_size.SetMin(10);
707 constraint_factory_.basic().sample_size.SetMax(15);
708 auto result = SelectSettings();
709 if (IsDeviceCapture()) {
710 EXPECT_FALSE(result.HasValue());
711 EXPECT_EQ(std::string(constraint_factory_.basic().sample_size.GetName()),
712 std::string(result.failed_constraint_name()));
713 } else {
714 // Content capture ignores the sample_size constraint.
715 EXPECT_TRUE(result.HasValue());
716 EXPECT_TRUE(result.device_id().empty());
717 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
718 result);
719 CheckGeometryDefaults(result);
720 }
721 }
722
723 TEST_P(MediaStreamConstraintsUtilAudioTest, IdealSampleSize) {
724 constraint_factory_.basic().sample_size.SetIdeal(10);
725 auto result = SelectSettings();
726 EXPECT_TRUE(result.HasValue());
727 if (IsDeviceCapture()) {
728 // The octagonal device is the one a sample size closest to ideal.
729 CheckDevice(*octagonal_device_, result);
730 } else {
731 // Content capture ignores the sample_size constraint.
732 EXPECT_TRUE(result.device_id().empty());
733 }
734 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
735 result);
736 CheckGeometryDefaults(result);
737 }
738
739 // ChannelCount tests.
740 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactValidChannelCount) {
741 constraint_factory_.basic().channel_count.SetExact(8);
742 auto result = SelectSettings();
743 EXPECT_TRUE(result.HasValue());
744 if (IsDeviceCapture()) {
745 CheckDevice(*octagonal_device_, result);
746 } else {
747 // Content capture ignores the channel_count constraint.
748 EXPECT_TRUE(result.device_id().empty());
749 }
750 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
751 result);
752 CheckGeometryDefaults(result);
753 }
754
755 TEST_P(MediaStreamConstraintsUtilAudioTest, ExactInvalidChannelCount) {
756 constraint_factory_.basic().channel_count.SetExact(666);
757 auto result = SelectSettings();
758 if (IsDeviceCapture()) {
759 EXPECT_FALSE(result.HasValue());
760 EXPECT_EQ(std::string(constraint_factory_.basic().channel_count.GetName()),
761 std::string(result.failed_constraint_name()));
762 } else {
763 // Content capture ignores the channel_count constraint.
764 EXPECT_TRUE(result.HasValue());
765 EXPECT_TRUE(result.device_id().empty());
766 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
767 result);
768 CheckGeometryDefaults(result);
769 }
770 }
771
772 TEST_P(MediaStreamConstraintsUtilAudioTest, MinValidChannelCount) {
773 constraint_factory_.basic().channel_count.SetMin(7);
774 auto result = SelectSettings();
775 EXPECT_TRUE(result.HasValue());
776 if (IsDeviceCapture()) {
777 // The device with echo canceller is the only one with a channel count that
778 // is greater than the requested minimum.
779 CheckDevice(*octagonal_device_, result);
780 } else {
781 // Content capture ignores the channel_count constraint.
782 EXPECT_TRUE(result.device_id().empty());
783 }
784 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
785 result);
786 CheckGeometryDefaults(result);
787 }
788
789 TEST_P(MediaStreamConstraintsUtilAudioTest, MaxValidChannelCount) {
790 constraint_factory_.basic().channel_count.SetMax(1);
791 auto result = SelectSettings();
792 EXPECT_TRUE(result.HasValue());
793 if (IsDeviceCapture()) {
794 // The octagonal device is the only one with a small-enough channel count.
795 CheckDevice(*mono_phone_device_, result);
796 } else {
797 // Content capture ignores the channel_count constraint.
798 EXPECT_TRUE(result.device_id().empty());
799 }
800 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
801 result);
802 CheckGeometryDefaults(result);
803 }
804
805 TEST_P(MediaStreamConstraintsUtilAudioTest, RangeValidChannelCount) {
806 constraint_factory_.basic().channel_count.SetMin(3);
807 constraint_factory_.basic().channel_count.SetMax(15);
808 auto result = SelectSettings();
809 EXPECT_TRUE(result.HasValue());
810 if (IsDeviceCapture()) {
811 // The octagonal device is the only one with a channel count in the range.
812 CheckDevice(*octagonal_device_, result);
813 } else {
814 // Content capture ignores the channel_count constraint.
815 EXPECT_TRUE(result.device_id().empty());
816 }
817 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
818 result);
819 CheckGeometryDefaults(result);
820 }
821
822 TEST_P(MediaStreamConstraintsUtilAudioTest, InvalidRangeChannelCount) {
823 constraint_factory_.basic().channel_count.SetMin(3);
824 constraint_factory_.basic().channel_count.SetMax(7);
825 auto result = SelectSettings();
826 if (IsDeviceCapture()) {
827 EXPECT_FALSE(result.HasValue());
828 EXPECT_EQ(std::string(constraint_factory_.basic().channel_count.GetName()),
829 std::string(result.failed_constraint_name()));
830 } else {
831 // Content capture ignores the channel_count constraint.
832 EXPECT_TRUE(result.HasValue());
833 EXPECT_TRUE(result.device_id().empty());
834 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
835 result);
836 CheckGeometryDefaults(result);
837 }
838 }
839
840 TEST_P(MediaStreamConstraintsUtilAudioTest, IdealChannelCount) {
841 constraint_factory_.basic().channel_count.SetIdeal(6);
842 auto result = SelectSettings();
843 EXPECT_TRUE(result.HasValue());
844 if (IsDeviceCapture()) {
845 // The octagonal device is the one the number of channels closest to ideal.
846 CheckDevice(*octagonal_device_, result);
847 } else {
848 // Content capture ignores the channel_count constraint.
849 EXPECT_TRUE(result.device_id().empty());
850 }
851 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
852 result);
853 CheckGeometryDefaults(result);
854 }
855
856 // Tests the echoCancellation constraint with a device without hardware echo
857 // cancellation.
858 TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithSw) {
859 for (auto set_function : kBoolSetFunctions) {
860 for (auto accessor : kFactoryAccessors) {
861 // Ideal advanced is ignored by the SelectSettings algorithm.
862 if (set_function == &blink::BooleanConstraint::SetIdeal &&
863 accessor == &MockConstraintFactory::AddAdvanced) {
864 continue;
865 }
866 for (bool value : kBoolValues) {
867 ResetFactory();
868 ((constraint_factory_.*accessor)().echo_cancellation.*
869 set_function)(value);
870 auto result = SelectSettings();
871 EXPECT_TRUE(result.HasValue());
872 const AudioProcessingProperties& properties =
873 result.audio_processing_properties();
874 // With device capture, the echo_cancellation constraint
875 // enables/disables all audio processing by default.
876 // With content capture, the echo_cancellation constraint controls
877 // only the echo_cancellation properties. The other audio processing
878 // properties default to false.
879 bool enable_sw_audio_processing = IsDeviceCapture() ? value : false;
880 EXPECT_EQ(value, properties.enable_sw_echo_cancellation);
881 EXPECT_EQ(!value, properties.disable_hw_echo_cancellation);
882 EXPECT_EQ(enable_sw_audio_processing,
883 properties.goog_auto_gain_control);
884 CheckGoogExperimentalEchoCancellationDefault(
885 properties, enable_sw_audio_processing);
886 EXPECT_EQ(enable_sw_audio_processing,
887 properties.goog_typing_noise_detection);
888 EXPECT_EQ(enable_sw_audio_processing,
889 properties.goog_noise_suppression);
890 EXPECT_EQ(enable_sw_audio_processing,
891 properties.goog_experimental_noise_suppression);
892 EXPECT_EQ(enable_sw_audio_processing, properties.goog_beamforming);
893 EXPECT_EQ(enable_sw_audio_processing, properties.goog_highpass_filter);
894 EXPECT_EQ(enable_sw_audio_processing,
895 properties.goog_experimental_auto_gain_control);
896
897 // The following are not audio processing.
898 EXPECT_FALSE(properties.goog_audio_mirroring);
899 EXPECT_FALSE(result.hotword_enabled());
900 EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
901 result.disable_local_echo());
902 EXPECT_FALSE(result.render_to_associated_sink());
903 if (IsDeviceCapture()) {
904 CheckDevice(*default_device_, result);
905 } else {
906 EXPECT_TRUE(result.device_id().empty());
907 }
908 }
909 }
910 }
911 }
912
913 // Tests the echoCancellation constraint with a device with hardware echo
914 // cancellation.
915 TEST_P(MediaStreamConstraintsUtilAudioTest, EchoCancellationWithHw) {
916 // With content capture, there is no hardware echo cancellation, so
917 // nothing to test.
918 if (!IsDeviceCapture())
919 return;
920
921 for (auto set_function : kBoolSetFunctions) {
922 for (auto accessor : kFactoryAccessors) {
923 // Ideal advanced is ignored by the SelectSettings algorithm.
924 if (set_function == &blink::BooleanConstraint::SetIdeal &&
925 accessor == &MockConstraintFactory::AddAdvanced) {
926 continue;
927 }
928 for (bool value : kBoolValues) {
929 ResetFactory();
930 constraint_factory_.basic().device_id.SetExact(
931 blink::WebString::FromASCII(hw_echo_canceller_device_->device_id));
932 ((constraint_factory_.*accessor)().echo_cancellation.*
933 set_function)(value);
934 auto result = SelectSettings();
935 EXPECT_TRUE(result.HasValue());
936 const AudioProcessingProperties& properties =
937 result.audio_processing_properties();
938 // With hardware echo cancellation, the echo_cancellation constraint
939 // enables/disables all audio processing by default, software echo
940 // cancellation is always disabled, and hardware echo cancellation is
941 // disabled if the echo_cancellation constraint is false.
942 EXPECT_FALSE(properties.enable_sw_echo_cancellation);
943 EXPECT_EQ(!value, properties.disable_hw_echo_cancellation);
944 EXPECT_EQ(value, properties.goog_auto_gain_control);
945 CheckGoogExperimentalEchoCancellationDefault(properties, value);
946 EXPECT_EQ(value, properties.goog_typing_noise_detection);
947 EXPECT_EQ(value, properties.goog_noise_suppression);
948 EXPECT_EQ(value, properties.goog_experimental_noise_suppression);
949 EXPECT_EQ(value, properties.goog_beamforming);
950 EXPECT_EQ(value, properties.goog_highpass_filter);
951 EXPECT_EQ(value, properties.goog_experimental_auto_gain_control);
952
953 // The following are not audio processing.
954 EXPECT_FALSE(properties.goog_audio_mirroring);
955 EXPECT_FALSE(result.hotword_enabled());
956 EXPECT_EQ(GetMediaStreamSource() != kMediaStreamSourceDesktop,
957 result.disable_local_echo());
958 EXPECT_FALSE(result.render_to_associated_sink());
959 CheckDevice(*hw_echo_canceller_device_, result);
960 }
961 }
962 }
963 }
964
965 // Tests the googEchoCancellation constraint with a device without hardware echo
966 // cancellation.
967 TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithSw) {
968 for (auto set_function : kBoolSetFunctions) {
969 for (auto accessor : kFactoryAccessors) {
970 // Ideal advanced is ignored by the SelectSettings algorithm.
971 if (set_function == &blink::BooleanConstraint::SetIdeal &&
972 accessor == &MockConstraintFactory::AddAdvanced) {
973 continue;
974 }
975 for (bool value : kBoolValues) {
976 ResetFactory();
977 ((constraint_factory_.*accessor)().goog_echo_cancellation.*
978 set_function)(value);
979 auto result = SelectSettings();
980 EXPECT_TRUE(result.HasValue());
981 const AudioProcessingProperties& properties =
982 result.audio_processing_properties();
983 // The goog_echo_cancellation constraint controls only the
984 // echo_cancellation properties. The other audio processing properties
985 // use the default values.
986 EXPECT_EQ(value, properties.enable_sw_echo_cancellation);
987 EXPECT_EQ(!value, properties.disable_hw_echo_cancellation);
988 CheckBoolDefaults(
989 AudioSettingsBoolMembers(),
990 {
991 &AudioProcessingProperties::enable_sw_echo_cancellation,
992 &AudioProcessingProperties::disable_hw_echo_cancellation,
993 },
994 result);
995 if (IsDeviceCapture()) {
996 CheckDevice(*default_device_, result);
997 } else {
998 EXPECT_TRUE(result.device_id().empty());
999 }
1000 }
1001 }
1002 }
1003 }
1004
1005 // Tests the googEchoCancellation constraint with a device without hardware echo
1006 // cancellation.
1007 TEST_P(MediaStreamConstraintsUtilAudioTest, GoogEchoCancellationWithHw) {
1008 // With content capture, there is no hardware echo cancellation, so
1009 // nothing to test.
1010 if (!IsDeviceCapture())
1011 return;
1012
1013 for (auto set_function : kBoolSetFunctions) {
1014 for (auto accessor : kFactoryAccessors) {
1015 // Ideal advanced is ignored by the SelectSettings algorithm.
1016 if (set_function == &blink::BooleanConstraint::SetIdeal &&
1017 accessor == &MockConstraintFactory::AddAdvanced) {
1018 continue;
1019 }
1020 for (bool value : kBoolValues) {
1021 ResetFactory();
1022 constraint_factory_.basic().device_id.SetExact(
1023 blink::WebString::FromASCII(hw_echo_canceller_device_->device_id));
1024 ((constraint_factory_.*accessor)().goog_echo_cancellation.*
1025 set_function)(value);
1026 auto result = SelectSettings();
1027 EXPECT_TRUE(result.HasValue());
1028 const AudioProcessingProperties& properties =
1029 result.audio_processing_properties();
1030 // With hardware echo cancellation, software echo cancellation is always
1031 // disabled, and hardware echo cancellation is disabled if
1032 // goog_echo_cancellation is false.
1033 EXPECT_FALSE(properties.enable_sw_echo_cancellation);
1034 EXPECT_EQ(!value, properties.disable_hw_echo_cancellation);
1035 CheckBoolDefaults(
1036 AudioSettingsBoolMembers(),
1037 {
1038 &AudioProcessingProperties::enable_sw_echo_cancellation,
1039 &AudioProcessingProperties::disable_hw_echo_cancellation,
1040 },
1041 result);
1042 CheckDevice(*hw_echo_canceller_device_, result);
1043 }
1044 }
1045 }
1046 }
1047
1048 // Test that having differing mandatory values for echoCancellation and
1049 // googEchoCancellation fails.
1050 TEST_P(MediaStreamConstraintsUtilAudioTest, ContradictoryEchoCancellation) {
1051 for (bool value : kBoolValues) {
1052 constraint_factory_.basic().echo_cancellation.SetExact(value);
1053 constraint_factory_.basic().goog_echo_cancellation.SetExact(!value);
1054 auto result = SelectSettings();
1055 EXPECT_FALSE(result.HasValue());
1056 EXPECT_EQ(result.failed_constraint_name(),
1057 constraint_factory_.basic().echo_cancellation.GetName());
1058 }
1059 }
1060
1061 // Tests that individual boolean audio-processing constraints override the
1062 // default value set by the echoCancellation constraint.
1063 TEST_P(MediaStreamConstraintsUtilAudioTest,
1064 EchoCancellationAndSingleBoolConstraint) {
1065 const AudioPropertiesBoolMembers kAudioProcessingProperties = {
1066 &AudioProcessingProperties::goog_audio_mirroring,
1067 &AudioProcessingProperties::goog_auto_gain_control,
1068 &AudioProcessingProperties::goog_experimental_echo_cancellation,
1069 &AudioProcessingProperties::goog_typing_noise_detection,
1070 &AudioProcessingProperties::goog_noise_suppression,
1071 &AudioProcessingProperties::goog_experimental_noise_suppression,
1072 &AudioProcessingProperties::goog_beamforming,
1073 &AudioProcessingProperties::goog_highpass_filter,
1074 &AudioProcessingProperties::goog_experimental_auto_gain_control};
1075
1076 const std::vector<
1077 blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*>
1078 kAudioProcessingConstraints = {
1079 &blink::WebMediaTrackConstraintSet::goog_audio_mirroring,
1080 &blink::WebMediaTrackConstraintSet::goog_auto_gain_control,
1081 &blink::WebMediaTrackConstraintSet::
1082 goog_experimental_echo_cancellation,
1083 &blink::WebMediaTrackConstraintSet::goog_typing_noise_detection,
1084 &blink::WebMediaTrackConstraintSet::goog_noise_suppression,
1085 &blink::WebMediaTrackConstraintSet::
1086 goog_experimental_noise_suppression,
1087 &blink::WebMediaTrackConstraintSet::goog_beamforming,
1088 &blink::WebMediaTrackConstraintSet::goog_highpass_filter,
1089 &blink::WebMediaTrackConstraintSet::
1090 goog_experimental_auto_gain_control,
1091 };
1092
1093 ASSERT_EQ(kAudioProcessingProperties.size(),
1094 kAudioProcessingConstraints.size());
1095 for (auto set_function : kBoolSetFunctions) {
1096 for (auto accessor : kFactoryAccessors) {
1097 // Ideal advanced is ignored by the SelectSettings algorithm.
1098 if (set_function == &blink::BooleanConstraint::SetIdeal &&
1099 accessor == &MockConstraintFactory::AddAdvanced) {
1100 continue;
1101 }
1102 for (size_t i = 0; i < kAudioProcessingProperties.size(); ++i) {
1103 ResetFactory();
1104 ((constraint_factory_.*accessor)().echo_cancellation.*
1105 set_function)(false);
1106 (((constraint_factory_.*accessor)().*kAudioProcessingConstraints[i]).*
1107 set_function)(true);
1108 auto result = SelectSettings();
1109 EXPECT_TRUE(result.HasValue());
1110 EXPECT_FALSE(
1111 result.audio_processing_properties().enable_sw_echo_cancellation);
1112 EXPECT_TRUE(
1113 result.audio_processing_properties().disable_hw_echo_cancellation);
1114 EXPECT_TRUE(result.audio_processing_properties().*
1115 kAudioProcessingProperties[i]);
1116 for (size_t j = 0; j < kAudioProcessingProperties.size(); ++j) {
1117 if (i == j)
1118 continue;
1119 EXPECT_FALSE(result.audio_processing_properties().*
1120 kAudioProcessingProperties[j]);
1121 }
1122 }
1123 }
1124 }
1125 }
1126
1127 // Test advanced constraints sets that can be satisfied.
1128 TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedCompatibleConstraints) {
1129 constraint_factory_.AddAdvanced().sample_size.SetExact(8);
1130 constraint_factory_.AddAdvanced().render_to_associated_sink.SetExact(true);
1131 constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
1132 auto result = SelectSettings();
1133 EXPECT_TRUE(result.HasValue());
1134 if (IsDeviceCapture()) {
1135 // The octagonal device is the only one that matches the first advanced
1136 // constraint set.
1137 CheckDevice(*octagonal_device_, result);
1138 } else {
1139 // Content capture ignores device-related constraints.
1140 EXPECT_TRUE(result.device_id().empty());
1141 }
1142 CheckBoolDefaults({&AudioCaptureSettings::render_to_associated_sink},
1143 {&AudioProcessingProperties::goog_audio_mirroring}, result);
1144 CheckGeometryDefaults(result);
1145 EXPECT_TRUE(result.render_to_associated_sink());
1146 EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
1147 }
1148
1149 // Test that an advanced constraint set that cannot be satisfied is ignored.
1150 TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedSelfConflictingConstraint) {
1151 auto& advanced = constraint_factory_.AddAdvanced();
1152 advanced.sample_size.SetExact(8);
1153 advanced.sample_rate.SetExact(8);
1154 auto result = SelectSettings();
1155 EXPECT_TRUE(result.HasValue());
1156 // The advanced constraint is self conflicting and ignored. The default
1157 // device is selected.
1158 CheckDeviceDefaults(result);
1159 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1160 result);
1161 CheckGeometryDefaults(result);
1162 }
1163
1164 // Test that an advanced constraint set that contradicts a previous constraint
1165 // set with a device-related constraint is ignored.
1166 TEST_P(MediaStreamConstraintsUtilAudioTest,
1167 AdvancedConflictingDeviceConstraint) {
1168 constraint_factory_.AddAdvanced().sample_size.SetExact(8);
1169 constraint_factory_.AddAdvanced().sample_size.SetExact(
1170 media::AudioParameters::kAudioCDSampleRate);
1171 auto result = SelectSettings();
1172 EXPECT_TRUE(result.HasValue());
1173 if (IsDeviceCapture()) {
1174 // The octagonal device is the only one that matches the first advanced
1175 // constraint set. The second set is ignored.
1176 CheckDevice(*octagonal_device_, result);
1177 EXPECT_NE(media::AudioParameters::kAudioCDSampleRate,
1178 result.device_parameters().sample_rate());
1179 } else {
1180 // Content capture ignores device-related constraints.
1181 EXPECT_TRUE(result.device_id().empty());
1182 }
1183 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1184 result);
1185 CheckGeometryDefaults(result);
1186 }
1187
1188 // Test that an advanced constraint set that contradicts a previous constraint
1189 // set is ignored, but that further constraint sets that can be satisfied are
1190 // applied.
1191 TEST_P(MediaStreamConstraintsUtilAudioTest,
1192 AdvancedConflictingMiddleConstraints) {
1193 constraint_factory_.AddAdvanced().sample_size.SetExact(8);
1194 auto& advanced2 = constraint_factory_.AddAdvanced();
1195 advanced2.sample_rate.SetExact(123456);
1196 advanced2.hotword_enabled.SetExact(true);
1197 constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
1198 auto result = SelectSettings();
1199 EXPECT_TRUE(result.HasValue());
1200 if (IsDeviceCapture()) {
1201 // The octagonal device is the only one that matches the first advanced
1202 // constraint set.
1203 CheckDevice(*octagonal_device_, result);
1204 // Second advanced set is discarded because no device has the requested
1205 // sample rate.
1206 EXPECT_NE(123456, result.device_parameters().sample_rate());
1207 EXPECT_FALSE(result.hotword_enabled());
1208 } else {
1209 // Content capture ignores device-related constraints. Thus, it does not
1210 // discard the second advanced set.
1211 EXPECT_TRUE(result.device_id().empty());
1212 EXPECT_TRUE(result.hotword_enabled());
1213 }
1214 CheckBoolDefaults({&AudioCaptureSettings::render_to_associated_sink,
1215 &AudioCaptureSettings::hotword_enabled},
1216 {&AudioProcessingProperties::goog_audio_mirroring}, result);
1217 CheckGeometryDefaults(result);
1218 EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
1219 }
1220
1221 // Test that an advanced constraint set that contradicts a previous constraint
1222 // set with a boolean constraint is ignored.
1223 TEST_P(MediaStreamConstraintsUtilAudioTest, AdvancedConflictingLastConstraint) {
1224 constraint_factory_.AddAdvanced().sample_size.SetExact(8);
1225 constraint_factory_.AddAdvanced().hotword_enabled.SetExact(true);
1226 constraint_factory_.AddAdvanced().goog_audio_mirroring.SetExact(true);
1227 constraint_factory_.AddAdvanced().hotword_enabled.SetExact(false);
1228 auto result = SelectSettings();
1229 EXPECT_TRUE(result.HasValue());
1230 if (IsDeviceCapture()) {
1231 // The octagonal device is the only one that matches the first advanced
1232 // constraint set.
1233 CheckDevice(*octagonal_device_, result);
1234 } else {
1235 // Content capture ignores device-related constraints.
1236 EXPECT_TRUE(result.device_id().empty());
1237 }
1238 CheckBoolDefaults({&AudioCaptureSettings::hotword_enabled},
1239 {&AudioProcessingProperties::goog_audio_mirroring}, result);
1240 CheckGeometryDefaults(result);
1241 // The fourth advanced set is ignored because it contradicts the second set.
1242 EXPECT_TRUE(result.hotword_enabled());
1243 EXPECT_TRUE(result.audio_processing_properties().goog_audio_mirroring);
1244 }
1245
1246 // Test that a valid geometry is interpreted correctly in all the ways it can
1247 // be set.
1248 TEST_P(MediaStreamConstraintsUtilAudioTest, ValidGeometry) {
1249 const blink::WebString kGeometry =
1250 blink::WebString::FromASCII("-0.02 0 0 0.02 0 1.01");
1251
1252 for (auto set_function : kStringSetFunctions) {
1253 for (auto accessor : kFactoryAccessors) {
1254 // Ideal advanced is ignored by the SelectSettings algorithm.
1255 // Using kStringSetFunctions[1] instead of
1256 // static_cast<StringSetFunction>(&blink::StringConstraint::SetIdeal)
1257 // because the equality comparison provides the wrong result in the
1258 // Windows Debug build, making the test fail.
hbos_chromium 2017/06/14 08:12:12 lol wtf
1259 if (set_function == kStringSetFunctions[1] &&
1260 accessor == &MockConstraintFactory::AddAdvanced) {
1261 continue;
1262 }
1263 ResetFactory();
1264 ((constraint_factory_.*accessor)().goog_array_geometry.*
1265 set_function)(kGeometry);
1266 auto result = SelectSettings();
1267 EXPECT_TRUE(result.HasValue());
1268 CheckDeviceDefaults(result);
1269 CheckBoolDefaults(AudioSettingsBoolMembers(),
1270 AudioPropertiesBoolMembers(), result);
1271 const std::vector<media::Point>& geometry =
1272 result.audio_processing_properties().goog_array_geometry;
1273 EXPECT_EQ(2u, geometry.size());
1274 EXPECT_EQ(media::Point(-0.02, 0, 0), geometry[0]);
1275 EXPECT_EQ(media::Point(0.02, 0, 1.01), geometry[1]);
1276 }
1277 }
1278 }
1279
1280 // Test that an invalid geometry is interpreted as empty in all the ways it can
1281 // be set.
1282 TEST_P(MediaStreamConstraintsUtilAudioTest, InvalidGeometry) {
1283 const blink::WebString kGeometry =
1284 blink::WebString::FromASCII("1 1 1 invalid");
1285
1286 for (auto set_function : kStringSetFunctions) {
1287 for (auto accessor : kFactoryAccessors) {
1288 // Ideal advanced is ignored by the SelectSettings algorithm.
1289 if (set_function == static_cast<StringSetFunction>(
1290 &blink::StringConstraint::SetIdeal) &&
1291 accessor == &MockConstraintFactory::AddAdvanced) {
1292 continue;
1293 }
1294 ResetFactory();
1295 ((constraint_factory_.*accessor)().goog_array_geometry.*
1296 set_function)(kGeometry);
1297 auto result = SelectSettings();
1298 EXPECT_TRUE(result.HasValue());
1299 CheckDeviceDefaults(result);
1300 CheckBoolDefaults(AudioSettingsBoolMembers(),
1301 AudioPropertiesBoolMembers(), result);
1302 const std::vector<media::Point>& geometry =
1303 result.audio_processing_properties().goog_array_geometry;
1304 EXPECT_EQ(0u, geometry.size());
1305 }
1306 }
1307 }
1308
1309 // Test that an invalid geometry is interpreted as empty in all the ways it can
1310 // be set.
1311 TEST_P(MediaStreamConstraintsUtilAudioTest, DeviceGeometry) {
1312 if (!IsDeviceCapture())
1313 return;
1314
1315 constraint_factory_.basic().device_id.SetExact(
1316 blink::WebString::FromASCII(geometry_device_->device_id));
1317
1318 {
1319 const blink::WebString kValidGeometry =
1320 blink::WebString::FromASCII("-0.02 0 0 0.02 0 1.01");
1321 constraint_factory_.basic().goog_array_geometry.SetExact(kValidGeometry);
1322 auto result = SelectSettings();
1323 EXPECT_TRUE(result.HasValue());
1324 CheckDevice(*geometry_device_, result);
1325 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1326 result);
1327 // Constraints geometry should be preferred over device geometry.
1328 const std::vector<media::Point>& geometry =
1329 result.audio_processing_properties().goog_array_geometry;
1330 EXPECT_EQ(2u, geometry.size());
1331 EXPECT_EQ(media::Point(-0.02, 0, 0), geometry[0]);
1332 EXPECT_EQ(media::Point(0.02, 0, 1.01), geometry[1]);
1333 }
1334
1335 {
1336 constraint_factory_.basic().goog_array_geometry.SetExact(
1337 blink::WebString());
1338 auto result = SelectSettings();
1339 EXPECT_TRUE(result.HasValue());
1340 CheckDevice(*geometry_device_, result);
1341 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1342 result);
1343 // Empty geometry is valid and should be preferred over device geometry.
1344 EXPECT_TRUE(
1345 result.audio_processing_properties().goog_array_geometry.empty());
1346 }
1347
1348 {
1349 const blink::WebString kInvalidGeometry =
1350 blink::WebString::FromASCII("1 1 1 invalid");
1351 constraint_factory_.basic().goog_array_geometry.SetExact(kInvalidGeometry);
1352 auto result = SelectSettings();
1353 EXPECT_TRUE(result.HasValue());
1354 CheckDevice(*geometry_device_, result);
1355 CheckBoolDefaults(AudioSettingsBoolMembers(), AudioPropertiesBoolMembers(),
1356 result);
1357 // Device geometry should be preferred over invalid constraints geometry.
1358 EXPECT_EQ(kMicPositions,
1359 result.audio_processing_properties().goog_array_geometry);
1360 }
1361 }
1362
1363 // NoDevices tests verify that the case with no devices is handled correctly.
1364 TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesNoConstraints) {
1365 // This test makes sense only for device capture.
1366 if (!IsDeviceCapture())
1367 return;
1368
1369 AudioDeviceCaptureCapabilities capabilities;
1370 auto result = SelectSettingsAudioCapture(
1371 capabilities, constraint_factory_.CreateWebMediaConstraints());
1372 EXPECT_FALSE(result.HasValue());
1373 EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
1374 }
1375
1376 TEST_P(MediaStreamConstraintsUtilAudioTest, NoDevicesWithConstraints) {
1377 // This test makes sense only for device capture.
1378 if (!IsDeviceCapture())
1379 return;
1380
1381 AudioDeviceCaptureCapabilities capabilities;
1382 constraint_factory_.basic().sample_size.SetExact(16);
1383 auto result = SelectSettingsAudioCapture(
1384 capabilities, constraint_factory_.CreateWebMediaConstraints());
1385 EXPECT_FALSE(result.HasValue());
1386 EXPECT_TRUE(std::string(result.failed_constraint_name()).empty());
1387 }
1388
1389 INSTANTIATE_TEST_CASE_P(,
1390 MediaStreamConstraintsUtilAudioTest,
1391 testing::Values("",
1392 kMediaStreamSourceTab,
1393 kMediaStreamSourceSystem,
1394 kMediaStreamSourceDesktop));
1395
1396 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698