1 /*
2  *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/audio_device/win/core_audio_utility_win.h"
12 #include "rtc_base/arraysize.h"
13 #include "rtc_base/logging.h"
14 #include "rtc_base/win/windows_version.h"
15 #include "test/gtest.h"
16 
17 #include "system_wrappers/include/sleep.h"
18 
19 using Microsoft::WRL::ComPtr;
20 using webrtc::AudioDeviceName;
21 
22 namespace webrtc {
23 namespace webrtc_win {
24 namespace {
25 
26 #define ABORT_TEST_IF_NOT(requirements_satisfied)                        \
27   do {                                                                   \
28     bool fail = false;                                                   \
29     if (ShouldAbortTest(requirements_satisfied, #requirements_satisfied, \
30                         &fail)) {                                        \
31       if (fail)                                                          \
32         FAIL();                                                          \
33       else                                                               \
34         return;                                                          \
35     }                                                                    \
36   } while (false)
37 
ShouldAbortTest(bool requirements_satisfied,const char * requirements_expression,bool * should_fail)38 bool ShouldAbortTest(bool requirements_satisfied,
39                      const char* requirements_expression,
40                      bool* should_fail) {
41   if (!requirements_satisfied) {
42     RTC_LOG(LS_ERROR) << "Requirement(s) not satisfied ("
43                       << requirements_expression << ")";
44     // TODO(henrika): improve hard-coded condition to determine if test should
45     // fail or be ignored. Could use e.g. a command-line argument here to
46     // determine if the test should fail or not.
47     *should_fail = false;
48     return true;
49   }
50   *should_fail = false;
51   return false;
52 }
53 
54 }  // namespace
55 
56 // CoreAudioUtilityWinTest test fixture.
57 class CoreAudioUtilityWinTest : public ::testing::Test {
58  protected:
CoreAudioUtilityWinTest()59   CoreAudioUtilityWinTest()
60       : com_init_(webrtc_win::ScopedCOMInitializer::kMTA) {
61     // We must initialize the COM library on a thread before we calling any of
62     // the library functions. All COM functions will return CO_E_NOTINITIALIZED
63     // otherwise.
64     EXPECT_TRUE(com_init_.Succeeded());
65 
66     // Configure logging.
67     rtc::LogMessage::LogToDebug(rtc::LS_INFO);
68     rtc::LogMessage::LogTimestamps();
69     rtc::LogMessage::LogThreads();
70   }
71 
~CoreAudioUtilityWinTest()72   virtual ~CoreAudioUtilityWinTest() {}
73 
DevicesAvailable()74   bool DevicesAvailable() {
75     return core_audio_utility::IsSupported() &&
76            core_audio_utility::NumberOfActiveDevices(eCapture) > 0 &&
77            core_audio_utility::NumberOfActiveDevices(eRender) > 0;
78   }
79 
80  private:
81   ScopedCOMInitializer com_init_;
82 };
83 
TEST_F(CoreAudioUtilityWinTest,WaveFormatWrapper)84 TEST_F(CoreAudioUtilityWinTest, WaveFormatWrapper) {
85   // Use default constructor for WAVEFORMATEX and verify its size.
86   WAVEFORMATEX format = {};
87   core_audio_utility::WaveFormatWrapper wave_format(&format);
88   EXPECT_FALSE(wave_format.IsExtensible());
89   EXPECT_EQ(wave_format.size(), sizeof(WAVEFORMATEX));
90   EXPECT_EQ(wave_format->cbSize, 0);
91 
92   // Ensure that the stand-alone WAVEFORMATEX structure has a valid format tag
93   // and that all accessors work.
94   format.wFormatTag = WAVE_FORMAT_PCM;
95   EXPECT_FALSE(wave_format.IsExtensible());
96   EXPECT_EQ(wave_format.size(), sizeof(WAVEFORMATEX));
97   EXPECT_EQ(wave_format.get()->wFormatTag, WAVE_FORMAT_PCM);
98   EXPECT_EQ(wave_format->wFormatTag, WAVE_FORMAT_PCM);
99 
100   // Next, ensure that the size is valid. Stand-alone is not extended.
101   EXPECT_EQ(wave_format.size(), sizeof(WAVEFORMATEX));
102 
103   // Verify format types for the stand-alone version.
104   EXPECT_TRUE(wave_format.IsPcm());
105   EXPECT_FALSE(wave_format.IsFloat());
106   format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
107   EXPECT_TRUE(wave_format.IsFloat());
108 }
109 
TEST_F(CoreAudioUtilityWinTest,WaveFormatWrapperExtended)110 TEST_F(CoreAudioUtilityWinTest, WaveFormatWrapperExtended) {
111   // Use default constructor for WAVEFORMATEXTENSIBLE and verify that it
112   // results in same size as for WAVEFORMATEX even if the size of |format_ex|
113   // equals the size of WAVEFORMATEXTENSIBLE.
114   WAVEFORMATEXTENSIBLE format_ex = {};
115   core_audio_utility::WaveFormatWrapper wave_format_ex(&format_ex);
116   EXPECT_FALSE(wave_format_ex.IsExtensible());
117   EXPECT_EQ(wave_format_ex.size(), sizeof(WAVEFORMATEX));
118   EXPECT_EQ(wave_format_ex->cbSize, 0);
119 
120   // Ensure that the extended structure has a valid format tag and that all
121   // accessors work.
122   format_ex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
123   EXPECT_FALSE(wave_format_ex.IsExtensible());
124   EXPECT_EQ(wave_format_ex.size(), sizeof(WAVEFORMATEX));
125   EXPECT_EQ(wave_format_ex->wFormatTag, WAVE_FORMAT_EXTENSIBLE);
126   EXPECT_EQ(wave_format_ex.get()->wFormatTag, WAVE_FORMAT_EXTENSIBLE);
127 
128   // Next, ensure that the size is valid (sum of stand-alone and extended).
129   // Now the structure qualifies as extended.
130   format_ex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
131   EXPECT_TRUE(wave_format_ex.IsExtensible());
132   EXPECT_EQ(wave_format_ex.size(), sizeof(WAVEFORMATEXTENSIBLE));
133   EXPECT_TRUE(wave_format_ex.GetExtensible());
134   EXPECT_EQ(wave_format_ex.GetExtensible()->Format.wFormatTag,
135             WAVE_FORMAT_EXTENSIBLE);
136 
137   // Verify format types for the extended version.
138   EXPECT_FALSE(wave_format_ex.IsPcm());
139   format_ex.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
140   EXPECT_TRUE(wave_format_ex.IsPcm());
141   EXPECT_FALSE(wave_format_ex.IsFloat());
142   format_ex.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
143   EXPECT_TRUE(wave_format_ex.IsFloat());
144 }
145 
TEST_F(CoreAudioUtilityWinTest,NumberOfActiveDevices)146 TEST_F(CoreAudioUtilityWinTest, NumberOfActiveDevices) {
147   ABORT_TEST_IF_NOT(DevicesAvailable());
148   int render_devices = core_audio_utility::NumberOfActiveDevices(eRender);
149   EXPECT_GT(render_devices, 0);
150   int capture_devices = core_audio_utility::NumberOfActiveDevices(eCapture);
151   EXPECT_GT(capture_devices, 0);
152   int total_devices = core_audio_utility::NumberOfActiveDevices(eAll);
153   EXPECT_EQ(total_devices, render_devices + capture_devices);
154 }
155 
TEST_F(CoreAudioUtilityWinTest,GetAudioClientVersion)156 TEST_F(CoreAudioUtilityWinTest, GetAudioClientVersion) {
157   uint32_t client_version = core_audio_utility::GetAudioClientVersion();
158   EXPECT_GE(client_version, 1u);
159   EXPECT_LE(client_version, 3u);
160 }
161 
TEST_F(CoreAudioUtilityWinTest,CreateDeviceEnumerator)162 TEST_F(CoreAudioUtilityWinTest, CreateDeviceEnumerator) {
163   ABORT_TEST_IF_NOT(DevicesAvailable());
164   ComPtr<IMMDeviceEnumerator> enumerator =
165       core_audio_utility::CreateDeviceEnumerator();
166   EXPECT_TRUE(enumerator.Get());
167 }
168 
TEST_F(CoreAudioUtilityWinTest,GetDefaultInputDeviceID)169 TEST_F(CoreAudioUtilityWinTest, GetDefaultInputDeviceID) {
170   ABORT_TEST_IF_NOT(DevicesAvailable());
171   std::string default_device_id = core_audio_utility::GetDefaultInputDeviceID();
172   EXPECT_FALSE(default_device_id.empty());
173 }
174 
TEST_F(CoreAudioUtilityWinTest,GetDefaultOutputDeviceID)175 TEST_F(CoreAudioUtilityWinTest, GetDefaultOutputDeviceID) {
176   ABORT_TEST_IF_NOT(DevicesAvailable());
177   std::string default_device_id =
178       core_audio_utility::GetDefaultOutputDeviceID();
179   EXPECT_FALSE(default_device_id.empty());
180 }
181 
TEST_F(CoreAudioUtilityWinTest,GetCommunicationsInputDeviceID)182 TEST_F(CoreAudioUtilityWinTest, GetCommunicationsInputDeviceID) {
183   ABORT_TEST_IF_NOT(DevicesAvailable());
184   std::string default_device_id =
185       core_audio_utility::GetCommunicationsInputDeviceID();
186   EXPECT_FALSE(default_device_id.empty());
187 }
188 
TEST_F(CoreAudioUtilityWinTest,GetCommunicationsOutputDeviceID)189 TEST_F(CoreAudioUtilityWinTest, GetCommunicationsOutputDeviceID) {
190   ABORT_TEST_IF_NOT(DevicesAvailable());
191   std::string default_device_id =
192       core_audio_utility::GetCommunicationsOutputDeviceID();
193   EXPECT_FALSE(default_device_id.empty());
194 }
195 
TEST_F(CoreAudioUtilityWinTest,CreateDefaultDevice)196 TEST_F(CoreAudioUtilityWinTest, CreateDefaultDevice) {
197   ABORT_TEST_IF_NOT(DevicesAvailable());
198 
199   struct {
200     EDataFlow flow;
201     ERole role;
202   } data[] = {{eRender, eConsole},         {eRender, eCommunications},
203               {eRender, eMultimedia},      {eCapture, eConsole},
204               {eCapture, eCommunications}, {eCapture, eMultimedia}};
205 
206   // Create default devices for all flow/role combinations above.
207   ComPtr<IMMDevice> audio_device;
208   for (size_t i = 0; i < arraysize(data); ++i) {
209     audio_device = core_audio_utility::CreateDevice(
210         AudioDeviceName::kDefaultDeviceId, data[i].flow, data[i].role);
211     EXPECT_TRUE(audio_device.Get());
212     EXPECT_EQ(data[i].flow,
213               core_audio_utility::GetDataFlow(audio_device.Get()));
214   }
215 
216   // Only eRender and eCapture are allowed as flow parameter.
217   audio_device = core_audio_utility::CreateDevice(
218       AudioDeviceName::kDefaultDeviceId, eAll, eConsole);
219   EXPECT_FALSE(audio_device.Get());
220 }
221 
TEST_F(CoreAudioUtilityWinTest,CreateDevice)222 TEST_F(CoreAudioUtilityWinTest, CreateDevice) {
223   ABORT_TEST_IF_NOT(DevicesAvailable());
224 
225   // Get name and ID of default device used for playback.
226   ComPtr<IMMDevice> default_render_device = core_audio_utility::CreateDevice(
227       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
228   AudioDeviceName default_render_name =
229       core_audio_utility::GetDeviceName(default_render_device.Get());
230   EXPECT_TRUE(default_render_name.IsValid());
231 
232   // Use the unique ID as input to CreateDevice() and create a corresponding
233   // IMMDevice. The data-flow direction and role parameters are ignored for
234   // this scenario.
235   ComPtr<IMMDevice> audio_device = core_audio_utility::CreateDevice(
236       default_render_name.unique_id, EDataFlow(), ERole());
237   EXPECT_TRUE(audio_device.Get());
238 
239   // Verify that the two IMMDevice interfaces represents the same endpoint
240   // by comparing their unique IDs.
241   AudioDeviceName device_name =
242       core_audio_utility::GetDeviceName(audio_device.Get());
243   EXPECT_EQ(default_render_name.unique_id, device_name.unique_id);
244 }
245 
TEST_F(CoreAudioUtilityWinTest,GetDefaultDeviceName)246 TEST_F(CoreAudioUtilityWinTest, GetDefaultDeviceName) {
247   ABORT_TEST_IF_NOT(DevicesAvailable());
248 
249   struct {
250     EDataFlow flow;
251     ERole role;
252   } data[] = {{eRender, eConsole},
253               {eRender, eCommunications},
254               {eCapture, eConsole},
255               {eCapture, eCommunications}};
256 
257   // Get name and ID of default devices for all flow/role combinations above.
258   ComPtr<IMMDevice> audio_device;
259   AudioDeviceName device_name;
260   for (size_t i = 0; i < arraysize(data); ++i) {
261     audio_device = core_audio_utility::CreateDevice(
262         AudioDeviceName::kDefaultDeviceId, data[i].flow, data[i].role);
263     device_name = core_audio_utility::GetDeviceName(audio_device.Get());
264     EXPECT_TRUE(device_name.IsValid());
265   }
266 }
267 
TEST_F(CoreAudioUtilityWinTest,GetFriendlyName)268 TEST_F(CoreAudioUtilityWinTest, GetFriendlyName) {
269   ABORT_TEST_IF_NOT(DevicesAvailable());
270 
271   // Get name and ID of default device used for recording.
272   ComPtr<IMMDevice> audio_device = core_audio_utility::CreateDevice(
273       AudioDeviceName::kDefaultDeviceId, eCapture, eConsole);
274   AudioDeviceName device_name =
275       core_audio_utility::GetDeviceName(audio_device.Get());
276   EXPECT_TRUE(device_name.IsValid());
277 
278   // Use unique ID as input to GetFriendlyName() and compare the result
279   // with the already obtained friendly name for the default capture device.
280   std::string friendly_name = core_audio_utility::GetFriendlyName(
281       device_name.unique_id, eCapture, eConsole);
282   EXPECT_EQ(friendly_name, device_name.device_name);
283 
284   // Same test as above but for playback.
285   audio_device = core_audio_utility::CreateDevice(
286       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
287   device_name = core_audio_utility::GetDeviceName(audio_device.Get());
288   friendly_name = core_audio_utility::GetFriendlyName(device_name.unique_id,
289                                                       eRender, eConsole);
290   EXPECT_EQ(friendly_name, device_name.device_name);
291 }
292 
TEST_F(CoreAudioUtilityWinTest,GetInputDeviceNames)293 TEST_F(CoreAudioUtilityWinTest, GetInputDeviceNames) {
294   ABORT_TEST_IF_NOT(DevicesAvailable());
295 
296   webrtc::AudioDeviceNames device_names;
297   EXPECT_TRUE(core_audio_utility::GetInputDeviceNames(&device_names));
298   // Number of elements in the list should be two more than the number of
299   // active devices since we always add default and default communication
300   // devices on index 0 and 1.
301   EXPECT_EQ(static_cast<int>(device_names.size()),
302             2 + core_audio_utility::NumberOfActiveDevices(eCapture));
303 }
304 
TEST_F(CoreAudioUtilityWinTest,GetOutputDeviceNames)305 TEST_F(CoreAudioUtilityWinTest, GetOutputDeviceNames) {
306   ABORT_TEST_IF_NOT(DevicesAvailable());
307 
308   webrtc::AudioDeviceNames device_names;
309   EXPECT_TRUE(core_audio_utility::GetOutputDeviceNames(&device_names));
310   // Number of elements in the list should be two more than the number of
311   // active devices since we always add default and default communication
312   // devices on index 0 and 1.
313   EXPECT_EQ(static_cast<int>(device_names.size()),
314             2 + core_audio_utility::NumberOfActiveDevices(eRender));
315 }
316 
TEST_F(CoreAudioUtilityWinTest,CreateSessionManager2)317 TEST_F(CoreAudioUtilityWinTest, CreateSessionManager2) {
318   ABORT_TEST_IF_NOT(DevicesAvailable() &&
319                     rtc::rtc_win::GetVersion() >= rtc::rtc_win::VERSION_WIN7);
320 
321   EDataFlow data_flow[] = {eRender, eCapture};
322 
323   // Obtain reference to an IAudioSessionManager2 interface for a default audio
324   // endpoint device specified by two different data flows and the |eConsole|
325   // role.
326   for (size_t i = 0; i < arraysize(data_flow); ++i) {
327     ComPtr<IMMDevice> device(core_audio_utility::CreateDevice(
328         AudioDeviceName::kDefaultDeviceId, data_flow[i], eConsole));
329     EXPECT_TRUE(device.Get());
330     ComPtr<IAudioSessionManager2> session_manager =
331         core_audio_utility::CreateSessionManager2(device.Get());
332     EXPECT_TRUE(session_manager.Get());
333   }
334 }
335 
TEST_F(CoreAudioUtilityWinTest,CreateSessionEnumerator)336 TEST_F(CoreAudioUtilityWinTest, CreateSessionEnumerator) {
337   ABORT_TEST_IF_NOT(DevicesAvailable() &&
338                     rtc::rtc_win::GetVersion() >= rtc::rtc_win::VERSION_WIN7);
339 
340   EDataFlow data_flow[] = {eRender, eCapture};
341 
342   // Obtain reference to an IAudioSessionEnumerator interface for a default
343   // audio endpoint device specified by two different data flows and the
344   // |eConsole| role.
345   for (size_t i = 0; i < arraysize(data_flow); ++i) {
346     ComPtr<IMMDevice> device(core_audio_utility::CreateDevice(
347         AudioDeviceName::kDefaultDeviceId, data_flow[i], eConsole));
348     EXPECT_TRUE(device.Get());
349     ComPtr<IAudioSessionEnumerator> session_enumerator =
350         core_audio_utility::CreateSessionEnumerator(device.Get());
351     EXPECT_TRUE(session_enumerator.Get());
352 
353     // Perform a sanity test of the interface by asking for the total number
354     // of audio sessions that are open on the audio device. Note that, we do
355     // not check if the session is active or not.
356     int session_count = 0;
357     EXPECT_TRUE(SUCCEEDED(session_enumerator->GetCount(&session_count)));
358     EXPECT_GE(session_count, 0);
359   }
360 }
361 
TEST_F(CoreAudioUtilityWinTest,NumberOfActiveSessions)362 TEST_F(CoreAudioUtilityWinTest, NumberOfActiveSessions) {
363   ABORT_TEST_IF_NOT(DevicesAvailable() &&
364                     rtc::rtc_win::GetVersion() >= rtc::rtc_win::VERSION_WIN7);
365 
366   EDataFlow data_flow[] = {eRender, eCapture};
367 
368   // Count number of active audio session for a default audio endpoint device
369   // specified by two different data flows and the |eConsole| role.
370   // Ensure that the number of active audio sessions is less than or equal to
371   // the total number of audio sessions on that same device.
372   for (size_t i = 0; i < arraysize(data_flow); ++i) {
373     // Create an audio endpoint device.
374     ComPtr<IMMDevice> device(core_audio_utility::CreateDevice(
375         AudioDeviceName::kDefaultDeviceId, data_flow[i], eConsole));
376     EXPECT_TRUE(device.Get());
377 
378     // Ask for total number of audio sessions on the created device.
379     ComPtr<IAudioSessionEnumerator> session_enumerator =
380         core_audio_utility::CreateSessionEnumerator(device.Get());
381     EXPECT_TRUE(session_enumerator.Get());
382     int total_session_count = 0;
383     EXPECT_TRUE(SUCCEEDED(session_enumerator->GetCount(&total_session_count)));
384     EXPECT_GE(total_session_count, 0);
385 
386     // Use NumberOfActiveSessions and get number of active audio sessions.
387     int active_session_count =
388         core_audio_utility::NumberOfActiveSessions(device.Get());
389     EXPECT_LE(active_session_count, total_session_count);
390   }
391 }
392 
TEST_F(CoreAudioUtilityWinTest,CreateClient)393 TEST_F(CoreAudioUtilityWinTest, CreateClient) {
394   ABORT_TEST_IF_NOT(DevicesAvailable());
395 
396   EDataFlow data_flow[] = {eRender, eCapture};
397 
398   // Obtain reference to an IAudioClient interface for a default audio endpoint
399   // device specified by two different data flows and the |eConsole| role.
400   for (size_t i = 0; i < arraysize(data_flow); ++i) {
401     ComPtr<IAudioClient> client = core_audio_utility::CreateClient(
402         AudioDeviceName::kDefaultDeviceId, data_flow[i], eConsole);
403     EXPECT_TRUE(client.Get());
404   }
405 }
406 
TEST_F(CoreAudioUtilityWinTest,CreateClient2)407 TEST_F(CoreAudioUtilityWinTest, CreateClient2) {
408   ABORT_TEST_IF_NOT(DevicesAvailable() &&
409                     core_audio_utility::GetAudioClientVersion() >= 2);
410 
411   EDataFlow data_flow[] = {eRender, eCapture};
412 
413   // Obtain reference to an IAudioClient2 interface for a default audio endpoint
414   // device specified by two different data flows and the |eConsole| role.
415   for (size_t i = 0; i < arraysize(data_flow); ++i) {
416     ComPtr<IAudioClient2> client2 = core_audio_utility::CreateClient2(
417         AudioDeviceName::kDefaultDeviceId, data_flow[i], eConsole);
418     EXPECT_TRUE(client2.Get());
419   }
420 }
421 
TEST_F(CoreAudioUtilityWinTest,CreateClient3)422 TEST_F(CoreAudioUtilityWinTest, CreateClient3) {
423   ABORT_TEST_IF_NOT(DevicesAvailable() &&
424                     core_audio_utility::GetAudioClientVersion() >= 3);
425 
426   EDataFlow data_flow[] = {eRender, eCapture};
427 
428   // Obtain reference to an IAudioClient3 interface for a default audio endpoint
429   // device specified by two different data flows and the |eConsole| role.
430   for (size_t i = 0; i < arraysize(data_flow); ++i) {
431     ComPtr<IAudioClient3> client3 = core_audio_utility::CreateClient3(
432         AudioDeviceName::kDefaultDeviceId, data_flow[i], eConsole);
433     EXPECT_TRUE(client3.Get());
434   }
435 }
436 
TEST_F(CoreAudioUtilityWinTest,SetClientProperties)437 TEST_F(CoreAudioUtilityWinTest, SetClientProperties) {
438   ABORT_TEST_IF_NOT(DevicesAvailable() &&
439                     core_audio_utility::GetAudioClientVersion() >= 2);
440 
441   ComPtr<IAudioClient2> client2 = core_audio_utility::CreateClient2(
442       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
443   EXPECT_TRUE(client2.Get());
444   EXPECT_TRUE(
445       SUCCEEDED(core_audio_utility::SetClientProperties(client2.Get())));
446 
447   ComPtr<IAudioClient3> client3 = core_audio_utility::CreateClient3(
448       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
449   EXPECT_TRUE(client3.Get());
450   EXPECT_TRUE(
451       SUCCEEDED(core_audio_utility::SetClientProperties(client3.Get())));
452 }
453 
TEST_F(CoreAudioUtilityWinTest,GetSharedModeEnginePeriod)454 TEST_F(CoreAudioUtilityWinTest, GetSharedModeEnginePeriod) {
455   ABORT_TEST_IF_NOT(DevicesAvailable() &&
456                     core_audio_utility::GetAudioClientVersion() >= 3);
457 
458   ComPtr<IAudioClient3> client3 = core_audio_utility::CreateClient3(
459       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
460   EXPECT_TRUE(client3.Get());
461 
462   WAVEFORMATPCMEX format;
463   EXPECT_TRUE(SUCCEEDED(
464       core_audio_utility::GetSharedModeMixFormat(client3.Get(), &format)));
465 
466   uint32_t default_period = 0;
467   uint32_t fundamental_period = 0;
468   uint32_t min_period = 0;
469   uint32_t max_period = 0;
470   EXPECT_TRUE(SUCCEEDED(core_audio_utility::GetSharedModeEnginePeriod(
471       client3.Get(), &format, &default_period, &fundamental_period, &min_period,
472       &max_period)));
473 }
474 
475 // TODO(henrika): figure out why usage of this API always reports
476 // AUDCLNT_E_OFFLOAD_MODE_ONLY.
TEST_F(CoreAudioUtilityWinTest,DISABLED_GetBufferSizeLimits)477 TEST_F(CoreAudioUtilityWinTest, DISABLED_GetBufferSizeLimits) {
478   ABORT_TEST_IF_NOT(DevicesAvailable() &&
479                     core_audio_utility::GetAudioClientVersion() >= 2);
480 
481   ComPtr<IAudioClient2> client2 = core_audio_utility::CreateClient2(
482       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
483   EXPECT_TRUE(client2.Get());
484 
485   WAVEFORMATPCMEX format;
486   EXPECT_TRUE(SUCCEEDED(
487       core_audio_utility::GetSharedModeMixFormat(client2.Get(), &format)));
488 
489   REFERENCE_TIME min_buffer_duration = 0;
490   REFERENCE_TIME max_buffer_duration = 0;
491   EXPECT_TRUE(SUCCEEDED(core_audio_utility::GetBufferSizeLimits(
492       client2.Get(), &format, &min_buffer_duration, &max_buffer_duration)));
493 }
494 
TEST_F(CoreAudioUtilityWinTest,GetSharedModeMixFormat)495 TEST_F(CoreAudioUtilityWinTest, GetSharedModeMixFormat) {
496   ABORT_TEST_IF_NOT(DevicesAvailable());
497 
498   ComPtr<IAudioClient> client = core_audio_utility::CreateClient(
499       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
500   EXPECT_TRUE(client.Get());
501 
502   // Perform a simple sanity test of the acquired format structure.
503   WAVEFORMATEXTENSIBLE format;
504   EXPECT_TRUE(SUCCEEDED(
505       core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
506   core_audio_utility::WaveFormatWrapper wformat(&format);
507   EXPECT_GE(wformat->nChannels, 1);
508   EXPECT_GE(wformat->nSamplesPerSec, 8000u);
509   EXPECT_GE(wformat->wBitsPerSample, 16);
510   if (wformat.IsExtensible()) {
511     EXPECT_EQ(wformat->wFormatTag, WAVE_FORMAT_EXTENSIBLE);
512     EXPECT_GE(wformat->cbSize, 22);
513     EXPECT_GE(wformat.GetExtensible()->Samples.wValidBitsPerSample, 16);
514   } else {
515     EXPECT_EQ(wformat->cbSize, 0);
516   }
517 }
518 
TEST_F(CoreAudioUtilityWinTest,IsFormatSupported)519 TEST_F(CoreAudioUtilityWinTest, IsFormatSupported) {
520   ABORT_TEST_IF_NOT(DevicesAvailable());
521 
522   // Create a default render client.
523   ComPtr<IAudioClient> client = core_audio_utility::CreateClient(
524       AudioDeviceName::kDefaultDeviceId, eRender, eConsole);
525   EXPECT_TRUE(client.Get());
526 
527   // Get the default, shared mode, mixing format.
528   WAVEFORMATEXTENSIBLE format;
529   EXPECT_TRUE(SUCCEEDED(
530       core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
531 
532   // In shared mode, the audio engine always supports the mix format.
533   EXPECT_TRUE(core_audio_utility::IsFormatSupported(
534       client.Get(), AUDCLNT_SHAREMODE_SHARED, &format));
535 
536   // Use an invalid format and verify that it is not supported.
537   format.Format.nSamplesPerSec += 1;
538   EXPECT_FALSE(core_audio_utility::IsFormatSupported(
539       client.Get(), AUDCLNT_SHAREMODE_SHARED, &format));
540 }
541 
TEST_F(CoreAudioUtilityWinTest,GetDevicePeriod)542 TEST_F(CoreAudioUtilityWinTest, GetDevicePeriod) {
543   ABORT_TEST_IF_NOT(DevicesAvailable());
544 
545   EDataFlow data_flow[] = {eRender, eCapture};
546 
547   // Verify that the device periods are valid for the default render and
548   // capture devices.
549   ComPtr<IAudioClient> client;
550   for (size_t i = 0; i < arraysize(data_flow); ++i) {
551     REFERENCE_TIME shared_time_period = 0;
552     REFERENCE_TIME exclusive_time_period = 0;
553     client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
554                                               data_flow[i], eConsole);
555     EXPECT_TRUE(client.Get());
556     EXPECT_TRUE(SUCCEEDED(core_audio_utility::GetDevicePeriod(
557         client.Get(), AUDCLNT_SHAREMODE_SHARED, &shared_time_period)));
558     EXPECT_GT(shared_time_period, 0);
559     EXPECT_TRUE(SUCCEEDED(core_audio_utility::GetDevicePeriod(
560         client.Get(), AUDCLNT_SHAREMODE_EXCLUSIVE, &exclusive_time_period)));
561     EXPECT_GT(exclusive_time_period, 0);
562     EXPECT_LE(exclusive_time_period, shared_time_period);
563   }
564 }
565 
TEST_F(CoreAudioUtilityWinTest,GetPreferredAudioParameters)566 TEST_F(CoreAudioUtilityWinTest, GetPreferredAudioParameters) {
567   ABORT_TEST_IF_NOT(DevicesAvailable());
568 
569   struct {
570     EDataFlow flow;
571     ERole role;
572   } data[] = {{eRender, eConsole},
573               {eRender, eCommunications},
574               {eCapture, eConsole},
575               {eCapture, eCommunications}};
576 
577   // Verify that the preferred audio parameters are OK for all flow/role
578   // combinations above.
579   ComPtr<IAudioClient> client;
580   webrtc::AudioParameters params;
581   for (size_t i = 0; i < arraysize(data); ++i) {
582     client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
583                                               data[i].flow, data[i].role);
584     EXPECT_TRUE(client.Get());
585     EXPECT_TRUE(SUCCEEDED(core_audio_utility::GetPreferredAudioParameters(
586         client.Get(), &params)));
587     EXPECT_TRUE(params.is_valid());
588     EXPECT_TRUE(params.is_complete());
589   }
590 }
591 
TEST_F(CoreAudioUtilityWinTest,SharedModeInitialize)592 TEST_F(CoreAudioUtilityWinTest, SharedModeInitialize) {
593   ABORT_TEST_IF_NOT(DevicesAvailable());
594 
595   ComPtr<IAudioClient> client;
596   client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
597                                             eRender, eConsole);
598   EXPECT_TRUE(client.Get());
599 
600   WAVEFORMATPCMEX format;
601   EXPECT_TRUE(SUCCEEDED(
602       core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
603 
604   // Perform a shared-mode initialization without event-driven buffer handling.
605   uint32_t endpoint_buffer_size = 0;
606   HRESULT hr = core_audio_utility::SharedModeInitialize(
607       client.Get(), &format, nullptr, 0, false, &endpoint_buffer_size);
608   EXPECT_TRUE(SUCCEEDED(hr));
609   EXPECT_GT(endpoint_buffer_size, 0u);
610 
611   // It is only possible to create a client once.
612   hr = core_audio_utility::SharedModeInitialize(
613       client.Get(), &format, nullptr, 0, false, &endpoint_buffer_size);
614   EXPECT_FALSE(SUCCEEDED(hr));
615   EXPECT_EQ(hr, AUDCLNT_E_ALREADY_INITIALIZED);
616 
617   // Verify that it is possible to reinitialize the client after releasing it
618   // and then creating a new client.
619   client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
620                                             eRender, eConsole);
621   EXPECT_TRUE(client.Get());
622   hr = core_audio_utility::SharedModeInitialize(
623       client.Get(), &format, nullptr, 0, false, &endpoint_buffer_size);
624   EXPECT_TRUE(SUCCEEDED(hr));
625   EXPECT_GT(endpoint_buffer_size, 0u);
626 
627   // Use a non-supported format and verify that initialization fails.
628   // A simple way to emulate an invalid format is to use the shared-mode
629   // mixing format and modify the preferred sample rate.
630   client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
631                                             eRender, eConsole);
632   EXPECT_TRUE(client.Get());
633   format.Format.nSamplesPerSec = format.Format.nSamplesPerSec + 1;
634   EXPECT_FALSE(core_audio_utility::IsFormatSupported(
635       client.Get(), AUDCLNT_SHAREMODE_SHARED, &format));
636   hr = core_audio_utility::SharedModeInitialize(
637       client.Get(), &format, nullptr, 0, false, &endpoint_buffer_size);
638   EXPECT_TRUE(FAILED(hr));
639   EXPECT_EQ(hr, E_INVALIDARG);
640 
641   // Finally, perform a shared-mode initialization using event-driven buffer
642   // handling. The event handle will be signaled when an audio buffer is ready
643   // to be processed by the client (not verified here). The event handle should
644   // be in the non-signaled state.
645   ScopedHandle event_handle(::CreateEvent(nullptr, TRUE, FALSE, nullptr));
646   client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
647                                             eRender, eConsole);
648   EXPECT_TRUE(client.Get());
649   EXPECT_TRUE(SUCCEEDED(
650       core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
651   EXPECT_TRUE(core_audio_utility::IsFormatSupported(
652       client.Get(), AUDCLNT_SHAREMODE_SHARED, &format));
653   hr = core_audio_utility::SharedModeInitialize(
654       client.Get(), &format, event_handle, 0, false, &endpoint_buffer_size);
655   EXPECT_TRUE(SUCCEEDED(hr));
656   EXPECT_GT(endpoint_buffer_size, 0u);
657 
658   // TODO(henrika): possibly add test for signature which overrides the default
659   // sample rate.
660 }
661 
TEST_F(CoreAudioUtilityWinTest,CreateRenderAndCaptureClients)662 TEST_F(CoreAudioUtilityWinTest, CreateRenderAndCaptureClients) {
663   ABORT_TEST_IF_NOT(DevicesAvailable());
664 
665   EDataFlow data_flow[] = {eRender, eCapture};
666 
667   WAVEFORMATPCMEX format;
668   uint32_t endpoint_buffer_size = 0;
669 
670   for (size_t i = 0; i < arraysize(data_flow); ++i) {
671     ComPtr<IAudioClient> client;
672     ComPtr<IAudioRenderClient> render_client;
673     ComPtr<IAudioCaptureClient> capture_client;
674 
675     // Create a default client for the given data-flow direction.
676     client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
677                                               data_flow[i], eConsole);
678     EXPECT_TRUE(client.Get());
679     EXPECT_TRUE(SUCCEEDED(
680         core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
681     if (data_flow[i] == eRender) {
682       // It is not possible to create a render client using an unitialized
683       // client interface.
684       render_client = core_audio_utility::CreateRenderClient(client.Get());
685       EXPECT_FALSE(render_client.Get());
686 
687       // Do a proper initialization and verify that it works this time.
688       core_audio_utility::SharedModeInitialize(client.Get(), &format, nullptr,
689                                                0, false, &endpoint_buffer_size);
690       render_client = core_audio_utility::CreateRenderClient(client.Get());
691       EXPECT_TRUE(render_client.Get());
692       EXPECT_GT(endpoint_buffer_size, 0u);
693     } else if (data_flow[i] == eCapture) {
694       // It is not possible to create a capture client using an unitialized
695       // client interface.
696       capture_client = core_audio_utility::CreateCaptureClient(client.Get());
697       EXPECT_FALSE(capture_client.Get());
698 
699       // Do a proper initialization and verify that it works this time.
700       core_audio_utility::SharedModeInitialize(client.Get(), &format, nullptr,
701                                                0, false, &endpoint_buffer_size);
702       capture_client = core_audio_utility::CreateCaptureClient(client.Get());
703       EXPECT_TRUE(capture_client.Get());
704       EXPECT_GT(endpoint_buffer_size, 0u);
705     }
706   }
707 }
708 
TEST_F(CoreAudioUtilityWinTest,CreateAudioClock)709 TEST_F(CoreAudioUtilityWinTest, CreateAudioClock) {
710   ABORT_TEST_IF_NOT(DevicesAvailable());
711 
712   EDataFlow data_flow[] = {eRender, eCapture};
713 
714   WAVEFORMATPCMEX format;
715   uint32_t endpoint_buffer_size = 0;
716 
717   for (size_t i = 0; i < arraysize(data_flow); ++i) {
718     ComPtr<IAudioClient> client;
719     ComPtr<IAudioClock> audio_clock;
720 
721     // Create a default client for the given data-flow direction.
722     client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
723                                               data_flow[i], eConsole);
724     EXPECT_TRUE(client.Get());
725     EXPECT_TRUE(SUCCEEDED(
726         core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
727 
728     // It is not possible to create an audio clock using an unitialized client
729     // interface.
730     audio_clock = core_audio_utility::CreateAudioClock(client.Get());
731     EXPECT_FALSE(audio_clock.Get());
732 
733     // Do a proper initialization and verify that it works this time.
734     core_audio_utility::SharedModeInitialize(client.Get(), &format, nullptr, 0,
735                                              false, &endpoint_buffer_size);
736     audio_clock = core_audio_utility::CreateAudioClock(client.Get());
737     EXPECT_TRUE(audio_clock.Get());
738     EXPECT_GT(endpoint_buffer_size, 0u);
739 
740     // Use the audio clock and verify that querying the device frequency works.
741     UINT64 frequency = 0;
742     EXPECT_TRUE(SUCCEEDED(audio_clock->GetFrequency(&frequency)));
743     EXPECT_GT(frequency, 0u);
744   }
745 }
746 
TEST_F(CoreAudioUtilityWinTest,CreateAudioSessionControl)747 TEST_F(CoreAudioUtilityWinTest, CreateAudioSessionControl) {
748   ABORT_TEST_IF_NOT(DevicesAvailable());
749 
750   EDataFlow data_flow[] = {eRender, eCapture};
751 
752   WAVEFORMATPCMEX format;
753   uint32_t endpoint_buffer_size = 0;
754 
755   for (size_t i = 0; i < arraysize(data_flow); ++i) {
756     ComPtr<IAudioClient> client;
757     ComPtr<IAudioSessionControl> audio_session_control;
758 
759     // Create a default client for the given data-flow direction.
760     client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
761                                               data_flow[i], eConsole);
762     EXPECT_TRUE(client.Get());
763     EXPECT_TRUE(SUCCEEDED(
764         core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
765 
766     // It is not possible to create an audio session control using an
767     // unitialized client interface.
768     audio_session_control =
769         core_audio_utility::CreateAudioSessionControl(client.Get());
770     EXPECT_FALSE(audio_session_control.Get());
771 
772     // Do a proper initialization and verify that it works this time.
773     core_audio_utility::SharedModeInitialize(client.Get(), &format, nullptr, 0,
774                                              false, &endpoint_buffer_size);
775     audio_session_control =
776         core_audio_utility::CreateAudioSessionControl(client.Get());
777     EXPECT_TRUE(audio_session_control.Get());
778     EXPECT_GT(endpoint_buffer_size, 0u);
779 
780     // Use the audio session control and verify that the session state can be
781     // queried. When a client opens a session by assigning the first stream to
782     // the session (by calling the IAudioClient::Initialize method), the initial
783     // session state is inactive. The session state changes from inactive to
784     // active when a stream in the session begins running (because the client
785     // has called the IAudioClient::Start method).
786     AudioSessionState state;
787     EXPECT_TRUE(SUCCEEDED(audio_session_control->GetState(&state)));
788     EXPECT_EQ(state, AudioSessionStateInactive);
789   }
790 }
791 
TEST_F(CoreAudioUtilityWinTest,CreateSimpleAudioVolume)792 TEST_F(CoreAudioUtilityWinTest, CreateSimpleAudioVolume) {
793   ABORT_TEST_IF_NOT(DevicesAvailable());
794 
795   EDataFlow data_flow[] = {eRender, eCapture};
796 
797   WAVEFORMATPCMEX format;
798   uint32_t endpoint_buffer_size = 0;
799 
800   for (size_t i = 0; i < arraysize(data_flow); ++i) {
801     ComPtr<IAudioClient> client;
802     ComPtr<ISimpleAudioVolume> simple_audio_volume;
803 
804     // Create a default client for the given data-flow direction.
805     client = core_audio_utility::CreateClient(AudioDeviceName::kDefaultDeviceId,
806                                               data_flow[i], eConsole);
807     EXPECT_TRUE(client.Get());
808     EXPECT_TRUE(SUCCEEDED(
809         core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
810 
811     // It is not possible to create an audio volume using an uninitialized
812     // client interface.
813     simple_audio_volume =
814         core_audio_utility::CreateSimpleAudioVolume(client.Get());
815     EXPECT_FALSE(simple_audio_volume.Get());
816 
817     // Do a proper initialization and verify that it works this time.
818     core_audio_utility::SharedModeInitialize(client.Get(), &format, nullptr, 0,
819                                              false, &endpoint_buffer_size);
820     simple_audio_volume =
821         core_audio_utility::CreateSimpleAudioVolume(client.Get());
822     EXPECT_TRUE(simple_audio_volume.Get());
823     EXPECT_GT(endpoint_buffer_size, 0u);
824 
825     // Use the audio volume interface and validate that it works. The volume
826     // level should be value in the range 0.0 to 1.0 at first call.
827     float volume = 0.0;
828     EXPECT_TRUE(SUCCEEDED(simple_audio_volume->GetMasterVolume(&volume)));
829     EXPECT_GE(volume, 0.0);
830     EXPECT_LE(volume, 1.0);
831 
832     // Next, set a new volume and verify that the setter does its job.
833     const float target_volume = 0.5;
834     EXPECT_TRUE(SUCCEEDED(
835         simple_audio_volume->SetMasterVolume(target_volume, nullptr)));
836     EXPECT_TRUE(SUCCEEDED(simple_audio_volume->GetMasterVolume(&volume)));
837     EXPECT_EQ(volume, target_volume);
838   }
839 }
840 
TEST_F(CoreAudioUtilityWinTest,FillRenderEndpointBufferWithSilence)841 TEST_F(CoreAudioUtilityWinTest, FillRenderEndpointBufferWithSilence) {
842   ABORT_TEST_IF_NOT(DevicesAvailable());
843 
844   // Create default clients using the default mixing format for shared mode.
845   ComPtr<IAudioClient> client(core_audio_utility::CreateClient(
846       AudioDeviceName::kDefaultDeviceId, eRender, eConsole));
847   EXPECT_TRUE(client.Get());
848 
849   WAVEFORMATPCMEX format;
850   uint32_t endpoint_buffer_size = 0;
851   EXPECT_TRUE(SUCCEEDED(
852       core_audio_utility::GetSharedModeMixFormat(client.Get(), &format)));
853   core_audio_utility::SharedModeInitialize(client.Get(), &format, nullptr, 0,
854                                            false, &endpoint_buffer_size);
855   EXPECT_GT(endpoint_buffer_size, 0u);
856 
857   ComPtr<IAudioRenderClient> render_client(
858       core_audio_utility::CreateRenderClient(client.Get()));
859   EXPECT_TRUE(render_client.Get());
860 
861   // The endpoint audio buffer should not be filled up by default after being
862   // created.
863   UINT32 num_queued_frames = 0;
864   client->GetCurrentPadding(&num_queued_frames);
865   EXPECT_EQ(num_queued_frames, 0u);
866 
867   // Fill it up with zeros and verify that the buffer is full.
868   // It is not possible to verify that the actual data consists of zeros
869   // since we can't access data that has already been sent to the endpoint
870   // buffer.
871   EXPECT_TRUE(core_audio_utility::FillRenderEndpointBufferWithSilence(
872       client.Get(), render_client.Get()));
873   client->GetCurrentPadding(&num_queued_frames);
874   EXPECT_EQ(num_queued_frames, endpoint_buffer_size);
875 }
876 
877 }  // namespace webrtc_win
878 }  // namespace webrtc
879