| 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 |