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

Side by Side Diff: media/audio/win/core_audio_util_win.cc

Issue 23523023: Add GetOutputStreamParameters, GetAssociatedOutputDeviceID to AudioManager. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 3 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
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 "media/audio/win/core_audio_util_win.h" 5 #include "media/audio/win/core_audio_util_win.h"
6 6
7 #include <audioclient.h> 7 #include <audioclient.h>
8 #include <devicetopology.h> 8 #include <devicetopology.h>
9 #include <functiondiscoverykeys_devpkey.h> 9 #include <functiondiscoverykeys_devpkey.h>
10 10
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 << ", nSamplesPerSec: " << format.Format.nSamplesPerSec 116 << ", nSamplesPerSec: " << format.Format.nSamplesPerSec
117 << ", nAvgBytesPerSec: " << format.Format.nAvgBytesPerSec 117 << ", nAvgBytesPerSec: " << format.Format.nAvgBytesPerSec
118 << ", nBlockAlign: " << format.Format.nBlockAlign 118 << ", nBlockAlign: " << format.Format.nBlockAlign
119 << ", wBitsPerSample: " << format.Format.wBitsPerSample 119 << ", wBitsPerSample: " << format.Format.wBitsPerSample
120 << ", cbSize: " << format.Format.cbSize 120 << ", cbSize: " << format.Format.cbSize
121 << ", wValidBitsPerSample: " << format.Samples.wValidBitsPerSample 121 << ", wValidBitsPerSample: " << format.Samples.wValidBitsPerSample
122 << ", dwChannelMask: 0x" << std::hex << format.dwChannelMask; 122 << ", dwChannelMask: 0x" << std::hex << format.dwChannelMask;
123 return os; 123 return os;
124 } 124 }
125 125
126 bool LoadAudiosesDll() { 126 static bool LoadAudiosesDll() {
127 static const wchar_t* const kAudiosesDLL = 127 static const wchar_t* const kAudiosesDLL =
128 L"%WINDIR%\\system32\\audioses.dll"; 128 L"%WINDIR%\\system32\\audioses.dll";
129 129
130 wchar_t path[MAX_PATH] = {0}; 130 wchar_t path[MAX_PATH] = {0};
131 ExpandEnvironmentStringsW(kAudiosesDLL, path, arraysize(path)); 131 ExpandEnvironmentStringsW(kAudiosesDLL, path, arraysize(path));
132 return (LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) != NULL); 132 return (LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) != NULL);
133 } 133 }
134 134
135 bool CanCreateDeviceEnumerator() { 135 static bool CanCreateDeviceEnumerator() {
136 ScopedComPtr<IMMDeviceEnumerator> device_enumerator; 136 ScopedComPtr<IMMDeviceEnumerator> device_enumerator;
137 HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), 137 HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator),
138 NULL, CLSCTX_INPROC_SERVER); 138 NULL, CLSCTX_INPROC_SERVER);
139 139
140 // If we hit CO_E_NOTINITIALIZED, CoInitialize has not been called and it 140 // If we hit CO_E_NOTINITIALIZED, CoInitialize has not been called and it
141 // must be called at least once for each thread that uses the COM library. 141 // must be called at least once for each thread that uses the COM library.
142 CHECK_NE(hr, CO_E_NOTINITIALIZED); 142 CHECK_NE(hr, CO_E_NOTINITIALIZED);
143 143
144 return SUCCEEDED(hr); 144 return SUCCEEDED(hr);
145 } 145 }
146 146
147 static std::string GetDeviceID(IMMDevice* device) {
148 ScopedCoMem<WCHAR> device_id_com;
149 std::string device_id;
150 if (SUCCEEDED(device->GetId(&device_id_com)))
151 WideToUTF8(device_id_com, wcslen(device_id_com), &device_id);
152 return device_id;
153 }
154
147 bool CoreAudioUtil::IsSupported() { 155 bool CoreAudioUtil::IsSupported() {
148 // It is possible to force usage of WaveXxx APIs by using a command line flag. 156 // It is possible to force usage of WaveXxx APIs by using a command line flag.
149 const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); 157 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
150 if (cmd_line->HasSwitch(switches::kForceWaveAudio)) { 158 if (cmd_line->HasSwitch(switches::kForceWaveAudio)) {
151 LOG(WARNING) << "Forcing usage of Windows WaveXxx APIs"; 159 LOG(WARNING) << "Forcing usage of Windows WaveXxx APIs";
152 return false; 160 return false;
153 } 161 }
154 162
155 // Microsoft does not plan to make the Core Audio APIs available for use 163 // Microsoft does not plan to make the Core Audio APIs available for use
156 // with earlier versions of Windows, including Microsoft Windows Server 2003, 164 // with earlier versions of Windows, including Microsoft Windows Server 2003,
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
256 hr = endpoint_device->GetState(&state); 264 hr = endpoint_device->GetState(&state);
257 if (SUCCEEDED(hr)) { 265 if (SUCCEEDED(hr)) {
258 if (!(state & DEVICE_STATE_ACTIVE)) { 266 if (!(state & DEVICE_STATE_ACTIVE)) {
259 DVLOG(1) << "Selected endpoint device is not active"; 267 DVLOG(1) << "Selected endpoint device is not active";
260 endpoint_device.Release(); 268 endpoint_device.Release();
261 } 269 }
262 } 270 }
263 return endpoint_device; 271 return endpoint_device;
264 } 272 }
265 273
274 std::string CoreAudioUtil::GetDefaultOutputDeviceID() {
275 DCHECK(IsSupported());
276 ScopedComPtr<IMMDevice> device(CreateDefaultDevice(eRender, eConsole));
277 return device ? GetDeviceID(device) : std::string();
278 }
279
266 ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDevice( 280 ScopedComPtr<IMMDevice> CoreAudioUtil::CreateDevice(
267 const std::string& device_id) { 281 const std::string& device_id) {
268 DCHECK(IsSupported()); 282 DCHECK(IsSupported());
269 ScopedComPtr<IMMDevice> endpoint_device; 283 ScopedComPtr<IMMDevice> endpoint_device;
270 284
271 // Create the IMMDeviceEnumerator interface. 285 // Create the IMMDeviceEnumerator interface.
272 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = 286 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
273 CreateDeviceEnumerator(); 287 CreateDeviceEnumerator();
274 if (!device_enumerator) 288 if (!device_enumerator)
275 return endpoint_device; 289 return endpoint_device;
276 290
277 // Retrieve an audio device specified by an endpoint device-identification 291 // Retrieve an audio device specified by an endpoint device-identification
278 // string. 292 // string.
279 HRESULT hr = device_enumerator->GetDevice(UTF8ToUTF16(device_id).c_str(), 293 HRESULT hr = device_enumerator->GetDevice(UTF8ToUTF16(device_id).c_str(),
280 endpoint_device.Receive()); 294 endpoint_device.Receive());
281 DVLOG_IF(1, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: " 295 DVLOG_IF(1, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: "
282 << std::hex << hr; 296 << std::hex << hr;
283 return endpoint_device; 297 return endpoint_device;
284 } 298 }
285 299
286 HRESULT CoreAudioUtil::GetDeviceName(IMMDevice* device, AudioDeviceName* name) { 300 HRESULT CoreAudioUtil::GetDeviceName(IMMDevice* device, AudioDeviceName* name) {
287 DCHECK(IsSupported()); 301 DCHECK(IsSupported());
288 302
289 // Retrieve unique name of endpoint device. 303 // Retrieve unique name of endpoint device.
290 // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}". 304 // Example: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}".
291 AudioDeviceName device_name; 305 AudioDeviceName device_name;
292 ScopedCoMem<WCHAR> endpoint_device_id; 306 device_name.unique_id = GetDeviceID(device);
henrika (OOO until Aug 14) 2013/09/04 11:11:40 nice
293 HRESULT hr = device->GetId(&endpoint_device_id); 307 if (device_name.unique_id.empty())
294 if (FAILED(hr)) 308 return E_FAIL;
295 return hr;
296 WideToUTF8(endpoint_device_id, wcslen(endpoint_device_id),
297 &device_name.unique_id);
298 309
299 // Retrieve user-friendly name of endpoint device. 310 // Retrieve user-friendly name of endpoint device.
300 // Example: "Microphone (Realtek High Definition Audio)". 311 // Example: "Microphone (Realtek High Definition Audio)".
301 ScopedComPtr<IPropertyStore> properties; 312 ScopedComPtr<IPropertyStore> properties;
302 hr = device->OpenPropertyStore(STGM_READ, properties.Receive()); 313 HRESULT hr = device->OpenPropertyStore(STGM_READ, properties.Receive());
303 if (FAILED(hr)) 314 if (FAILED(hr))
304 return hr; 315 return hr;
305 base::win::ScopedPropVariant friendly_name; 316 base::win::ScopedPropVariant friendly_name;
306 hr = properties->GetValue(PKEY_Device_FriendlyName, friendly_name.Receive()); 317 hr = properties->GetValue(PKEY_Device_FriendlyName, friendly_name.Receive());
307 if (FAILED(hr)) 318 if (FAILED(hr))
308 return hr; 319 return hr;
309 if (friendly_name.get().vt == VT_LPWSTR && friendly_name.get().pwszVal) { 320 if (friendly_name.get().vt == VT_LPWSTR && friendly_name.get().pwszVal) {
310 WideToUTF8(friendly_name.get().pwszVal, 321 WideToUTF8(friendly_name.get().pwszVal,
311 wcslen(friendly_name.get().pwszVal), 322 wcslen(friendly_name.get().pwszVal),
312 &device_name.device_name); 323 &device_name.device_name);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 ScopedComPtr<IMMDevice> output_device; 401 ScopedComPtr<IMMDevice> output_device;
391 for (UINT i = 0; i < count; ++i) { 402 for (UINT i = 0; i < count; ++i) {
392 collection->Item(i, output_device.Receive()); 403 collection->Item(i, output_device.Receive());
393 std::string output_controller_id(CoreAudioUtil::GetAudioControllerID( 404 std::string output_controller_id(CoreAudioUtil::GetAudioControllerID(
394 output_device, enumerator)); 405 output_device, enumerator));
395 if (output_controller_id == controller_id) 406 if (output_controller_id == controller_id)
396 break; 407 break;
397 output_device = NULL; 408 output_device = NULL;
398 } 409 }
399 410
400 std::string id; 411 return output_device ? GetDeviceID(output_device) : std::string();
401 if (output_device) {
402 ScopedCoMem<WCHAR> wide_id;
403 output_device->GetId(&wide_id);
404 WideToUTF8(wide_id, wcslen(wide_id), &id);
405 }
406
407 return id;
408 } 412 }
409 413
410 std::string CoreAudioUtil::GetFriendlyName(const std::string& device_id) { 414 std::string CoreAudioUtil::GetFriendlyName(const std::string& device_id) {
411 DCHECK(IsSupported()); 415 DCHECK(IsSupported());
412 ScopedComPtr<IMMDevice> audio_device = CreateDevice(device_id); 416 ScopedComPtr<IMMDevice> audio_device = CreateDevice(device_id);
413 if (!audio_device) 417 if (!audio_device)
414 return std::string(); 418 return std::string();
415 419
416 AudioDeviceName device_name; 420 AudioDeviceName device_name;
417 HRESULT hr = GetDeviceName(audio_device, &device_name); 421 HRESULT hr = GetDeviceName(audio_device, &device_name);
418 if (FAILED(hr)) 422 if (FAILED(hr))
419 return std::string(); 423 return std::string();
420 424
421 return device_name.device_name; 425 return device_name.device_name;
422 } 426 }
423 427
424 bool CoreAudioUtil::DeviceIsDefault(EDataFlow flow, 428 bool CoreAudioUtil::DeviceIsDefault(EDataFlow flow,
425 ERole role, 429 ERole role,
426 const std::string& device_id) { 430 const std::string& device_id) {
427 DCHECK(IsSupported()); 431 DCHECK(IsSupported());
428 ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role); 432 ScopedComPtr<IMMDevice> device = CreateDefaultDevice(flow, role);
429 if (!device) 433 if (!device)
430 return false; 434 return false;
431 435
432 ScopedCoMem<WCHAR> default_device_id; 436 std::string str_default(GetDeviceID(device));
433 HRESULT hr = device->GetId(&default_device_id); 437 return device_id.compare(str_default) == 0;
434 if (FAILED(hr))
435 return false;
436
437 std::string str_default;
438 WideToUTF8(default_device_id, wcslen(default_device_id), &str_default);
439 if (device_id.compare(str_default) != 0)
440 return false;
441 return true;
442 } 438 }
443 439
444 EDataFlow CoreAudioUtil::GetDataFlow(IMMDevice* device) { 440 EDataFlow CoreAudioUtil::GetDataFlow(IMMDevice* device) {
445 DCHECK(IsSupported()); 441 DCHECK(IsSupported());
446 ScopedComPtr<IMMEndpoint> endpoint; 442 ScopedComPtr<IMMEndpoint> endpoint;
447 HRESULT hr = device->QueryInterface(endpoint.Receive()); 443 HRESULT hr = device->QueryInterface(endpoint.Receive());
448 if (FAILED(hr)) { 444 if (FAILED(hr)) {
449 DVLOG(1) << "IMMDevice::QueryInterface: " << std::hex << hr; 445 DVLOG(1) << "IMMDevice::QueryInterface: " << std::hex << hr;
450 return eAll; 446 return eAll;
451 } 447 }
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 return false; 795 return false;
800 796
801 // Using the AUDCLNT_BUFFERFLAGS_SILENT flag eliminates the need to 797 // Using the AUDCLNT_BUFFERFLAGS_SILENT flag eliminates the need to
802 // explicitly write silence data to the rendering buffer. 798 // explicitly write silence data to the rendering buffer.
803 DVLOG(2) << "filling up " << num_frames_to_fill << " frames with silence"; 799 DVLOG(2) << "filling up " << num_frames_to_fill << " frames with silence";
804 return SUCCEEDED(render_client->ReleaseBuffer(num_frames_to_fill, 800 return SUCCEEDED(render_client->ReleaseBuffer(num_frames_to_fill,
805 AUDCLNT_BUFFERFLAGS_SILENT)); 801 AUDCLNT_BUFFERFLAGS_SILENT));
806 } 802 }
807 803
808 } // namespace media 804 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698