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

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

Issue 2144333002: MuteSource Audio During Full Screen Cast (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Run Git Cl Format Created 4 years, 5 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 <devicetopology.h> 7 #include <devicetopology.h>
8 #include <dxdiag.h> 8 #include <dxdiag.h>
9 #include <functiondiscoverykeys_devpkey.h> 9 #include <functiondiscoverykeys_devpkey.h>
10 #include <stddef.h> 10 #include <stddef.h>
(...skipping 12 matching lines...) Expand all
23 #include "media/base/media_switches.h" 23 #include "media/base/media_switches.h"
24 24
25 using base::win::ScopedCoMem; 25 using base::win::ScopedCoMem;
26 using base::win::ScopedHandle; 26 using base::win::ScopedHandle;
27 27
28 namespace media { 28 namespace media {
29 29
30 // See header file for documentation. 30 // See header file for documentation.
31 // {BE39AF4F-087C-423F-9303-234EC1E5B8EE} 31 // {BE39AF4F-087C-423F-9303-234EC1E5B8EE}
32 const GUID kCommunicationsSessionId = { 32 const GUID kCommunicationsSessionId = {
33 0xbe39af4f, 0x87c, 0x423f, { 0x93, 0x3, 0x23, 0x4e, 0xc1, 0xe5, 0xb8, 0xee } 33 0xbe39af4f,
34 }; 34 0x87c,
35 0x423f,
36 {0x93, 0x3, 0x23, 0x4e, 0xc1, 0xe5, 0xb8, 0xee}};
35 37
36 enum { KSAUDIO_SPEAKER_UNSUPPORTED = 0 }; 38 enum { KSAUDIO_SPEAKER_UNSUPPORTED = 0 };
37 39
38 // Converts Microsoft's channel configuration to ChannelLayout. 40 // Converts Microsoft's channel configuration to ChannelLayout.
39 // This mapping is not perfect but the best we can do given the current 41 // This mapping is not perfect but the best we can do given the current
40 // ChannelLayout enumerator and the Windows-specific speaker configurations 42 // ChannelLayout enumerator and the Windows-specific speaker configurations
41 // defined in ksmedia.h. Don't assume that the channel ordering in 43 // defined in ksmedia.h. Don't assume that the channel ordering in
42 // ChannelLayout is exactly the same as the Windows specific configuration. 44 // ChannelLayout is exactly the same as the Windows specific configuration.
43 // As an example: KSAUDIO_SPEAKER_7POINT1_SURROUND is mapped to 45 // As an example: KSAUDIO_SPEAKER_7POINT1_SURROUND is mapped to
44 // CHANNEL_LAYOUT_7_1 but the positions of Back L, Back R and Side L, Side R 46 // CHANNEL_LAYOUT_7_1 but the positions of Back L, Back R and Side L, Side R
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), 190 HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator),
189 NULL, CLSCTX_INPROC_SERVER); 191 NULL, CLSCTX_INPROC_SERVER);
190 if (hr == CO_E_NOTINITIALIZED && allow_reinitialize) { 192 if (hr == CO_E_NOTINITIALIZED && allow_reinitialize) {
191 LOG(ERROR) << "CoCreateInstance fails with CO_E_NOTINITIALIZED"; 193 LOG(ERROR) << "CoCreateInstance fails with CO_E_NOTINITIALIZED";
192 // We have seen crashes which indicates that this method can in fact 194 // We have seen crashes which indicates that this method can in fact
193 // fail with CO_E_NOTINITIALIZED in combination with certain 3rd party 195 // fail with CO_E_NOTINITIALIZED in combination with certain 3rd party
194 // modules. Calling CoInitializeEx is an attempt to resolve the reported 196 // modules. Calling CoInitializeEx is an attempt to resolve the reported
195 // issues. See http://crbug.com/378465 for details. 197 // issues. See http://crbug.com/378465 for details.
196 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 198 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
197 if (SUCCEEDED(hr)) { 199 if (SUCCEEDED(hr)) {
198 hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), 200 hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), NULL,
199 NULL, CLSCTX_INPROC_SERVER); 201 CLSCTX_INPROC_SERVER);
200 } 202 }
201 } 203 }
202 return device_enumerator; 204 return device_enumerator;
203 } 205 }
204 206
205 static bool IsSupportedInternal() { 207 static bool IsSupportedInternal() {
206 // It is possible to force usage of WaveXxx APIs by using a command line flag. 208 // It is possible to force usage of WaveXxx APIs by using a command line flag.
207 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); 209 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
208 if (cmd_line->HasSwitch(switches::kForceWaveAudio)) { 210 if (cmd_line->HasSwitch(switches::kForceWaveAudio)) {
209 DVLOG(1) << "Forcing usage of Windows WaveXxx APIs"; 211 DVLOG(1) << "Forcing usage of Windows WaveXxx APIs";
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 // Create the IMMDeviceEnumerator interface. 265 // Create the IMMDeviceEnumerator interface.
264 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = 266 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
265 CreateDeviceEnumerator(); 267 CreateDeviceEnumerator();
266 if (!device_enumerator.get()) 268 if (!device_enumerator.get())
267 return 0; 269 return 0;
268 270
269 // Generate a collection of active (present and not disabled) audio endpoint 271 // Generate a collection of active (present and not disabled) audio endpoint
270 // devices for the specified data-flow direction. 272 // devices for the specified data-flow direction.
271 // This method will succeed even if all devices are disabled. 273 // This method will succeed even if all devices are disabled.
272 ScopedComPtr<IMMDeviceCollection> collection; 274 ScopedComPtr<IMMDeviceCollection> collection;
273 HRESULT hr = device_enumerator->EnumAudioEndpoints(data_flow, 275 HRESULT hr = device_enumerator->EnumAudioEndpoints(
274 DEVICE_STATE_ACTIVE, 276 data_flow, DEVICE_STATE_ACTIVE, collection.Receive());
275 collection.Receive());
276 if (FAILED(hr)) { 277 if (FAILED(hr)) {
277 LOG(ERROR) << "IMMDeviceCollection::EnumAudioEndpoints: " << std::hex << hr; 278 LOG(ERROR) << "IMMDeviceCollection::EnumAudioEndpoints: " << std::hex << hr;
278 return 0; 279 return 0;
279 } 280 }
280 281
281 // Retrieve the number of active audio devices for the specified direction 282 // Retrieve the number of active audio devices for the specified direction
282 UINT number_of_active_devices = 0; 283 UINT number_of_active_devices = 0;
283 collection->GetCount(&number_of_active_devices); 284 collection->GetCount(&number_of_active_devices);
284 DVLOG(2) << ((data_flow == eCapture) ? "[in ] " : "[out] ") 285 DVLOG(2) << ((data_flow == eCapture) ? "[in ] " : "[out] ")
285 << "number of devices: " << number_of_active_devices; 286 << "number of devices: " << number_of_active_devices;
(...skipping 18 matching lines...) Expand all
304 CreateDeviceEnumerator(); 305 CreateDeviceEnumerator();
305 if (!device_enumerator.get()) 306 if (!device_enumerator.get())
306 return endpoint_device; 307 return endpoint_device;
307 308
308 // Retrieve the default audio endpoint for the specified data-flow 309 // Retrieve the default audio endpoint for the specified data-flow
309 // direction and role. 310 // direction and role.
310 HRESULT hr = device_enumerator->GetDefaultAudioEndpoint( 311 HRESULT hr = device_enumerator->GetDefaultAudioEndpoint(
311 data_flow, role, endpoint_device.Receive()); 312 data_flow, role, endpoint_device.Receive());
312 313
313 if (FAILED(hr)) { 314 if (FAILED(hr)) {
314 DVLOG(1) << "IMMDeviceEnumerator::GetDefaultAudioEndpoint: " 315 DVLOG(1) << "IMMDeviceEnumerator::GetDefaultAudioEndpoint: " << std::hex
315 << std::hex << hr; 316 << hr;
316 return endpoint_device; 317 return endpoint_device;
317 } 318 }
318 319
319 // Verify that the audio endpoint device is active, i.e., that the audio 320 // Verify that the audio endpoint device is active, i.e., that the audio
320 // adapter that connects to the endpoint device is present and enabled. 321 // adapter that connects to the endpoint device is present and enabled.
321 if (!IsDeviceActive(endpoint_device.get())) { 322 if (!IsDeviceActive(endpoint_device.get())) {
322 DVLOG(1) << "Selected endpoint device is not active"; 323 DVLOG(1) << "Selected endpoint device is not active";
323 endpoint_device.Release(); 324 endpoint_device.Release();
324 } 325 }
325 return endpoint_device; 326 return endpoint_device;
(...skipping 13 matching lines...) Expand all
339 // Create the IMMDeviceEnumerator interface. 340 // Create the IMMDeviceEnumerator interface.
340 ScopedComPtr<IMMDeviceEnumerator> device_enumerator = 341 ScopedComPtr<IMMDeviceEnumerator> device_enumerator =
341 CreateDeviceEnumerator(); 342 CreateDeviceEnumerator();
342 if (!device_enumerator.get()) 343 if (!device_enumerator.get())
343 return endpoint_device; 344 return endpoint_device;
344 345
345 // Retrieve an audio device specified by an endpoint device-identification 346 // Retrieve an audio device specified by an endpoint device-identification
346 // string. 347 // string.
347 HRESULT hr = device_enumerator->GetDevice( 348 HRESULT hr = device_enumerator->GetDevice(
348 base::UTF8ToUTF16(device_id).c_str(), endpoint_device.Receive()); 349 base::UTF8ToUTF16(device_id).c_str(), endpoint_device.Receive());
349 DVLOG_IF(1, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: " 350 DVLOG_IF(1, FAILED(hr)) << "IMMDeviceEnumerator::GetDevice: " << std::hex
350 << std::hex << hr; 351 << hr;
351 352
352 if (FAILED(hr)) { 353 if (FAILED(hr)) {
353 DVLOG(1) << "IMMDeviceEnumerator::GetDevice: " << std::hex << hr; 354 DVLOG(1) << "IMMDeviceEnumerator::GetDevice: " << std::hex << hr;
354 return endpoint_device; 355 return endpoint_device;
355 } 356 }
356 357
357 // Verify that the audio endpoint device is active, i.e., that the audio 358 // Verify that the audio endpoint device is active, i.e., that the audio
358 // adapter that connects to the endpoint device is present and enabled. 359 // adapter that connects to the endpoint device is present and enabled.
359 if (!IsDeviceActive(endpoint_device.get())) { 360 if (!IsDeviceActive(endpoint_device.get())) {
360 DVLOG(1) << "Selected endpoint device is not active"; 361 DVLOG(1) << "Selected endpoint device is not active";
(...skipping 15 matching lines...) Expand all
376 HRESULT hr = GetDeviceFriendlyNameInternal(device, &device_name.device_name); 377 HRESULT hr = GetDeviceFriendlyNameInternal(device, &device_name.device_name);
377 if (FAILED(hr)) 378 if (FAILED(hr))
378 return hr; 379 return hr;
379 380
380 *name = device_name; 381 *name = device_name;
381 DVLOG(2) << "friendly name: " << device_name.device_name; 382 DVLOG(2) << "friendly name: " << device_name.device_name;
382 DVLOG(2) << "unique id : " << device_name.unique_id; 383 DVLOG(2) << "unique id : " << device_name.unique_id;
383 return hr; 384 return hr;
384 } 385 }
385 386
386 std::string CoreAudioUtil::GetAudioControllerID(IMMDevice* device, 387 std::string CoreAudioUtil::GetAudioControllerID(
388 IMMDevice* device,
387 IMMDeviceEnumerator* enumerator) { 389 IMMDeviceEnumerator* enumerator) {
388 DCHECK(IsSupported()); 390 DCHECK(IsSupported());
389 391
390 // Fetching the controller device id could be as simple as fetching the value 392 // Fetching the controller device id could be as simple as fetching the value
391 // of the "{B3F8FA53-0004-438E-9003-51A46E139BFC},2" property in the property 393 // of the "{B3F8FA53-0004-438E-9003-51A46E139BFC},2" property in the property
392 // store of the |device|, but that key isn't defined in any header and 394 // store of the |device|, but that key isn't defined in any header and
393 // according to MS should not be relied upon. 395 // according to MS should not be relied upon.
394 // So, instead, we go deeper, look at the device topology and fetch the 396 // So, instead, we go deeper, look at the device topology and fetch the
395 // PKEY_Device_InstanceId of the associated physical audio device. 397 // PKEY_Device_InstanceId of the associated physical audio device.
396 ScopedComPtr<IDeviceTopology> topology; 398 ScopedComPtr<IDeviceTopology> topology;
397 ScopedComPtr<IConnector> connector; 399 ScopedComPtr<IConnector> connector;
398 ScopedCoMem<WCHAR> filter_id; 400 ScopedCoMem<WCHAR> filter_id;
399 if (FAILED(device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL, 401 if (FAILED(device->Activate(__uuidof(IDeviceTopology), CLSCTX_ALL, NULL,
400 topology.ReceiveVoid())) || 402 topology.ReceiveVoid())) ||
401 // For our purposes checking the first connected device should be enough 403 // For our purposes checking the first connected device should be enough
402 // and if there are cases where there are more than one device connected 404 // and if there are cases where there are more than one device connected
403 // we're not sure how to handle that anyway. So we pass 0. 405 // we're not sure how to handle that anyway. So we pass 0.
404 FAILED(topology->GetConnector(0, connector.Receive())) || 406 FAILED(topology->GetConnector(0, connector.Receive())) ||
405 FAILED(connector->GetDeviceIdConnectedTo(&filter_id))) { 407 FAILED(connector->GetDeviceIdConnectedTo(&filter_id))) {
406 DLOG(ERROR) << "Failed to get the device identifier of the audio device"; 408 DLOG(ERROR) << "Failed to get the device identifier of the audio device";
407 return std::string(); 409 return std::string();
408 } 410 }
409 411
410 // Now look at the properties of the connected device node and fetch the 412 // Now look at the properties of the connected device node and fetch the
411 // instance id (PKEY_Device_InstanceId) of the device node that uniquely 413 // instance id (PKEY_Device_InstanceId) of the device node that uniquely
412 // identifies the controller. 414 // identifies the controller.
413 ScopedComPtr<IMMDevice> device_node; 415 ScopedComPtr<IMMDevice> device_node;
414 ScopedComPtr<IPropertyStore> properties; 416 ScopedComPtr<IPropertyStore> properties;
415 base::win::ScopedPropVariant instance_id; 417 base::win::ScopedPropVariant instance_id;
416 if (FAILED(enumerator->GetDevice(filter_id, device_node.Receive())) || 418 if (FAILED(enumerator->GetDevice(filter_id, device_node.Receive())) ||
417 FAILED(device_node->OpenPropertyStore(STGM_READ, properties.Receive())) || 419 FAILED(device_node->OpenPropertyStore(STGM_READ, properties.Receive())) ||
418 FAILED(properties->GetValue(PKEY_Device_InstanceId, 420 FAILED(properties->GetValue(PKEY_Device_InstanceId,
419 instance_id.Receive())) || 421 instance_id.Receive())) ||
420 instance_id.get().vt != VT_LPWSTR) { 422 instance_id.get().vt != VT_LPWSTR) {
421 DLOG(ERROR) << "Failed to get instance id of the audio device node"; 423 DLOG(ERROR) << "Failed to get instance id of the audio device node";
422 return std::string(); 424 return std::string();
423 } 425 }
424 426
425 std::string controller_id; 427 std::string controller_id;
426 base::WideToUTF8(instance_id.get().pwszVal, 428 base::WideToUTF8(instance_id.get().pwszVal, wcslen(instance_id.get().pwszVal),
427 wcslen(instance_id.get().pwszVal),
428 &controller_id); 429 &controller_id);
429 430
430 return controller_id; 431 return controller_id;
431 } 432 }
432 433
433 std::string CoreAudioUtil::GetMatchingOutputDeviceID( 434 std::string CoreAudioUtil::GetMatchingOutputDeviceID(
434 const std::string& input_device_id) { 435 const std::string& input_device_id) {
435 // Special handling for the default communications device. 436 // Special handling for the default communications device.
436 // We always treat the configured communications devices, as a pair. 437 // We always treat the configured communications devices, as a pair.
437 // If we didn't do that and the user has e.g. configured a mic of a headset 438 // If we didn't do that and the user has e.g. configured a mic of a headset
(...skipping 20 matching lines...) Expand all
458 ScopedComPtr<IMMDeviceEnumerator> enumerator(CreateDeviceEnumerator()); 459 ScopedComPtr<IMMDeviceEnumerator> enumerator(CreateDeviceEnumerator());
459 std::string controller_id( 460 std::string controller_id(
460 GetAudioControllerID(input_device.get(), enumerator.get())); 461 GetAudioControllerID(input_device.get(), enumerator.get()));
461 if (controller_id.empty()) 462 if (controller_id.empty())
462 return std::string(); 463 return std::string();
463 464
464 // Now enumerate the available (and active) output devices and see if any of 465 // Now enumerate the available (and active) output devices and see if any of
465 // them is associated with the same controller. 466 // them is associated with the same controller.
466 ScopedComPtr<IMMDeviceCollection> collection; 467 ScopedComPtr<IMMDeviceCollection> collection;
467 enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, 468 enumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE,
468 collection.Receive()); 469 collection.Receive());
469 if (!collection.get()) 470 if (!collection.get())
470 return std::string(); 471 return std::string();
471 472
472 UINT count = 0; 473 UINT count = 0;
473 collection->GetCount(&count); 474 collection->GetCount(&count);
474 ScopedComPtr<IMMDevice> output_device; 475 ScopedComPtr<IMMDevice> output_device;
475 for (UINT i = 0; i < count; ++i) { 476 for (UINT i = 0; i < count; ++i) {
476 collection->Item(i, output_device.Receive()); 477 collection->Item(i, output_device.Receive());
477 std::string output_controller_id( 478 std::string output_controller_id(
478 GetAudioControllerID(output_device.get(), enumerator.get())); 479 GetAudioControllerID(output_device.get(), enumerator.get()));
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
528 return data_flow; 529 return data_flow;
529 } 530 }
530 531
531 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient( 532 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient(
532 IMMDevice* audio_device) { 533 IMMDevice* audio_device) {
533 DCHECK(IsSupported()); 534 DCHECK(IsSupported());
534 535
535 // Creates and activates an IAudioClient COM object given the selected 536 // Creates and activates an IAudioClient COM object given the selected
536 // endpoint device. 537 // endpoint device.
537 ScopedComPtr<IAudioClient> audio_client; 538 ScopedComPtr<IAudioClient> audio_client;
538 HRESULT hr = audio_device->Activate(__uuidof(IAudioClient), 539 HRESULT hr =
539 CLSCTX_INPROC_SERVER, 540 audio_device->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL,
540 NULL, 541 audio_client.ReceiveVoid());
541 audio_client.ReceiveVoid());
542 DVLOG_IF(1, FAILED(hr)) << "IMMDevice::Activate: " << std::hex << hr; 542 DVLOG_IF(1, FAILED(hr)) << "IMMDevice::Activate: " << std::hex << hr;
543 return audio_client; 543 return audio_client;
544 } 544 }
545 545
546 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateDefaultClient( 546 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateDefaultClient(
547 EDataFlow data_flow, ERole role) { 547 EDataFlow data_flow,
548 ERole role) {
548 DCHECK(IsSupported()); 549 DCHECK(IsSupported());
549 ScopedComPtr<IMMDevice> default_device(CreateDefaultDevice(data_flow, role)); 550 ScopedComPtr<IMMDevice> default_device(CreateDefaultDevice(data_flow, role));
550 return (default_device.get() ? CreateClient(default_device.get()) 551 return (default_device.get() ? CreateClient(default_device.get())
551 : ScopedComPtr<IAudioClient>()); 552 : ScopedComPtr<IAudioClient>());
552 } 553 }
553 554
554 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient( 555 ScopedComPtr<IAudioClient> CoreAudioUtil::CreateClient(
555 const std::string& device_id, EDataFlow data_flow, ERole role) { 556 const std::string& device_id,
557 EDataFlow data_flow,
558 ERole role) {
556 if (IsDefaultDeviceId(device_id)) 559 if (IsDefaultDeviceId(device_id))
557 return CreateDefaultClient(data_flow, role); 560 return CreateDefaultClient(data_flow, role);
558 561
559 ScopedComPtr<IMMDevice> device(CreateDevice(device_id)); 562 ScopedComPtr<IMMDevice> device(CreateDevice(device_id));
560 if (!device.get()) 563 if (!device.get())
561 return ScopedComPtr<IAudioClient>(); 564 return ScopedComPtr<IAudioClient>();
562 565
563 return CreateClient(device.get()); 566 return CreateClient(device.get());
564 } 567 }
565 568
566 HRESULT CoreAudioUtil::GetSharedModeMixFormat( 569 HRESULT CoreAudioUtil::GetSharedModeMixFormat(IAudioClient* client,
567 IAudioClient* client, WAVEFORMATPCMEX* format) { 570 WAVEFORMATPCMEX* format) {
568 DCHECK(IsSupported()); 571 DCHECK(IsSupported());
569 ScopedCoMem<WAVEFORMATPCMEX> format_pcmex; 572 ScopedCoMem<WAVEFORMATPCMEX> format_pcmex;
570 HRESULT hr = client->GetMixFormat( 573 HRESULT hr =
571 reinterpret_cast<WAVEFORMATEX**>(&format_pcmex)); 574 client->GetMixFormat(reinterpret_cast<WAVEFORMATEX**>(&format_pcmex));
572 if (FAILED(hr)) 575 if (FAILED(hr))
573 return hr; 576 return hr;
574 577
575 size_t bytes = sizeof(WAVEFORMATEX) + format_pcmex->Format.cbSize; 578 size_t bytes = sizeof(WAVEFORMATEX) + format_pcmex->Format.cbSize;
576 DCHECK_EQ(bytes, sizeof(WAVEFORMATPCMEX)); 579 DCHECK_EQ(bytes, sizeof(WAVEFORMATPCMEX));
577 580
578 memcpy(format, format_pcmex, bytes); 581 memcpy(format, format_pcmex, bytes);
579 DVLOG(2) << *format; 582 DVLOG(2) << *format;
580 583
581 return hr; 584 return hr;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 return false; 631 return false;
629 } 632 }
630 format.dwChannelMask = new_config; 633 format.dwChannelMask = new_config;
631 634
632 // Modify the format if the new channel layout has changed the number of 635 // Modify the format if the new channel layout has changed the number of
633 // utilized channels. 636 // utilized channels.
634 const int channels = ChannelLayoutToChannelCount(channel_layout); 637 const int channels = ChannelLayoutToChannelCount(channel_layout);
635 if (channels != format.Format.nChannels) { 638 if (channels != format.Format.nChannels) {
636 format.Format.nChannels = channels; 639 format.Format.nChannels = channels;
637 format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * channels; 640 format.Format.nBlockAlign = (format.Format.wBitsPerSample / 8) * channels;
638 format.Format.nAvgBytesPerSec = format.Format.nSamplesPerSec * 641 format.Format.nAvgBytesPerSec =
639 format.Format.nBlockAlign; 642 format.Format.nSamplesPerSec * format.Format.nBlockAlign;
640 } 643 }
641 DVLOG(2) << format; 644 DVLOG(2) << format;
642 645
643 // Some devices can initialize a shared-mode stream with a format that is 646 // Some devices can initialize a shared-mode stream with a format that is
644 // not identical to the mix format obtained from the GetMixFormat() method. 647 // not identical to the mix format obtained from the GetMixFormat() method.
645 // However, chances of succeeding increases if we use the same number of 648 // However, chances of succeeding increases if we use the same number of
646 // channels and the same sample rate as the mix format. I.e, this call will 649 // channels and the same sample rate as the mix format. I.e, this call will
647 // return true only in those cases where the audio engine is able to support 650 // return true only in those cases where the audio engine is able to support
648 // an even wider range of shared-mode formats where the installation package 651 // an even wider range of shared-mode formats where the installation package
649 // for the audio device includes a local effects (LFX) audio processing 652 // for the audio device includes a local effects (LFX) audio processing
650 // object (APO) that can handle format conversions. 653 // object (APO) that can handle format conversions.
651 return CoreAudioUtil::IsFormatSupported(client.get(), 654 return CoreAudioUtil::IsFormatSupported(client.get(),
652 AUDCLNT_SHAREMODE_SHARED, &format); 655 AUDCLNT_SHAREMODE_SHARED, &format);
653 } 656 }
654 657
655 HRESULT CoreAudioUtil::GetDevicePeriod(IAudioClient* client, 658 HRESULT CoreAudioUtil::GetDevicePeriod(IAudioClient* client,
656 AUDCLNT_SHAREMODE share_mode, 659 AUDCLNT_SHAREMODE share_mode,
657 REFERENCE_TIME* device_period) { 660 REFERENCE_TIME* device_period) {
658 DCHECK(IsSupported()); 661 DCHECK(IsSupported());
659 662
660 // Get the period of the engine thread. 663 // Get the period of the engine thread.
661 REFERENCE_TIME default_period = 0; 664 REFERENCE_TIME default_period = 0;
662 REFERENCE_TIME minimum_period = 0; 665 REFERENCE_TIME minimum_period = 0;
663 HRESULT hr = client->GetDevicePeriod(&default_period, &minimum_period); 666 HRESULT hr = client->GetDevicePeriod(&default_period, &minimum_period);
664 if (FAILED(hr)) 667 if (FAILED(hr))
665 return hr; 668 return hr;
666 669
667 *device_period = (share_mode == AUDCLNT_SHAREMODE_SHARED) ? default_period : 670 *device_period = (share_mode == AUDCLNT_SHAREMODE_SHARED) ? default_period
668 minimum_period; 671 : minimum_period;
669 DVLOG(2) << "device_period: " 672 DVLOG(2) << "device_period: "
670 << RefererenceTimeToTimeDelta(*device_period).InMillisecondsF() 673 << RefererenceTimeToTimeDelta(*device_period).InMillisecondsF()
671 << " [ms]"; 674 << " [ms]";
672 return hr; 675 return hr;
673 } 676 }
674 677
675 HRESULT CoreAudioUtil::GetPreferredAudioParameters( 678 HRESULT CoreAudioUtil::GetPreferredAudioParameters(IAudioClient* client,
676 IAudioClient* client, AudioParameters* params) { 679 AudioParameters* params) {
677 DCHECK(IsSupported()); 680 DCHECK(IsSupported());
678 WAVEFORMATPCMEX mix_format; 681 WAVEFORMATPCMEX mix_format;
679 HRESULT hr = GetSharedModeMixFormat(client, &mix_format); 682 HRESULT hr = GetSharedModeMixFormat(client, &mix_format);
680 if (FAILED(hr)) 683 if (FAILED(hr))
681 return hr; 684 return hr;
682 685
683 REFERENCE_TIME default_period = 0; 686 REFERENCE_TIME default_period = 0;
684 hr = GetDevicePeriod(client, AUDCLNT_SHAREMODE_SHARED, &default_period); 687 hr = GetDevicePeriod(client, AUDCLNT_SHAREMODE_SHARED, &default_period);
685 if (FAILED(hr)) 688 if (FAILED(hr))
686 return hr; 689 return hr;
687 690
688 // Get the integer mask which corresponds to the channel layout the 691 // Get the integer mask which corresponds to the channel layout the
689 // audio engine uses for its internal processing/mixing of shared-mode 692 // audio engine uses for its internal processing/mixing of shared-mode
690 // streams. This mask indicates which channels are present in the multi- 693 // streams. This mask indicates which channels are present in the multi-
691 // channel stream. The least significant bit corresponds with the Front Left 694 // channel stream. The least significant bit corresponds with the Front Left
692 // speaker, the next least significant bit corresponds to the Front Right 695 // speaker, the next least significant bit corresponds to the Front Right
693 // speaker, and so on, continuing in the order defined in KsMedia.h. 696 // speaker, and so on, continuing in the order defined in KsMedia.h.
694 // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083.aspx 697 // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083.aspx
695 // for more details. 698 // for more details.
696 ChannelConfig channel_config = mix_format.dwChannelMask; 699 ChannelConfig channel_config = mix_format.dwChannelMask;
697 700
698 // Convert Microsoft's channel configuration to genric ChannelLayout. 701 // Convert Microsoft's channel configuration to genric ChannelLayout.
699 ChannelLayout channel_layout = ChannelConfigToChannelLayout(channel_config); 702 ChannelLayout channel_layout = ChannelConfigToChannelLayout(channel_config);
700 703
701 // Some devices don't appear to set a valid channel layout, so guess based on 704 // Some devices don't appear to set a valid channel layout, so guess based on
702 // the number of channels. See http://crbug.com/311906. 705 // the number of channels. See http://crbug.com/311906.
703 if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) { 706 if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
704 DVLOG(1) << "Unsupported channel config: " 707 DVLOG(1) << "Unsupported channel config: " << std::hex << channel_config
705 << std::hex << channel_config 708 << ". Guessing layout by channel count: " << std::dec
706 << ". Guessing layout by channel count: " 709 << mix_format.Format.nChannels;
707 << std::dec << mix_format.Format.nChannels;
708 channel_layout = GuessChannelLayout(mix_format.Format.nChannels); 710 channel_layout = GuessChannelLayout(mix_format.Format.nChannels);
709 } 711 }
710 712
711 // Preferred sample rate. 713 // Preferred sample rate.
712 int sample_rate = mix_format.Format.nSamplesPerSec; 714 int sample_rate = mix_format.Format.nSamplesPerSec;
713 715
714 // TODO(henrika): possibly use format.Format.wBitsPerSample here instead. 716 // TODO(henrika): possibly use format.Format.wBitsPerSample here instead.
715 // We use a hard-coded value of 16 bits per sample today even if most audio 717 // We use a hard-coded value of 16 bits per sample today even if most audio
716 // engines does the actual mixing in 32 bits per sample. 718 // engines does the actual mixing in 32 bits per sample.
717 int bits_per_sample = 16; 719 int bits_per_sample = 16;
718 720
719 // We are using the native device period to derive the smallest possible 721 // We are using the native device period to derive the smallest possible
720 // buffer size in shared mode. Note that the actual endpoint buffer will be 722 // buffer size in shared mode. Note that the actual endpoint buffer will be
721 // larger than this size but it will be possible to fill it up in two calls. 723 // larger than this size but it will be possible to fill it up in two calls.
722 // TODO(henrika): ensure that this scheme works for capturing as well. 724 // TODO(henrika): ensure that this scheme works for capturing as well.
723 int frames_per_buffer = static_cast<int>(sample_rate * 725 int frames_per_buffer = static_cast<int>(
724 RefererenceTimeToTimeDelta(default_period).InSecondsF() + 0.5); 726 sample_rate * RefererenceTimeToTimeDelta(default_period).InSecondsF() +
727 0.5);
725 728
726 DVLOG(1) << "channel_layout : " << channel_layout; 729 DVLOG(1) << "channel_layout : " << channel_layout;
727 DVLOG(1) << "sample_rate : " << sample_rate; 730 DVLOG(1) << "sample_rate : " << sample_rate;
728 DVLOG(1) << "bits_per_sample : " << bits_per_sample; 731 DVLOG(1) << "bits_per_sample : " << bits_per_sample;
729 DVLOG(1) << "frames_per_buffer: " << frames_per_buffer; 732 DVLOG(1) << "frames_per_buffer: " << frames_per_buffer;
730 733
731 AudioParameters audio_params(AudioParameters::AUDIO_PCM_LOW_LATENCY, 734 AudioParameters audio_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
732 channel_layout, 735 channel_layout, sample_rate, bits_per_sample,
733 sample_rate,
734 bits_per_sample,
735 frames_per_buffer); 736 frames_per_buffer);
736 737
737 *params = audio_params; 738 *params = audio_params;
738 return hr; 739 return hr;
739 } 740 }
740 741
741 HRESULT CoreAudioUtil::GetPreferredAudioParameters(const std::string& device_id, 742 HRESULT CoreAudioUtil::GetPreferredAudioParameters(const std::string& device_id,
742 bool is_output_device, 743 bool is_output_device,
743 AudioParameters* params) { 744 AudioParameters* params) {
744 DCHECK(IsSupported()); 745 DCHECK(IsSupported());
745 746
746 ScopedComPtr<IMMDevice> device; 747 ScopedComPtr<IMMDevice> device;
747 if (device_id == AudioDeviceDescription::kDefaultDeviceId) { 748 if (device_id == AudioDeviceDescription::kDefaultDeviceId) {
748 device = CoreAudioUtil::CreateDefaultDevice( 749 device = CoreAudioUtil::CreateDefaultDevice(
749 is_output_device ? eRender : eCapture, eConsole); 750 is_output_device ? eRender : eCapture, eConsole);
750 } else if (device_id == AudioDeviceDescription::kLoopbackInputDeviceId) { 751 } else if (device_id == AudioDeviceDescription::kLoopbackInputDeviceId ||
752 device_id == AudioDeviceDescription::kLoopbackWithMuteDeviceId) {
751 DCHECK(!is_output_device); 753 DCHECK(!is_output_device);
752 device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole); 754 device = CoreAudioUtil::CreateDefaultDevice(eRender, eConsole);
753 } else if (device_id == AudioDeviceDescription::kCommunicationsDeviceId) { 755 } else if (device_id == AudioDeviceDescription::kCommunicationsDeviceId) {
754 device = CoreAudioUtil::CreateDefaultDevice( 756 device = CoreAudioUtil::CreateDefaultDevice(
755 is_output_device ? eRender : eCapture, eCommunications); 757 is_output_device ? eRender : eCapture, eCommunications);
756 } else { 758 } else {
757 device = CreateDevice(device_id); 759 device = CreateDevice(device_id);
758 } 760 }
759 761
760 if (!device.get()) { 762 if (!device.get()) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 // ensure that the volume level and muting state for a rendering session 813 // ensure that the volume level and muting state for a rendering session
812 // are persistent across system restarts. The volume level and muting 814 // are persistent across system restarts. The volume level and muting
813 // state for a capture session are never persistent. 815 // state for a capture session are never persistent.
814 DWORD stream_flags = 0; 816 DWORD stream_flags = 0;
815 817
816 // Enable event-driven streaming if a valid event handle is provided. 818 // Enable event-driven streaming if a valid event handle is provided.
817 // After the stream starts, the audio engine will signal the event handle 819 // After the stream starts, the audio engine will signal the event handle
818 // to notify the client each time a buffer becomes ready to process. 820 // to notify the client each time a buffer becomes ready to process.
819 // Event-driven buffering is supported for both rendering and capturing. 821 // Event-driven buffering is supported for both rendering and capturing.
820 // Both shared-mode and exclusive-mode streams can use event-driven buffering. 822 // Both shared-mode and exclusive-mode streams can use event-driven buffering.
821 bool use_event = (event_handle != NULL && 823 bool use_event =
822 event_handle != INVALID_HANDLE_VALUE); 824 (event_handle != NULL && event_handle != INVALID_HANDLE_VALUE);
823 if (use_event) 825 if (use_event)
824 stream_flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK; 826 stream_flags |= AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
825 DVLOG(2) << "stream_flags: 0x" << std::hex << stream_flags; 827 DVLOG(2) << "stream_flags: 0x" << std::hex << stream_flags;
826 828
827 // Initialize the shared mode client for minimal delay. 829 // Initialize the shared mode client for minimal delay.
828 HRESULT hr = client->Initialize(AUDCLNT_SHAREMODE_SHARED, 830 HRESULT hr = client->Initialize(AUDCLNT_SHAREMODE_SHARED, stream_flags, 0, 0,
829 stream_flags,
830 0,
831 0,
832 reinterpret_cast<const WAVEFORMATEX*>(format), 831 reinterpret_cast<const WAVEFORMATEX*>(format),
833 session_guid); 832 session_guid);
834 if (FAILED(hr)) { 833 if (FAILED(hr)) {
835 DVLOG(1) << "IAudioClient::Initialize: " << std::hex << hr; 834 DVLOG(1) << "IAudioClient::Initialize: " << std::hex << hr;
836 return hr; 835 return hr;
837 } 836 }
838 837
839 if (use_event) { 838 if (use_event) {
840 hr = client->SetEventHandle(event_handle); 839 hr = client->SetEventHandle(event_handle);
841 if (FAILED(hr)) { 840 if (FAILED(hr)) {
842 DVLOG(1) << "IAudioClient::SetEventHandle: " << std::hex << hr; 841 DVLOG(1) << "IAudioClient::SetEventHandle: " << std::hex << hr;
843 return hr; 842 return hr;
844 } 843 }
845 } 844 }
846 845
847 UINT32 buffer_size_in_frames = 0; 846 UINT32 buffer_size_in_frames = 0;
848 hr = client->GetBufferSize(&buffer_size_in_frames); 847 hr = client->GetBufferSize(&buffer_size_in_frames);
849 if (FAILED(hr)) { 848 if (FAILED(hr)) {
850 DVLOG(1) << "IAudioClient::GetBufferSize: " << std::hex << hr; 849 DVLOG(1) << "IAudioClient::GetBufferSize: " << std::hex << hr;
851 return hr; 850 return hr;
852 } 851 }
853 852
854 *endpoint_buffer_size = buffer_size_in_frames; 853 *endpoint_buffer_size = buffer_size_in_frames;
855 DVLOG(2) << "endpoint buffer size: " << buffer_size_in_frames; 854 DVLOG(2) << "endpoint buffer size: " << buffer_size_in_frames;
856 855
857 // TODO(henrika): utilize when delay measurements are added. 856 // TODO(henrika): utilize when delay measurements are added.
858 REFERENCE_TIME latency = 0; 857 REFERENCE_TIME latency = 0;
859 hr = client->GetStreamLatency(&latency); 858 hr = client->GetStreamLatency(&latency);
860 DVLOG(2) << "stream latency: " 859 DVLOG(2) << "stream latency: "
861 << RefererenceTimeToTimeDelta(latency).InMillisecondsF() << " [ms]"; 860 << RefererenceTimeToTimeDelta(latency).InMillisecondsF() << " [ms]";
862 return hr; 861 return hr;
863 } 862 }
864 863
865 ScopedComPtr<IAudioRenderClient> CoreAudioUtil::CreateRenderClient( 864 ScopedComPtr<IAudioRenderClient> CoreAudioUtil::CreateRenderClient(
866 IAudioClient* client) { 865 IAudioClient* client) {
867 DCHECK(IsSupported()); 866 DCHECK(IsSupported());
868 867
(...skipping 19 matching lines...) Expand all
888 HRESULT hr = client->GetService(__uuidof(IAudioCaptureClient), 887 HRESULT hr = client->GetService(__uuidof(IAudioCaptureClient),
889 audio_capture_client.ReceiveVoid()); 888 audio_capture_client.ReceiveVoid());
890 if (FAILED(hr)) { 889 if (FAILED(hr)) {
891 DVLOG(1) << "IAudioClient::GetService: " << std::hex << hr; 890 DVLOG(1) << "IAudioClient::GetService: " << std::hex << hr;
892 return ScopedComPtr<IAudioCaptureClient>(); 891 return ScopedComPtr<IAudioCaptureClient>();
893 } 892 }
894 return audio_capture_client; 893 return audio_capture_client;
895 } 894 }
896 895
897 bool CoreAudioUtil::FillRenderEndpointBufferWithSilence( 896 bool CoreAudioUtil::FillRenderEndpointBufferWithSilence(
898 IAudioClient* client, IAudioRenderClient* render_client) { 897 IAudioClient* client,
898 IAudioRenderClient* render_client) {
899 DCHECK(IsSupported()); 899 DCHECK(IsSupported());
900 900
901 UINT32 endpoint_buffer_size = 0; 901 UINT32 endpoint_buffer_size = 0;
902 if (FAILED(client->GetBufferSize(&endpoint_buffer_size))) 902 if (FAILED(client->GetBufferSize(&endpoint_buffer_size)))
903 return false; 903 return false;
904 904
905 UINT32 num_queued_frames = 0; 905 UINT32 num_queued_frames = 0;
906 if (FAILED(client->GetCurrentPadding(&num_queued_frames))) 906 if (FAILED(client->GetCurrentPadding(&num_queued_frames)))
907 return false; 907 return false;
908 908
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 964
965 if (variant.type() == VT_BSTR && variant.ptr()->bstrVal) { 965 if (variant.type() == VT_BSTR && variant.ptr()->bstrVal) {
966 base::WideToUTF8(variant.ptr()->bstrVal, wcslen(variant.ptr()->bstrVal), 966 base::WideToUTF8(variant.ptr()->bstrVal, wcslen(variant.ptr()->bstrVal),
967 driver_version); 967 driver_version);
968 } 968 }
969 969
970 return true; 970 return true;
971 } 971 }
972 972
973 } // namespace media 973 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698