Chromium Code Reviews| 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 <endpointvolume.h> | |
| 7 #include <memory> | 8 #include <memory> |
| 8 | 9 |
| 9 #include "base/logging.h" | 10 #include "base/logging.h" |
| 10 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
| 11 #include "base/trace_event/trace_event.h" | 12 #include "base/trace_event/trace_event.h" |
| 12 #include "media/audio/audio_device_description.h" | 13 #include "media/audio/audio_device_description.h" |
| 13 #include "media/audio/win/audio_manager_win.h" | 14 #include "media/audio/win/audio_manager_win.h" |
| 14 #include "media/audio/win/avrt_wrapper_win.h" | 15 #include "media/audio/win/avrt_wrapper_win.h" |
| 15 #include "media/audio/win/core_audio_util_win.h" | 16 #include "media/audio/win/core_audio_util_win.h" |
| 16 #include "media/base/audio_bus.h" | 17 #include "media/base/audio_bus.h" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 28 opened_(false), | 29 opened_(false), |
| 29 started_(false), | 30 started_(false), |
| 30 frame_size_(0), | 31 frame_size_(0), |
| 31 packet_size_frames_(0), | 32 packet_size_frames_(0), |
| 32 packet_size_bytes_(0), | 33 packet_size_bytes_(0), |
| 33 endpoint_buffer_size_frames_(0), | 34 endpoint_buffer_size_frames_(0), |
| 34 device_id_(device_id), | 35 device_id_(device_id), |
| 35 perf_count_to_100ns_units_(0.0), | 36 perf_count_to_100ns_units_(0.0), |
| 36 ms_to_frame_count_(0.0), | 37 ms_to_frame_count_(0.0), |
| 37 sink_(NULL), | 38 sink_(NULL), |
| 38 audio_bus_(media::AudioBus::Create(params)) { | 39 audio_bus_(media::AudioBus::Create(params)), |
| 40 mute_done_(false) { | |
| 39 DCHECK(manager_); | 41 DCHECK(manager_); |
| 40 | 42 |
| 41 // Load the Avrt DLL if not already loaded. Required to support MMCSS. | 43 // Load the Avrt DLL if not already loaded. Required to support MMCSS. |
| 42 bool avrt_init = avrt::Initialize(); | 44 bool avrt_init = avrt::Initialize(); |
| 43 DCHECK(avrt_init) << "Failed to load the Avrt.dll"; | 45 DCHECK(avrt_init) << "Failed to load the Avrt.dll"; |
| 44 | 46 |
| 45 // Set up the desired capture format specified by the client. | 47 // Set up the desired capture format specified by the client. |
| 46 format_.nSamplesPerSec = params.sample_rate(); | 48 format_.nSamplesPerSec = params.sample_rate(); |
| 47 format_.wFormatTag = WAVE_FORMAT_PCM; | 49 format_.wFormatTag = WAVE_FORMAT_PCM; |
| 48 format_.wBitsPerSample = params.bits_per_sample(); | 50 format_.wBitsPerSample = params.bits_per_sample(); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 | 160 |
| 159 started_ = SUCCEEDED(hr); | 161 started_ = SUCCEEDED(hr); |
| 160 } | 162 } |
| 161 | 163 |
| 162 void WASAPIAudioInputStream::Stop() { | 164 void WASAPIAudioInputStream::Stop() { |
| 163 DCHECK(CalledOnValidThread()); | 165 DCHECK(CalledOnValidThread()); |
| 164 DVLOG(1) << "WASAPIAudioInputStream::Stop()"; | 166 DVLOG(1) << "WASAPIAudioInputStream::Stop()"; |
| 165 if (!started_) | 167 if (!started_) |
| 166 return; | 168 return; |
| 167 | 169 |
| 170 if (device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId && | |
|
henrika (OOO until Aug 14)
2016/07/25 08:38:19
Add a comment on 169 explaining what you do here.
qiangchen
2016/07/25 22:42:22
Done.
| |
| 171 mute_done_) { | |
| 172 IAudioEndpointVolume* pVolume = NULL; | |
| 173 HRESULT hr = | |
| 174 endpoint_device_->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, | |
| 175 NULL, reinterpret_cast<void**>(&pVolume)); | |
|
henrika (OOO until Aug 14)
2016/07/25 08:38:19
Can you use base::win::ScopedComPtr<IAudioEndpoint
qiangchen
2016/07/25 22:42:22
Done.
| |
| 176 | |
| 177 if (SUCCEEDED(hr)) { | |
| 178 hr = pVolume->SetMute(false, NULL); | |
| 179 mute_done_ = false; | |
| 180 } | |
| 181 } | |
| 182 | |
| 168 // Stops periodic AGC microphone measurements. | 183 // Stops periodic AGC microphone measurements. |
| 169 StopAgc(); | 184 StopAgc(); |
| 170 | 185 |
| 171 // Shut down the capture thread. | 186 // Shut down the capture thread. |
| 172 if (stop_capture_event_.IsValid()) { | 187 if (stop_capture_event_.IsValid()) { |
| 173 SetEvent(stop_capture_event_.Get()); | 188 SetEvent(stop_capture_event_.Get()); |
| 174 } | 189 } |
| 175 | 190 |
| 176 // Stop the input audio streaming. | 191 // Stop the input audio streaming. |
| 177 HRESULT hr = audio_client_->Stop(); | 192 HRESULT hr = audio_client_->Stop(); |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 | 479 |
| 465 if (device_id_ == AudioDeviceDescription::kDefaultDeviceId) { | 480 if (device_id_ == AudioDeviceDescription::kDefaultDeviceId) { |
| 466 // Retrieve the default capture audio endpoint for the specified role. | 481 // Retrieve the default capture audio endpoint for the specified role. |
| 467 // Note that, in Windows Vista, the MMDevice API supports device roles | 482 // Note that, in Windows Vista, the MMDevice API supports device roles |
| 468 // but the system-supplied user interface programs do not. | 483 // but the system-supplied user interface programs do not. |
| 469 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eConsole, | 484 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eConsole, |
| 470 endpoint_device_.Receive()); | 485 endpoint_device_.Receive()); |
| 471 } else if (device_id_ == AudioDeviceDescription::kCommunicationsDeviceId) { | 486 } else if (device_id_ == AudioDeviceDescription::kCommunicationsDeviceId) { |
| 472 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, | 487 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, |
| 473 endpoint_device_.Receive()); | 488 endpoint_device_.Receive()); |
| 489 } else if (device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId) { | |
| 490 // Capture the default playback stream. | |
| 491 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, | |
| 492 endpoint_device_.Receive()); | |
| 493 | |
| 494 IAudioEndpointVolume* pVolume = NULL; | |
|
henrika (OOO until Aug 14)
2016/07/25 08:38:19
See comments above. Also, you duplicate code here.
qiangchen
2016/07/25 22:42:22
Done.
| |
| 495 HRESULT hr2 = | |
|
henrika (OOO until Aug 14)
2016/07/25 08:38:19
Try to clean this up and avoid using a second HRES
qiangchen
2016/07/25 22:42:22
Done.
| |
| 496 endpoint_device_->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, | |
| 497 NULL, reinterpret_cast<void**>(&pVolume)); | |
| 498 if (SUCCEEDED(hr2) && pVolume) { | |
| 499 BOOL muted = false; | |
| 500 hr2 = pVolume->GetMute(&muted); | |
| 501 if (SUCCEEDED(hr2) && !muted) { | |
|
henrika (OOO until Aug 14)
2016/07/25 08:38:19
Improve comments and explain why you always mute h
qiangchen
2016/07/25 22:42:22
Done.
| |
| 502 hr2 = pVolume->SetMute(true, NULL); | |
| 503 mute_done_ = true; | |
| 504 } | |
| 505 } | |
| 474 } else if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId) { | 506 } else if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId) { |
| 475 // Capture the default playback stream. | 507 // Capture the default playback stream. |
| 476 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, | 508 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, |
| 477 endpoint_device_.Receive()); | 509 endpoint_device_.Receive()); |
| 478 } else { | 510 } else { |
| 479 hr = enumerator->GetDevice(base::UTF8ToUTF16(device_id_).c_str(), | 511 hr = enumerator->GetDevice(base::UTF8ToUTF16(device_id_).c_str(), |
| 480 endpoint_device_.Receive()); | 512 endpoint_device_.Receive()); |
| 481 } | 513 } |
| 482 | 514 |
| 483 if (FAILED(hr)) | 515 if (FAILED(hr)) |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 565 DLOG_IF(ERROR, hr == S_FALSE) << "Format is not supported " | 597 DLOG_IF(ERROR, hr == S_FALSE) << "Format is not supported " |
| 566 << "but a closest match exists."; | 598 << "but a closest match exists."; |
| 567 return (hr == S_OK); | 599 return (hr == S_OK); |
| 568 } | 600 } |
| 569 | 601 |
| 570 HRESULT WASAPIAudioInputStream::InitializeAudioEngine() { | 602 HRESULT WASAPIAudioInputStream::InitializeAudioEngine() { |
| 571 DWORD flags; | 603 DWORD flags; |
| 572 // Use event-driven mode only fo regular input devices. For loopback the | 604 // Use event-driven mode only fo regular input devices. For loopback the |
| 573 // EVENTCALLBACK flag is specified when intializing | 605 // EVENTCALLBACK flag is specified when intializing |
| 574 // |audio_render_client_for_loopback_|. | 606 // |audio_render_client_for_loopback_|. |
| 575 if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId) { | 607 if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId || |
| 608 device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId) { | |
| 576 flags = AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; | 609 flags = AUDCLNT_STREAMFLAGS_LOOPBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; |
| 577 } else { | 610 } else { |
| 578 flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; | 611 flags = AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST; |
| 579 } | 612 } |
| 580 | 613 |
| 581 // Initialize the audio stream between the client and the device. | 614 // Initialize the audio stream between the client and the device. |
| 582 // We connect indirectly through the audio engine by using shared mode. | 615 // We connect indirectly through the audio engine by using shared mode. |
| 583 // Note that, |hnsBufferDuration| is set of 0, which ensures that the | 616 // Note that, |hnsBufferDuration| is set of 0, which ensures that the |
| 584 // buffer is never smaller than the minimum buffer size needed to ensure | 617 // buffer is never smaller than the minimum buffer size needed to ensure |
| 585 // that glitches do not occur between the periodic processing passes. | 618 // that glitches do not occur between the periodic processing passes. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 639 // to MSDN: | 672 // to MSDN: |
| 640 // | 673 // |
| 641 // A pull-mode capture client does not receive any events when a stream is | 674 // A pull-mode capture client does not receive any events when a stream is |
| 642 // initialized with event-driven buffering and is loopback-enabled. To | 675 // initialized with event-driven buffering and is loopback-enabled. To |
| 643 // work around this, initialize a render stream in event-driven mode. Each | 676 // work around this, initialize a render stream in event-driven mode. Each |
| 644 // time the client receives an event for the render stream, it must signal | 677 // time the client receives an event for the render stream, it must signal |
| 645 // the capture client to run the capture thread that reads the next set of | 678 // the capture client to run the capture thread that reads the next set of |
| 646 // samples from the capture endpoint buffer. | 679 // samples from the capture endpoint buffer. |
| 647 // | 680 // |
| 648 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd316551(v=vs.85).a spx | 681 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd316551(v=vs.85).a spx |
| 649 if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId) { | 682 if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId || |
| 683 device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId) { | |
| 650 hr = endpoint_device_->Activate( | 684 hr = endpoint_device_->Activate( |
| 651 __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, | 685 __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, |
| 652 audio_render_client_for_loopback_.ReceiveVoid()); | 686 audio_render_client_for_loopback_.ReceiveVoid()); |
| 653 if (FAILED(hr)) | 687 if (FAILED(hr)) |
| 654 return hr; | 688 return hr; |
| 655 | 689 |
| 656 hr = audio_render_client_for_loopback_->Initialize( | 690 hr = audio_render_client_for_loopback_->Initialize( |
| 657 AUDCLNT_SHAREMODE_SHARED, | 691 AUDCLNT_SHAREMODE_SHARED, |
| 658 AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, | 692 AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, |
| 659 0, 0, &format_, NULL); | 693 0, 0, &format_, NULL); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 677 return hr; | 711 return hr; |
| 678 | 712 |
| 679 // Obtain a reference to the ISimpleAudioVolume interface which enables | 713 // Obtain a reference to the ISimpleAudioVolume interface which enables |
| 680 // us to control the master volume level of an audio session. | 714 // us to control the master volume level of an audio session. |
| 681 hr = audio_client_->GetService(__uuidof(ISimpleAudioVolume), | 715 hr = audio_client_->GetService(__uuidof(ISimpleAudioVolume), |
| 682 simple_audio_volume_.ReceiveVoid()); | 716 simple_audio_volume_.ReceiveVoid()); |
| 683 return hr; | 717 return hr; |
| 684 } | 718 } |
| 685 | 719 |
| 686 } // namespace media | 720 } // namespace media |
| OLD | NEW |