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 "media/audio/win/audio_low_latency_input_win.h" | 5 #include "media/audio/win/audio_low_latency_input_win.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/strings/utf_string_conversions.h" | 9 #include "base/strings/utf_string_conversions.h" |
10 #include "media/audio/win/audio_manager_win.h" | 10 #include "media/audio/win/audio_manager_win.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 const AudioParameters& params, | 21 const AudioParameters& params, |
22 const std::string& device_id) | 22 const std::string& device_id) |
23 : manager_(manager), | 23 : manager_(manager), |
24 capture_thread_(NULL), | 24 capture_thread_(NULL), |
25 opened_(false), | 25 opened_(false), |
26 started_(false), | 26 started_(false), |
27 frame_size_(0), | 27 frame_size_(0), |
28 packet_size_frames_(0), | 28 packet_size_frames_(0), |
29 packet_size_bytes_(0), | 29 packet_size_bytes_(0), |
30 endpoint_buffer_size_frames_(0), | 30 endpoint_buffer_size_frames_(0), |
31 effects_(params.effects()), | |
32 device_id_(device_id), | 31 device_id_(device_id), |
33 perf_count_to_100ns_units_(0.0), | 32 perf_count_to_100ns_units_(0.0), |
34 ms_to_frame_count_(0.0), | 33 ms_to_frame_count_(0.0), |
35 sink_(NULL), | 34 sink_(NULL), |
36 audio_bus_(media::AudioBus::Create(params)) { | 35 audio_bus_(media::AudioBus::Create(params)) { |
37 DCHECK(manager_); | 36 DCHECK(manager_); |
38 | 37 |
39 // Load the Avrt DLL if not already loaded. Required to support MMCSS. | 38 // Load the Avrt DLL if not already loaded. Required to support MMCSS. |
40 bool avrt_init = avrt::Initialize(); | 39 bool avrt_init = avrt::Initialize(); |
41 DCHECK(avrt_init) << "Failed to load the Avrt.dll"; | 40 DCHECK(avrt_init) << "Failed to load the Avrt.dll"; |
(...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 | 425 |
427 ScopedComPtr<IMMDeviceEnumerator> enumerator; | 426 ScopedComPtr<IMMDeviceEnumerator> enumerator; |
428 HRESULT hr = enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), | 427 HRESULT hr = enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), |
429 NULL, CLSCTX_INPROC_SERVER); | 428 NULL, CLSCTX_INPROC_SERVER); |
430 if (FAILED(hr)) | 429 if (FAILED(hr)) |
431 return hr; | 430 return hr; |
432 | 431 |
433 // Retrieve the IMMDevice by using the specified role or the specified | 432 // Retrieve the IMMDevice by using the specified role or the specified |
434 // unique endpoint device-identification string. | 433 // unique endpoint device-identification string. |
435 | 434 |
436 if (effects_ & AudioParameters::DUCKING) { | 435 if (device_id_ == AudioManagerBase::kDefaultDeviceId) { |
437 // Ducking has been requested and it is only supported for the default | 436 // Retrieve the default capture audio endpoint for the specified role. |
438 // communication device. So, let's open up the communication device and | 437 // Note that, in Windows Vista, the MMDevice API supports device roles |
439 // see if the ID of that device matches the requested ID. | 438 // but the system-supplied user interface programs do not. |
440 // We consider a kDefaultDeviceId as well as an explicit device id match, | 439 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eConsole, |
441 // to be valid matches. | 440 endpoint_device_.Receive()); |
| 441 } else if (device_id_ == AudioManagerBase::kCommunicationsDeviceId) { |
442 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, | 442 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, |
443 endpoint_device_.Receive()); | 443 endpoint_device_.Receive()); |
444 if (endpoint_device_.get() && | 444 } else if (device_id_ == AudioManagerBase::kLoopbackInputDeviceId) { |
445 device_id_ != AudioManagerBase::kDefaultDeviceId) { | 445 // Capture the default playback stream. |
446 base::win::ScopedCoMem<WCHAR> communications_id; | 446 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, |
447 endpoint_device_->GetId(&communications_id); | 447 endpoint_device_.Receive()); |
448 if (device_id_ != | 448 } else { |
449 base::WideToUTF8(static_cast<WCHAR*>(communications_id))) { | 449 hr = enumerator->GetDevice(base::UTF8ToUTF16(device_id_).c_str(), |
450 DLOG(WARNING) << "Ducking has been requested for a non-default device." | 450 endpoint_device_.Receive()); |
451 "Not supported."; | |
452 // We can't honor the requested effect flag, so turn it off and | |
453 // continue. We'll check this flag later to see if we've actually | |
454 // opened up the communications device, so it's important that it | |
455 // reflects the active state. | |
456 effects_ &= ~AudioParameters::DUCKING; | |
457 endpoint_device_.Release(); // Fall back on code below. | |
458 } | |
459 } | |
460 } | |
461 | |
462 if (!endpoint_device_.get()) { | |
463 if (device_id_ == AudioManagerBase::kDefaultDeviceId) { | |
464 // Retrieve the default capture audio endpoint for the specified role. | |
465 // Note that, in Windows Vista, the MMDevice API supports device roles | |
466 // but the system-supplied user interface programs do not. | |
467 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eConsole, | |
468 endpoint_device_.Receive()); | |
469 } else if (device_id_ == AudioManagerBase::kLoopbackInputDeviceId) { | |
470 // Capture the default playback stream. | |
471 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, | |
472 endpoint_device_.Receive()); | |
473 } else { | |
474 hr = enumerator->GetDevice(base::UTF8ToUTF16(device_id_).c_str(), | |
475 endpoint_device_.Receive()); | |
476 } | |
477 } | 451 } |
478 | 452 |
479 if (FAILED(hr)) | 453 if (FAILED(hr)) |
480 return hr; | 454 return hr; |
481 | 455 |
482 // Verify that the audio endpoint device is active, i.e., the audio | 456 // Verify that the audio endpoint device is active, i.e., the audio |
483 // adapter that connects to the endpoint device is present and enabled. | 457 // adapter that connects to the endpoint device is present and enabled. |
484 DWORD state = DEVICE_STATE_DISABLED; | 458 DWORD state = DEVICE_STATE_DISABLED; |
485 hr = endpoint_device_->GetState(&state); | 459 hr = endpoint_device_->GetState(&state); |
486 if (FAILED(hr)) | 460 if (FAILED(hr)) |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 } | 538 } |
565 | 539 |
566 HRESULT WASAPIAudioInputStream::InitializeAudioEngine() { | 540 HRESULT WASAPIAudioInputStream::InitializeAudioEngine() { |
567 DWORD flags; | 541 DWORD flags; |
568 // Use event-driven mode only fo regular input devices. For loopback the | 542 // Use event-driven mode only fo regular input devices. For loopback the |
569 // EVENTCALLBACK flag is specified when intializing | 543 // EVENTCALLBACK flag is specified when intializing |
570 // |audio_render_client_for_loopback_|. | 544 // |audio_render_client_for_loopback_|. |
571 if (device_id_ == AudioManagerBase::kLoopbackInputDeviceId) { | 545 if (device_id_ == AudioManagerBase::kLoopbackInputDeviceId) { |
572 flags = AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; | 546 flags = AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; |
573 } else { | 547 } else { |
574 flags = | 548 flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; |
575 AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; | |
576 } | 549 } |
577 | 550 |
578 // Initialize the audio stream between the client and the device. | 551 // Initialize the audio stream between the client and the device. |
579 // We connect indirectly through the audio engine by using shared mode. | 552 // We connect indirectly through the audio engine by using shared mode. |
580 // Note that, |hnsBufferDuration| is set of 0, which ensures that the | 553 // Note that, |hnsBufferDuration| is set of 0, which ensures that the |
581 // buffer is never smaller than the minimum buffer size needed to ensure | 554 // buffer is never smaller than the minimum buffer size needed to ensure |
582 // that glitches do not occur between the periodic processing passes. | 555 // that glitches do not occur between the periodic processing passes. |
583 // This setting should lead to lowest possible latency. | 556 // This setting should lead to lowest possible latency. |
584 HRESULT hr = audio_client_->Initialize( | 557 HRESULT hr = audio_client_->Initialize( |
585 AUDCLNT_SHAREMODE_SHARED, | 558 AUDCLNT_SHAREMODE_SHARED, |
586 flags, | 559 flags, |
587 0, // hnsBufferDuration | 560 0, // hnsBufferDuration |
588 0, | 561 0, |
589 &format_, | 562 &format_, |
590 (effects_ & AudioParameters::DUCKING) ? &kCommunicationsSessionId : NULL); | 563 device_id_ == AudioManagerBase::kCommunicationsDeviceId ? |
| 564 &kCommunicationsSessionId : nullptr); |
591 | 565 |
592 if (FAILED(hr)) | 566 if (FAILED(hr)) |
593 return hr; | 567 return hr; |
594 | 568 |
595 // Retrieve the length of the endpoint buffer shared between the client | 569 // Retrieve the length of the endpoint buffer shared between the client |
596 // and the audio engine. The buffer length determines the maximum amount | 570 // and the audio engine. The buffer length determines the maximum amount |
597 // of capture data that the audio engine can read from the endpoint buffer | 571 // of capture data that the audio engine can read from the endpoint buffer |
598 // during a single processing pass. | 572 // during a single processing pass. |
599 // A typical value is 960 audio frames <=> 20ms @ 48kHz sample rate. | 573 // A typical value is 960 audio frames <=> 20ms @ 48kHz sample rate. |
600 hr = audio_client_->GetBufferSize(&endpoint_buffer_size_frames_); | 574 hr = audio_client_->GetBufferSize(&endpoint_buffer_size_frames_); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 return hr; | 649 return hr; |
676 | 650 |
677 // Obtain a reference to the ISimpleAudioVolume interface which enables | 651 // Obtain a reference to the ISimpleAudioVolume interface which enables |
678 // us to control the master volume level of an audio session. | 652 // us to control the master volume level of an audio session. |
679 hr = audio_client_->GetService(__uuidof(ISimpleAudioVolume), | 653 hr = audio_client_->GetService(__uuidof(ISimpleAudioVolume), |
680 simple_audio_volume_.ReceiveVoid()); | 654 simple_audio_volume_.ReceiveVoid()); |
681 return hr; | 655 return hr; |
682 } | 656 } |
683 | 657 |
684 } // namespace media | 658 } // namespace media |
OLD | NEW |