| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/scoped_ptr.h" | 5 #include "base/memory/scoped_ptr.h" |
| 6 #include "base/strings/utf_string_conversions.h" | 6 #include "base/strings/utf_string_conversions.h" |
| 7 #include "base/synchronization/waitable_event.h" | 7 #include "base/synchronization/waitable_event.h" |
| 8 #include "base/win/scoped_co_mem.h" | 8 #include "base/win/scoped_co_mem.h" |
| 9 #include "base/win/scoped_com_initializer.h" | 9 #include "base/win/scoped_com_initializer.h" |
| 10 #include "base/win/scoped_handle.h" | 10 #include "base/win/scoped_handle.h" |
| 11 #include "media/audio/audio_unittest_utils.h" |
| 11 #include "media/audio/win/core_audio_util_win.h" | 12 #include "media/audio/win/core_audio_util_win.h" |
| 12 #include "testing/gmock/include/gmock/gmock.h" | 13 #include "testing/gmock/include/gmock/gmock.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 14 | 15 |
| 15 using base::win::ScopedCOMInitializer; | 16 using base::win::ScopedCOMInitializer; |
| 16 | 17 |
| 17 namespace media { | 18 namespace media { |
| 18 | 19 |
| 19 class CoreAudioUtilWinTest : public ::testing::Test { | 20 class CoreAudioUtilWinTest : public ::testing::Test { |
| 20 protected: | 21 protected: |
| 21 // The test runs on a COM thread in the multithreaded apartment (MTA). | 22 // The test runs on a COM thread in the multithreaded apartment (MTA). |
| 22 // If we don't initialize the COM library on a thread before using COM, | 23 // If we don't initialize the COM library on a thread before using COM, |
| 23 // all function calls will return CO_E_NOTINITIALIZED. | 24 // all function calls will return CO_E_NOTINITIALIZED. |
| 24 CoreAudioUtilWinTest() | 25 CoreAudioUtilWinTest() |
| 25 : com_init_(ScopedCOMInitializer::kMTA) { | 26 : com_init_(ScopedCOMInitializer::kMTA) |
| 26 DCHECK(com_init_.succeeded()); | 27 DCHECK(com_init_.succeeded()); |
| 27 } | 28 } |
| 28 virtual ~CoreAudioUtilWinTest() {} | 29 virtual ~CoreAudioUtilWinTest() {} |
| 29 | 30 |
| 30 bool CanRunAudioTest() { | 31 bool DevicesAvailable() { |
| 31 bool core_audio = CoreAudioUtil::IsSupported(); | 32 if (!CoreAudioUtil::IsSupported()) |
| 32 if (!core_audio) | |
| 33 return false; | 33 return false; |
| 34 int capture_devices = CoreAudioUtil::NumberOfActiveDevices(eCapture); | 34 return CoreAudioUtil::NumberOfActiveDevices(eCapture) > 0 && |
| 35 int render_devices = CoreAudioUtil::NumberOfActiveDevices(eRender); | 35 CoreAudioUtil::NumberOfActiveDevices(eRender) > 0; |
| 36 return ((capture_devices > 0) && (render_devices > 0)); | |
| 37 } | 36 } |
| 38 | 37 |
| 39 ScopedCOMInitializer com_init_; | 38 ScopedCOMInitializer com_init_; |
| 40 }; | 39 }; |
| 41 | 40 |
| 42 TEST_F(CoreAudioUtilWinTest, NumberOfActiveDevices) { | 41 TEST_F(CoreAudioUtilWinTest, NumberOfActiveDevices) { |
| 43 if (!CanRunAudioTest()) | 42 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 44 return; | |
| 45 | 43 |
| 46 int render_devices = CoreAudioUtil::NumberOfActiveDevices(eRender); | 44 int render_devices = CoreAudioUtil::NumberOfActiveDevices(eRender); |
| 47 EXPECT_GT(render_devices, 0); | 45 EXPECT_GT(render_devices, 0); |
| 48 int capture_devices = CoreAudioUtil::NumberOfActiveDevices(eCapture); | 46 int capture_devices = CoreAudioUtil::NumberOfActiveDevices(eCapture); |
| 49 EXPECT_GT(capture_devices, 0); | 47 EXPECT_GT(capture_devices, 0); |
| 50 int total_devices = CoreAudioUtil::NumberOfActiveDevices(eAll); | 48 int total_devices = CoreAudioUtil::NumberOfActiveDevices(eAll); |
| 51 EXPECT_EQ(total_devices, render_devices + capture_devices); | 49 EXPECT_EQ(total_devices, render_devices + capture_devices); |
| 52 } | 50 } |
| 53 | 51 |
| 54 TEST_F(CoreAudioUtilWinTest, CreateDeviceEnumerator) { | 52 TEST_F(CoreAudioUtilWinTest, CreateDeviceEnumerator) { |
| 55 if (!CanRunAudioTest()) | 53 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 56 return; | |
| 57 | 54 |
| 58 ScopedComPtr<IMMDeviceEnumerator> enumerator = | 55 ScopedComPtr<IMMDeviceEnumerator> enumerator = |
| 59 CoreAudioUtil::CreateDeviceEnumerator(); | 56 CoreAudioUtil::CreateDeviceEnumerator(); |
| 60 EXPECT_TRUE(enumerator.get()); | 57 EXPECT_TRUE(enumerator.get()); |
| 61 } | 58 } |
| 62 | 59 |
| 63 TEST_F(CoreAudioUtilWinTest, CreateDefaultDevice) { | 60 TEST_F(CoreAudioUtilWinTest, CreateDefaultDevice) { |
| 64 if (!CanRunAudioTest()) | 61 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 65 return; | |
| 66 | 62 |
| 67 struct { | 63 struct { |
| 68 EDataFlow flow; | 64 EDataFlow flow; |
| 69 ERole role; | 65 ERole role; |
| 70 } data[] = { | 66 } data[] = { |
| 71 {eRender, eConsole}, | 67 {eRender, eConsole}, |
| 72 {eRender, eCommunications}, | 68 {eRender, eCommunications}, |
| 73 {eRender, eMultimedia}, | 69 {eRender, eMultimedia}, |
| 74 {eCapture, eConsole}, | 70 {eCapture, eConsole}, |
| 75 {eCapture, eCommunications}, | 71 {eCapture, eCommunications}, |
| 76 {eCapture, eMultimedia} | 72 {eCapture, eMultimedia} |
| 77 }; | 73 }; |
| 78 | 74 |
| 79 // Create default devices for all flow/role combinations above. | 75 // Create default devices for all flow/role combinations above. |
| 80 ScopedComPtr<IMMDevice> audio_device; | 76 ScopedComPtr<IMMDevice> audio_device; |
| 81 for (int i = 0; i < arraysize(data); ++i) { | 77 for (int i = 0; i < arraysize(data); ++i) { |
| 82 audio_device = | 78 audio_device = |
| 83 CoreAudioUtil::CreateDefaultDevice(data[i].flow, data[i].role); | 79 CoreAudioUtil::CreateDefaultDevice(data[i].flow, data[i].role); |
| 84 EXPECT_TRUE(audio_device.get()); | 80 EXPECT_TRUE(audio_device.get()); |
| 85 EXPECT_EQ(data[i].flow, CoreAudioUtil::GetDataFlow(audio_device.get())); | 81 EXPECT_EQ(data[i].flow, CoreAudioUtil::GetDataFlow(audio_device.get())); |
| 86 } | 82 } |
| 87 | 83 |
| 88 // Only eRender and eCapture are allowed as flow parameter. | 84 // Only eRender and eCapture are allowed as flow parameter. |
| 89 audio_device = CoreAudioUtil::CreateDefaultDevice(eAll, eConsole); | 85 audio_device = CoreAudioUtil::CreateDefaultDevice(eAll, eConsole); |
| 90 EXPECT_FALSE(audio_device.get()); | 86 EXPECT_FALSE(audio_device.get()); |
| 91 } | 87 } |
| 92 | 88 |
| 93 TEST_F(CoreAudioUtilWinTest, CreateDevice) { | 89 TEST_F(CoreAudioUtilWinTest, CreateDevice) { |
| 94 if (!CanRunAudioTest()) | 90 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 95 return; | |
| 96 | 91 |
| 97 // Get name and ID of default device used for playback. | 92 // Get name and ID of default device used for playback. |
| 98 ScopedComPtr<IMMDevice> default_render_device = | 93 ScopedComPtr<IMMDevice> default_render_device = |
| 99 CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); | 94 CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); |
| 100 AudioDeviceName default_render_name; | 95 AudioDeviceName default_render_name; |
| 101 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDeviceName( | 96 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDeviceName( |
| 102 default_render_device.get(), &default_render_name))); | 97 default_render_device.get(), &default_render_name))); |
| 103 | 98 |
| 104 // Use the uniqe ID as input to CreateDevice() and create a corresponding | 99 // Use the uniqe ID as input to CreateDevice() and create a corresponding |
| 105 // IMMDevice. | 100 // IMMDevice. |
| 106 ScopedComPtr<IMMDevice> audio_device = | 101 ScopedComPtr<IMMDevice> audio_device = |
| 107 CoreAudioUtil::CreateDevice(default_render_name.unique_id); | 102 CoreAudioUtil::CreateDevice(default_render_name.unique_id); |
| 108 EXPECT_TRUE(audio_device.get()); | 103 EXPECT_TRUE(audio_device.get()); |
| 109 | 104 |
| 110 // Verify that the two IMMDevice interfaces represents the same endpoint | 105 // Verify that the two IMMDevice interfaces represents the same endpoint |
| 111 // by comparing their unique IDs. | 106 // by comparing their unique IDs. |
| 112 AudioDeviceName device_name; | 107 AudioDeviceName device_name; |
| 113 EXPECT_TRUE(SUCCEEDED( | 108 EXPECT_TRUE(SUCCEEDED( |
| 114 CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name))); | 109 CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name))); |
| 115 EXPECT_EQ(default_render_name.unique_id, device_name.unique_id); | 110 EXPECT_EQ(default_render_name.unique_id, device_name.unique_id); |
| 116 } | 111 } |
| 117 | 112 |
| 118 TEST_F(CoreAudioUtilWinTest, GetDefaultDeviceName) { | 113 TEST_F(CoreAudioUtilWinTest, GetDefaultDeviceName) { |
| 119 if (!CanRunAudioTest()) | 114 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 120 return; | |
| 121 | 115 |
| 122 struct { | 116 struct { |
| 123 EDataFlow flow; | 117 EDataFlow flow; |
| 124 ERole role; | 118 ERole role; |
| 125 } data[] = { | 119 } data[] = { |
| 126 {eRender, eConsole}, | 120 {eRender, eConsole}, |
| 127 {eRender, eCommunications}, | 121 {eRender, eCommunications}, |
| 128 {eCapture, eConsole}, | 122 {eCapture, eConsole}, |
| 129 {eCapture, eCommunications} | 123 {eCapture, eCommunications} |
| 130 }; | 124 }; |
| 131 | 125 |
| 132 // Get name and ID of default devices for all flow/role combinations above. | 126 // Get name and ID of default devices for all flow/role combinations above. |
| 133 ScopedComPtr<IMMDevice> audio_device; | 127 ScopedComPtr<IMMDevice> audio_device; |
| 134 AudioDeviceName device_name; | 128 AudioDeviceName device_name; |
| 135 for (int i = 0; i < arraysize(data); ++i) { | 129 for (int i = 0; i < arraysize(data); ++i) { |
| 136 audio_device = | 130 audio_device = |
| 137 CoreAudioUtil::CreateDefaultDevice(data[i].flow, data[i].role); | 131 CoreAudioUtil::CreateDefaultDevice(data[i].flow, data[i].role); |
| 138 EXPECT_TRUE(SUCCEEDED( | 132 EXPECT_TRUE(SUCCEEDED( |
| 139 CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name))); | 133 CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name))); |
| 140 EXPECT_FALSE(device_name.device_name.empty()); | 134 EXPECT_FALSE(device_name.device_name.empty()); |
| 141 EXPECT_FALSE(device_name.unique_id.empty()); | 135 EXPECT_FALSE(device_name.unique_id.empty()); |
| 142 } | 136 } |
| 143 } | 137 } |
| 144 | 138 |
| 145 TEST_F(CoreAudioUtilWinTest, GetAudioControllerID) { | 139 TEST_F(CoreAudioUtilWinTest, GetAudioControllerID) { |
| 146 if (!CanRunAudioTest()) | 140 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 147 return; | |
| 148 | 141 |
| 149 ScopedComPtr<IMMDeviceEnumerator> enumerator( | 142 ScopedComPtr<IMMDeviceEnumerator> enumerator( |
| 150 CoreAudioUtil::CreateDeviceEnumerator()); | 143 CoreAudioUtil::CreateDeviceEnumerator()); |
| 151 ASSERT_TRUE(enumerator.get()); | 144 ASSERT_TRUE(enumerator.get()); |
| 152 | 145 |
| 153 // Enumerate all active input and output devices and fetch the ID of | 146 // Enumerate all active input and output devices and fetch the ID of |
| 154 // the associated device. | 147 // the associated device. |
| 155 EDataFlow flows[] = { eRender , eCapture }; | 148 EDataFlow flows[] = { eRender , eCapture }; |
| 156 for (int i = 0; i < arraysize(flows); ++i) { | 149 for (int i = 0; i < arraysize(flows); ++i) { |
| 157 ScopedComPtr<IMMDeviceCollection> collection; | 150 ScopedComPtr<IMMDeviceCollection> collection; |
| 158 ASSERT_TRUE(SUCCEEDED(enumerator->EnumAudioEndpoints(flows[i], | 151 ASSERT_TRUE(SUCCEEDED(enumerator->EnumAudioEndpoints(flows[i], |
| 159 DEVICE_STATE_ACTIVE, collection.Receive()))); | 152 DEVICE_STATE_ACTIVE, collection.Receive()))); |
| 160 UINT count = 0; | 153 UINT count = 0; |
| 161 collection->GetCount(&count); | 154 collection->GetCount(&count); |
| 162 for (UINT j = 0; j < count; ++j) { | 155 for (UINT j = 0; j < count; ++j) { |
| 163 ScopedComPtr<IMMDevice> device; | 156 ScopedComPtr<IMMDevice> device; |
| 164 collection->Item(j, device.Receive()); | 157 collection->Item(j, device.Receive()); |
| 165 std::string controller_id( | 158 std::string controller_id( |
| 166 CoreAudioUtil::GetAudioControllerID(device.get(), enumerator.get())); | 159 CoreAudioUtil::GetAudioControllerID(device.get(), enumerator.get())); |
| 167 EXPECT_FALSE(controller_id.empty()); | 160 EXPECT_FALSE(controller_id.empty()); |
| 168 } | 161 } |
| 169 } | 162 } |
| 170 } | 163 } |
| 171 | 164 |
| 172 TEST_F(CoreAudioUtilWinTest, GetFriendlyName) { | 165 TEST_F(CoreAudioUtilWinTest, GetFriendlyName) { |
| 173 if (!CanRunAudioTest()) | 166 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 174 return; | |
| 175 | 167 |
| 176 // Get name and ID of default device used for recording. | 168 // Get name and ID of default device used for recording. |
| 177 ScopedComPtr<IMMDevice> audio_device = | 169 ScopedComPtr<IMMDevice> audio_device = |
| 178 CoreAudioUtil::CreateDefaultDevice(eCapture, eConsole); | 170 CoreAudioUtil::CreateDefaultDevice(eCapture, eConsole); |
| 179 AudioDeviceName device_name; | 171 AudioDeviceName device_name; |
| 180 HRESULT hr = CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name); | 172 HRESULT hr = CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name); |
| 181 EXPECT_TRUE(SUCCEEDED(hr)); | 173 EXPECT_TRUE(SUCCEEDED(hr)); |
| 182 | 174 |
| 183 // Use unique ID as input to GetFriendlyName() and compare the result | 175 // Use unique ID as input to GetFriendlyName() and compare the result |
| 184 // with the already obtained friendly name for the default capture device. | 176 // with the already obtained friendly name for the default capture device. |
| 185 std::string friendly_name = CoreAudioUtil::GetFriendlyName( | 177 std::string friendly_name = CoreAudioUtil::GetFriendlyName( |
| 186 device_name.unique_id); | 178 device_name.unique_id); |
| 187 EXPECT_EQ(friendly_name, device_name.device_name); | 179 EXPECT_EQ(friendly_name, device_name.device_name); |
| 188 | 180 |
| 189 // Same test as above but for playback. | 181 // Same test as above but for playback. |
| 190 audio_device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); | 182 audio_device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); |
| 191 hr = CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name); | 183 hr = CoreAudioUtil::GetDeviceName(audio_device.get(), &device_name); |
| 192 EXPECT_TRUE(SUCCEEDED(hr)); | 184 EXPECT_TRUE(SUCCEEDED(hr)); |
| 193 friendly_name = CoreAudioUtil::GetFriendlyName(device_name.unique_id); | 185 friendly_name = CoreAudioUtil::GetFriendlyName(device_name.unique_id); |
| 194 EXPECT_EQ(friendly_name, device_name.device_name); | 186 EXPECT_EQ(friendly_name, device_name.device_name); |
| 195 } | 187 } |
| 196 | 188 |
| 197 TEST_F(CoreAudioUtilWinTest, DeviceIsDefault) { | 189 TEST_F(CoreAudioUtilWinTest, DeviceIsDefault) { |
| 198 if (!CanRunAudioTest()) | 190 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 199 return; | |
| 200 | 191 |
| 201 // Verify that the default render device is correctly identified as a | 192 // Verify that the default render device is correctly identified as a |
| 202 // default device. | 193 // default device. |
| 203 ScopedComPtr<IMMDevice> audio_device = | 194 ScopedComPtr<IMMDevice> audio_device = |
| 204 CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); | 195 CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); |
| 205 AudioDeviceName name; | 196 AudioDeviceName name; |
| 206 EXPECT_TRUE( | 197 EXPECT_TRUE( |
| 207 SUCCEEDED(CoreAudioUtil::GetDeviceName(audio_device.get(), &name))); | 198 SUCCEEDED(CoreAudioUtil::GetDeviceName(audio_device.get(), &name))); |
| 208 const std::string id = name.unique_id; | 199 const std::string id = name.unique_id; |
| 209 EXPECT_TRUE(CoreAudioUtil::DeviceIsDefault(eRender, eConsole, id)); | 200 EXPECT_TRUE(CoreAudioUtil::DeviceIsDefault(eRender, eConsole, id)); |
| 210 EXPECT_FALSE(CoreAudioUtil::DeviceIsDefault(eCapture, eConsole, id)); | 201 EXPECT_FALSE(CoreAudioUtil::DeviceIsDefault(eCapture, eConsole, id)); |
| 211 } | 202 } |
| 212 | 203 |
| 213 TEST_F(CoreAudioUtilWinTest, CreateDefaultClient) { | 204 TEST_F(CoreAudioUtilWinTest, CreateDefaultClient) { |
| 214 if (!CanRunAudioTest()) | 205 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 215 return; | |
| 216 | 206 |
| 217 EDataFlow data[] = {eRender, eCapture}; | 207 EDataFlow data[] = {eRender, eCapture}; |
| 218 | 208 |
| 219 for (int i = 0; i < arraysize(data); ++i) { | 209 for (int i = 0; i < arraysize(data); ++i) { |
| 220 ScopedComPtr<IAudioClient> client; | 210 ScopedComPtr<IAudioClient> client; |
| 221 client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); | 211 client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); |
| 222 EXPECT_TRUE(client.get()); | 212 EXPECT_TRUE(client.get()); |
| 223 } | 213 } |
| 224 } | 214 } |
| 225 | 215 |
| 226 TEST_F(CoreAudioUtilWinTest, CreateClient) { | 216 TEST_F(CoreAudioUtilWinTest, CreateClient) { |
| 227 if (!CanRunAudioTest()) | 217 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 228 return; | |
| 229 | 218 |
| 230 EDataFlow data[] = {eRender, eCapture}; | 219 EDataFlow data[] = {eRender, eCapture}; |
| 231 | 220 |
| 232 for (int i = 0; i < arraysize(data); ++i) { | 221 for (int i = 0; i < arraysize(data); ++i) { |
| 233 ScopedComPtr<IMMDevice> device; | 222 ScopedComPtr<IMMDevice> device; |
| 234 ScopedComPtr<IAudioClient> client; | 223 ScopedComPtr<IAudioClient> client; |
| 235 device = CoreAudioUtil::CreateDefaultDevice(data[i], eConsole); | 224 device = CoreAudioUtil::CreateDefaultDevice(data[i], eConsole); |
| 236 EXPECT_TRUE(device.get()); | 225 EXPECT_TRUE(device.get()); |
| 237 EXPECT_EQ(data[i], CoreAudioUtil::GetDataFlow(device.get())); | 226 EXPECT_EQ(data[i], CoreAudioUtil::GetDataFlow(device.get())); |
| 238 client = CoreAudioUtil::CreateClient(device.get()); | 227 client = CoreAudioUtil::CreateClient(device.get()); |
| 239 EXPECT_TRUE(client.get()); | 228 EXPECT_TRUE(client.get()); |
| 240 } | 229 } |
| 241 } | 230 } |
| 242 | 231 |
| 243 TEST_F(CoreAudioUtilWinTest, GetSharedModeMixFormat) { | 232 TEST_F(CoreAudioUtilWinTest, GetSharedModeMixFormat) { |
| 244 if (!CanRunAudioTest()) | 233 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 245 return; | |
| 246 | 234 |
| 247 ScopedComPtr<IMMDevice> device; | 235 ScopedComPtr<IMMDevice> device; |
| 248 ScopedComPtr<IAudioClient> client; | 236 ScopedComPtr<IAudioClient> client; |
| 249 device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); | 237 device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); |
| 250 EXPECT_TRUE(device.get()); | 238 EXPECT_TRUE(device.get()); |
| 251 client = CoreAudioUtil::CreateClient(device.get()); | 239 client = CoreAudioUtil::CreateClient(device.get()); |
| 252 EXPECT_TRUE(client.get()); | 240 EXPECT_TRUE(client.get()); |
| 253 | 241 |
| 254 // Perform a simple sanity test of the aquired format structure. | 242 // Perform a simple sanity test of the aquired format structure. |
| 255 WAVEFORMATPCMEX format; | 243 WAVEFORMATPCMEX format; |
| 256 EXPECT_TRUE( | 244 EXPECT_TRUE( |
| 257 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); | 245 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); |
| 258 EXPECT_GE(format.Format.nChannels, 1); | 246 EXPECT_GE(format.Format.nChannels, 1); |
| 259 EXPECT_GE(format.Format.nSamplesPerSec, 8000u); | 247 EXPECT_GE(format.Format.nSamplesPerSec, 8000u); |
| 260 EXPECT_GE(format.Format.wBitsPerSample, 16); | 248 EXPECT_GE(format.Format.wBitsPerSample, 16); |
| 261 EXPECT_GE(format.Samples.wValidBitsPerSample, 16); | 249 EXPECT_GE(format.Samples.wValidBitsPerSample, 16); |
| 262 EXPECT_EQ(format.Format.wFormatTag, WAVE_FORMAT_EXTENSIBLE); | 250 EXPECT_EQ(format.Format.wFormatTag, WAVE_FORMAT_EXTENSIBLE); |
| 263 } | 251 } |
| 264 | 252 |
| 265 TEST_F(CoreAudioUtilWinTest, IsChannelLayoutSupported) { | 253 TEST_F(CoreAudioUtilWinTest, IsChannelLayoutSupported) { |
| 266 if (!CanRunAudioTest()) | 254 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 267 return; | |
| 268 | 255 |
| 269 // The preferred channel layout should always be supported. Being supported | 256 // The preferred channel layout should always be supported. Being supported |
| 270 // means that it is possible to initialize a shared mode stream with the | 257 // means that it is possible to initialize a shared mode stream with the |
| 271 // particular channel layout. | 258 // particular channel layout. |
| 272 AudioParameters mix_params; | 259 AudioParameters mix_params; |
| 273 HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(eRender, eConsole, | 260 HRESULT hr = CoreAudioUtil::GetPreferredAudioParameters(eRender, eConsole, |
| 274 &mix_params); | 261 &mix_params); |
| 275 EXPECT_TRUE(SUCCEEDED(hr)); | 262 EXPECT_TRUE(SUCCEEDED(hr)); |
| 276 EXPECT_TRUE(mix_params.IsValid()); | 263 EXPECT_TRUE(mix_params.IsValid()); |
| 277 EXPECT_TRUE(CoreAudioUtil::IsChannelLayoutSupported( | 264 EXPECT_TRUE(CoreAudioUtil::IsChannelLayoutSupported( |
| 278 std::string(), eRender, eConsole, mix_params.channel_layout())); | 265 std::string(), eRender, eConsole, mix_params.channel_layout())); |
| 279 | 266 |
| 280 // Check if it is possible to modify the channel layout to stereo for a | 267 // Check if it is possible to modify the channel layout to stereo for a |
| 281 // device which reports that it prefers to be openen up in an other | 268 // device which reports that it prefers to be openen up in an other |
| 282 // channel configuration. | 269 // channel configuration. |
| 283 if (mix_params.channel_layout() != CHANNEL_LAYOUT_STEREO) { | 270 if (mix_params.channel_layout() != CHANNEL_LAYOUT_STEREO) { |
| 284 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; | 271 ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; |
| 285 // TODO(henrika): it might be too pessimistic to assume false as return | 272 // TODO(henrika): it might be too pessimistic to assume false as return |
| 286 // value here. | 273 // value here. |
| 287 EXPECT_FALSE(CoreAudioUtil::IsChannelLayoutSupported( | 274 EXPECT_FALSE(CoreAudioUtil::IsChannelLayoutSupported( |
| 288 std::string(), eRender, eConsole, channel_layout)); | 275 std::string(), eRender, eConsole, channel_layout)); |
| 289 } | 276 } |
| 290 } | 277 } |
| 291 | 278 |
| 292 TEST_F(CoreAudioUtilWinTest, GetDevicePeriod) { | 279 TEST_F(CoreAudioUtilWinTest, GetDevicePeriod) { |
| 293 if (!CanRunAudioTest()) | 280 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 294 return; | |
| 295 | 281 |
| 296 EDataFlow data[] = {eRender, eCapture}; | 282 EDataFlow data[] = {eRender, eCapture}; |
| 297 | 283 |
| 298 // Verify that the device periods are valid for the default render and | 284 // Verify that the device periods are valid for the default render and |
| 299 // capture devices. | 285 // capture devices. |
| 300 for (int i = 0; i < arraysize(data); ++i) { | 286 for (int i = 0; i < arraysize(data); ++i) { |
| 301 ScopedComPtr<IAudioClient> client; | 287 ScopedComPtr<IAudioClient> client; |
| 302 REFERENCE_TIME shared_time_period = 0; | 288 REFERENCE_TIME shared_time_period = 0; |
| 303 REFERENCE_TIME exclusive_time_period = 0; | 289 REFERENCE_TIME exclusive_time_period = 0; |
| 304 client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); | 290 client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); |
| 305 EXPECT_TRUE(client.get()); | 291 EXPECT_TRUE(client.get()); |
| 306 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDevicePeriod( | 292 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDevicePeriod( |
| 307 client.get(), AUDCLNT_SHAREMODE_SHARED, &shared_time_period))); | 293 client.get(), AUDCLNT_SHAREMODE_SHARED, &shared_time_period))); |
| 308 EXPECT_GT(shared_time_period, 0); | 294 EXPECT_GT(shared_time_period, 0); |
| 309 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDevicePeriod( | 295 EXPECT_TRUE(SUCCEEDED(CoreAudioUtil::GetDevicePeriod( |
| 310 client.get(), AUDCLNT_SHAREMODE_EXCLUSIVE, &exclusive_time_period))); | 296 client.get(), AUDCLNT_SHAREMODE_EXCLUSIVE, &exclusive_time_period))); |
| 311 EXPECT_GT(exclusive_time_period, 0); | 297 EXPECT_GT(exclusive_time_period, 0); |
| 312 EXPECT_LE(exclusive_time_period, shared_time_period); | 298 EXPECT_LE(exclusive_time_period, shared_time_period); |
| 313 } | 299 } |
| 314 } | 300 } |
| 315 | 301 |
| 316 TEST_F(CoreAudioUtilWinTest, GetPreferredAudioParameters) { | 302 TEST_F(CoreAudioUtilWinTest, GetPreferredAudioParameters) { |
| 317 if (!CanRunAudioTest()) | 303 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 318 return; | |
| 319 | 304 |
| 320 EDataFlow data[] = {eRender, eCapture}; | 305 EDataFlow data[] = {eRender, eCapture}; |
| 321 | 306 |
| 322 // Verify that the preferred audio parameters are OK for the default render | 307 // Verify that the preferred audio parameters are OK for the default render |
| 323 // and capture devices. | 308 // and capture devices. |
| 324 for (int i = 0; i < arraysize(data); ++i) { | 309 for (int i = 0; i < arraysize(data); ++i) { |
| 325 ScopedComPtr<IAudioClient> client; | 310 ScopedComPtr<IAudioClient> client; |
| 326 AudioParameters params; | 311 AudioParameters params; |
| 327 client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); | 312 client = CoreAudioUtil::CreateDefaultClient(data[i], eConsole); |
| 328 EXPECT_TRUE(client.get()); | 313 EXPECT_TRUE(client.get()); |
| 329 EXPECT_TRUE(SUCCEEDED( | 314 EXPECT_TRUE(SUCCEEDED( |
| 330 CoreAudioUtil::GetPreferredAudioParameters(client.get(), ¶ms))); | 315 CoreAudioUtil::GetPreferredAudioParameters(client.get(), ¶ms))); |
| 331 EXPECT_TRUE(params.IsValid()); | 316 EXPECT_TRUE(params.IsValid()); |
| 332 } | 317 } |
| 333 } | 318 } |
| 334 | 319 |
| 335 TEST_F(CoreAudioUtilWinTest, SharedModeInitialize) { | 320 TEST_F(CoreAudioUtilWinTest, SharedModeInitialize) { |
| 336 if (!CanRunAudioTest()) | 321 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 337 return; | |
| 338 | 322 |
| 339 ScopedComPtr<IAudioClient> client; | 323 ScopedComPtr<IAudioClient> client; |
| 340 client = CoreAudioUtil::CreateDefaultClient(eRender, eConsole); | 324 client = CoreAudioUtil::CreateDefaultClient(eRender, eConsole); |
| 341 EXPECT_TRUE(client.get()); | 325 EXPECT_TRUE(client.get()); |
| 342 | 326 |
| 343 WAVEFORMATPCMEX format; | 327 WAVEFORMATPCMEX format; |
| 344 EXPECT_TRUE( | 328 EXPECT_TRUE( |
| 345 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); | 329 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); |
| 346 | 330 |
| 347 // Perform a shared-mode initialization without event-driven buffer handling. | 331 // Perform a shared-mode initialization without event-driven buffer handling. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); | 373 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); |
| 390 EXPECT_TRUE(CoreAudioUtil::IsFormatSupported( | 374 EXPECT_TRUE(CoreAudioUtil::IsFormatSupported( |
| 391 client.get(), AUDCLNT_SHAREMODE_SHARED, &format)); | 375 client.get(), AUDCLNT_SHAREMODE_SHARED, &format)); |
| 392 hr = CoreAudioUtil::SharedModeInitialize( | 376 hr = CoreAudioUtil::SharedModeInitialize( |
| 393 client.get(), &format, event_handle.Get(), &endpoint_buffer_size, NULL); | 377 client.get(), &format, event_handle.Get(), &endpoint_buffer_size, NULL); |
| 394 EXPECT_TRUE(SUCCEEDED(hr)); | 378 EXPECT_TRUE(SUCCEEDED(hr)); |
| 395 EXPECT_GT(endpoint_buffer_size, 0u); | 379 EXPECT_GT(endpoint_buffer_size, 0u); |
| 396 } | 380 } |
| 397 | 381 |
| 398 TEST_F(CoreAudioUtilWinTest, CreateRenderAndCaptureClients) { | 382 TEST_F(CoreAudioUtilWinTest, CreateRenderAndCaptureClients) { |
| 399 if (!CanRunAudioTest()) | 383 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 400 return; | |
| 401 | 384 |
| 402 EDataFlow data[] = {eRender, eCapture}; | 385 EDataFlow data[] = {eRender, eCapture}; |
| 403 | 386 |
| 404 WAVEFORMATPCMEX format; | 387 WAVEFORMATPCMEX format; |
| 405 uint32 endpoint_buffer_size = 0; | 388 uint32 endpoint_buffer_size = 0; |
| 406 | 389 |
| 407 for (int i = 0; i < arraysize(data); ++i) { | 390 for (int i = 0; i < arraysize(data); ++i) { |
| 408 ScopedComPtr<IAudioClient> client; | 391 ScopedComPtr<IAudioClient> client; |
| 409 ScopedComPtr<IAudioRenderClient> render_client; | 392 ScopedComPtr<IAudioRenderClient> render_client; |
| 410 ScopedComPtr<IAudioCaptureClient> capture_client; | 393 ScopedComPtr<IAudioCaptureClient> capture_client; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 435 CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, | 418 CoreAudioUtil::SharedModeInitialize(client.get(), &format, NULL, |
| 436 &endpoint_buffer_size, NULL); | 419 &endpoint_buffer_size, NULL); |
| 437 capture_client = CoreAudioUtil::CreateCaptureClient(client.get()); | 420 capture_client = CoreAudioUtil::CreateCaptureClient(client.get()); |
| 438 EXPECT_TRUE(capture_client.get()); | 421 EXPECT_TRUE(capture_client.get()); |
| 439 EXPECT_GT(endpoint_buffer_size, 0u); | 422 EXPECT_GT(endpoint_buffer_size, 0u); |
| 440 } | 423 } |
| 441 } | 424 } |
| 442 } | 425 } |
| 443 | 426 |
| 444 TEST_F(CoreAudioUtilWinTest, FillRenderEndpointBufferWithSilence) { | 427 TEST_F(CoreAudioUtilWinTest, FillRenderEndpointBufferWithSilence) { |
| 445 if (!CanRunAudioTest()) | 428 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 446 return; | |
| 447 | 429 |
| 448 // Create default clients using the default mixing format for shared mode. | 430 // Create default clients using the default mixing format for shared mode. |
| 449 ScopedComPtr<IAudioClient> client( | 431 ScopedComPtr<IAudioClient> client( |
| 450 CoreAudioUtil::CreateDefaultClient(eRender, eConsole)); | 432 CoreAudioUtil::CreateDefaultClient(eRender, eConsole)); |
| 451 EXPECT_TRUE(client.get()); | 433 EXPECT_TRUE(client.get()); |
| 452 | 434 |
| 453 WAVEFORMATPCMEX format; | 435 WAVEFORMATPCMEX format; |
| 454 uint32 endpoint_buffer_size = 0; | 436 uint32 endpoint_buffer_size = 0; |
| 455 EXPECT_TRUE( | 437 EXPECT_TRUE( |
| 456 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); | 438 SUCCEEDED(CoreAudioUtil::GetSharedModeMixFormat(client.get(), &format))); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 471 // Fill it up with zeros and verify that the buffer is full. | 453 // Fill it up with zeros and verify that the buffer is full. |
| 472 // It is not possible to verify that the actual data consists of zeros | 454 // It is not possible to verify that the actual data consists of zeros |
| 473 // since we can't access data that has already been sent to the endpoint | 455 // since we can't access data that has already been sent to the endpoint |
| 474 // buffer. | 456 // buffer. |
| 475 EXPECT_TRUE(CoreAudioUtil::FillRenderEndpointBufferWithSilence( | 457 EXPECT_TRUE(CoreAudioUtil::FillRenderEndpointBufferWithSilence( |
| 476 client.get(), render_client.get())); | 458 client.get(), render_client.get())); |
| 477 client->GetCurrentPadding(&num_queued_frames); | 459 client->GetCurrentPadding(&num_queued_frames); |
| 478 EXPECT_EQ(num_queued_frames, endpoint_buffer_size); | 460 EXPECT_EQ(num_queued_frames, endpoint_buffer_size); |
| 479 } | 461 } |
| 480 | 462 |
| 481 // This test can only succeed on a machine that has audio hardware | 463 // This test can only run on a machine that has audio hardware |
| 482 // that has both input and output devices. Currently this is the case | 464 // that has both input and output devices. |
| 483 // with our test bots and the CanRunAudioTest() method should make sure | |
| 484 // that the test won't run in unsupported environments, but be warned. | |
| 485 TEST_F(CoreAudioUtilWinTest, GetMatchingOutputDeviceID) { | 465 TEST_F(CoreAudioUtilWinTest, GetMatchingOutputDeviceID) { |
| 486 if (!CanRunAudioTest()) | 466 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 487 return; | |
| 488 | 467 |
| 489 bool found_a_pair = false; | 468 bool found_a_pair = false; |
| 490 | 469 |
| 491 ScopedComPtr<IMMDeviceEnumerator> enumerator( | 470 ScopedComPtr<IMMDeviceEnumerator> enumerator( |
| 492 CoreAudioUtil::CreateDeviceEnumerator()); | 471 CoreAudioUtil::CreateDeviceEnumerator()); |
| 493 ASSERT_TRUE(enumerator.get()); | 472 ASSERT_TRUE(enumerator.get()); |
| 494 | 473 |
| 495 // Enumerate all active input and output devices and fetch the ID of | 474 // Enumerate all active input and output devices and fetch the ID of |
| 496 // the associated device. | 475 // the associated device. |
| 497 ScopedComPtr<IMMDeviceCollection> collection; | 476 ScopedComPtr<IMMDeviceCollection> collection; |
| 498 ASSERT_TRUE(SUCCEEDED(enumerator->EnumAudioEndpoints(eCapture, | 477 ASSERT_TRUE(SUCCEEDED(enumerator->EnumAudioEndpoints(eCapture, |
| 499 DEVICE_STATE_ACTIVE, collection.Receive()))); | 478 DEVICE_STATE_ACTIVE, collection.Receive()))); |
| 500 UINT count = 0; | 479 UINT count = 0; |
| 501 collection->GetCount(&count); | 480 collection->GetCount(&count); |
| 502 for (UINT i = 0; i < count && !found_a_pair; ++i) { | 481 for (UINT i = 0; i < count && !found_a_pair; ++i) { |
| 503 ScopedComPtr<IMMDevice> device; | 482 ScopedComPtr<IMMDevice> device; |
| 504 collection->Item(i, device.Receive()); | 483 collection->Item(i, device.Receive()); |
| 505 base::win::ScopedCoMem<WCHAR> wide_id; | 484 base::win::ScopedCoMem<WCHAR> wide_id; |
| 506 device->GetId(&wide_id); | 485 device->GetId(&wide_id); |
| 507 std::string id; | 486 std::string id; |
| 508 base::WideToUTF8(wide_id, wcslen(wide_id), &id); | 487 base::WideToUTF8(wide_id, wcslen(wide_id), &id); |
| 509 found_a_pair = !CoreAudioUtil::GetMatchingOutputDeviceID(id).empty(); | 488 found_a_pair = !CoreAudioUtil::GetMatchingOutputDeviceID(id).empty(); |
| 510 } | 489 } |
| 511 | 490 |
| 512 EXPECT_TRUE(found_a_pair); | 491 EXPECT_TRUE(found_a_pair); |
| 513 } | 492 } |
| 514 | 493 |
| 515 TEST_F(CoreAudioUtilWinTest, GetDefaultOutputDeviceID) { | 494 TEST_F(CoreAudioUtilWinTest, GetDefaultOutputDeviceID) { |
| 516 if (!CanRunAudioTest()) | 495 ABORT_AUDIO_TEST_IF_NOT(DevicesAvailable()); |
| 517 return; | |
| 518 | 496 |
| 519 std::string default_device_id(CoreAudioUtil::GetDefaultOutputDeviceID()); | 497 std::string default_device_id(CoreAudioUtil::GetDefaultOutputDeviceID()); |
| 520 EXPECT_FALSE(default_device_id.empty()); | 498 EXPECT_FALSE(default_device_id.empty()); |
| 521 } | 499 } |
| 522 | 500 |
| 523 } // namespace media | 501 } // namespace media |
| OLD | NEW |