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 <objbase.h> |
| 8 |
7 #include <cmath> | 9 #include <cmath> |
8 #include <memory> | 10 #include <memory> |
9 | 11 |
10 #include "base/logging.h" | 12 #include "base/logging.h" |
11 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
12 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
13 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
14 #include "media/audio/audio_device_description.h" | 16 #include "media/audio/audio_device_description.h" |
15 #include "media/audio/win/audio_manager_win.h" | 17 #include "media/audio/win/audio_manager_win.h" |
16 #include "media/audio/win/avrt_wrapper_win.h" | 18 #include "media/audio/win/avrt_wrapper_win.h" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 // set at construction. | 119 // set at construction. |
118 HRESULT hr = SetCaptureDevice(); | 120 HRESULT hr = SetCaptureDevice(); |
119 if (FAILED(hr)) { | 121 if (FAILED(hr)) { |
120 ReportOpenResult(); | 122 ReportOpenResult(); |
121 return false; | 123 return false; |
122 } | 124 } |
123 | 125 |
124 // Obtain an IAudioClient interface which enables us to create and initialize | 126 // Obtain an IAudioClient interface which enables us to create and initialize |
125 // an audio stream between an audio application and the audio engine. | 127 // an audio stream between an audio application and the audio engine. |
126 hr = endpoint_device_->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, | 128 hr = endpoint_device_->Activate(__uuidof(IAudioClient), CLSCTX_INPROC_SERVER, |
127 NULL, audio_client_.ReceiveVoid()); | 129 NULL, &audio_client_); |
128 if (FAILED(hr)) { | 130 if (FAILED(hr)) { |
129 open_result_ = OPEN_RESULT_ACTIVATION_FAILED; | 131 open_result_ = OPEN_RESULT_ACTIVATION_FAILED; |
130 ReportOpenResult(); | 132 ReportOpenResult(); |
131 return false; | 133 return false; |
132 } | 134 } |
133 | 135 |
134 #ifndef NDEBUG | 136 #ifndef NDEBUG |
135 // Retrieve the stream format which the audio engine uses for its internal | 137 // Retrieve the stream format which the audio engine uses for its internal |
136 // processing/mixing of shared-mode streams. This function call is for | 138 // processing/mixing of shared-mode streams. This function call is for |
137 // diagnostic purposes only and only in debug mode. | 139 // diagnostic purposes only and only in debug mode. |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 DVLOG(1) << "AudioBlockFifo buffer count: " << buffers_required; | 372 DVLOG(1) << "AudioBlockFifo buffer count: " << buffers_required; |
371 | 373 |
372 LARGE_INTEGER now_count = {}; | 374 LARGE_INTEGER now_count = {}; |
373 bool recording = true; | 375 bool recording = true; |
374 bool error = false; | 376 bool error = false; |
375 double volume = GetVolume(); | 377 double volume = GetVolume(); |
376 HANDLE wait_array[2] = {stop_capture_event_.Get(), | 378 HANDLE wait_array[2] = {stop_capture_event_.Get(), |
377 audio_samples_ready_event_.Get()}; | 379 audio_samples_ready_event_.Get()}; |
378 | 380 |
379 base::win::ScopedComPtr<IAudioClock> audio_clock; | 381 base::win::ScopedComPtr<IAudioClock> audio_clock; |
380 audio_client_->GetService(__uuidof(IAudioClock), audio_clock.ReceiveVoid()); | 382 audio_client_->GetService(IID_PPV_ARGS(&audio_clock)); |
381 | 383 |
382 while (recording && !error) { | 384 while (recording && !error) { |
383 HRESULT hr = S_FALSE; | 385 HRESULT hr = S_FALSE; |
384 | 386 |
385 // Wait for a close-down event or a new capture event. | 387 // Wait for a close-down event or a new capture event. |
386 DWORD wait_result = WaitForMultipleObjects(2, wait_array, FALSE, INFINITE); | 388 DWORD wait_result = WaitForMultipleObjects(2, wait_array, FALSE, INFINITE); |
387 switch (wait_result) { | 389 switch (wait_result) { |
388 case WAIT_FAILED: | 390 case WAIT_FAILED: |
389 error = true; | 391 error = true; |
390 break; | 392 break; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 endpoint_device_.Receive()); | 531 endpoint_device_.Receive()); |
530 } else if (device_id_ == AudioDeviceDescription::kCommunicationsDeviceId) { | 532 } else if (device_id_ == AudioDeviceDescription::kCommunicationsDeviceId) { |
531 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, | 533 hr = enumerator->GetDefaultAudioEndpoint(eCapture, eCommunications, |
532 endpoint_device_.Receive()); | 534 endpoint_device_.Receive()); |
533 } else if (device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId) { | 535 } else if (device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId) { |
534 // Capture the default playback stream. | 536 // Capture the default playback stream. |
535 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, | 537 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, |
536 endpoint_device_.Receive()); | 538 endpoint_device_.Receive()); |
537 | 539 |
538 endpoint_device_->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, | 540 endpoint_device_->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, |
539 system_audio_volume_.ReceiveVoid()); | 541 &system_audio_volume_); |
540 } else if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId) { | 542 } else if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId) { |
541 // Capture the default playback stream. | 543 // Capture the default playback stream. |
542 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, | 544 hr = enumerator->GetDefaultAudioEndpoint(eRender, eConsole, |
543 endpoint_device_.Receive()); | 545 endpoint_device_.Receive()); |
544 } else { | 546 } else { |
545 hr = enumerator->GetDevice(base::UTF8ToUTF16(device_id_).c_str(), | 547 hr = enumerator->GetDevice(base::UTF8ToUTF16(device_id_).c_str(), |
546 endpoint_device_.Receive()); | 548 endpoint_device_.Receive()); |
547 } | 549 } |
548 | 550 |
549 if (FAILED(hr)) { | 551 if (FAILED(hr)) { |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 // work around this, initialize a render stream in event-driven mode. Each | 772 // work around this, initialize a render stream in event-driven mode. Each |
771 // time the client receives an event for the render stream, it must signal | 773 // time the client receives an event for the render stream, it must signal |
772 // the capture client to run the capture thread that reads the next set of | 774 // the capture client to run the capture thread that reads the next set of |
773 // samples from the capture endpoint buffer. | 775 // samples from the capture endpoint buffer. |
774 // | 776 // |
775 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd316551(v=vs.85).a
spx | 777 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd316551(v=vs.85).a
spx |
776 if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId || | 778 if (device_id_ == AudioDeviceDescription::kLoopbackInputDeviceId || |
777 device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId) { | 779 device_id_ == AudioDeviceDescription::kLoopbackWithMuteDeviceId) { |
778 hr = endpoint_device_->Activate( | 780 hr = endpoint_device_->Activate( |
779 __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, | 781 __uuidof(IAudioClient), CLSCTX_INPROC_SERVER, NULL, |
780 audio_render_client_for_loopback_.ReceiveVoid()); | 782 &audio_render_client_for_loopback_); |
781 if (FAILED(hr)) { | 783 if (FAILED(hr)) { |
782 open_result_ = OPEN_RESULT_LOOPBACK_ACTIVATE_FAILED; | 784 open_result_ = OPEN_RESULT_LOOPBACK_ACTIVATE_FAILED; |
783 return hr; | 785 return hr; |
784 } | 786 } |
785 | 787 |
786 hr = audio_render_client_for_loopback_->Initialize( | 788 hr = audio_render_client_for_loopback_->Initialize( |
787 AUDCLNT_SHAREMODE_SHARED, | 789 AUDCLNT_SHAREMODE_SHARED, |
788 AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, 0, 0, | 790 AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST, 0, 0, |
789 &format_, NULL); | 791 &format_, NULL); |
790 if (FAILED(hr)) { | 792 if (FAILED(hr)) { |
791 open_result_ = OPEN_RESULT_LOOPBACK_INIT_FAILED; | 793 open_result_ = OPEN_RESULT_LOOPBACK_INIT_FAILED; |
792 return hr; | 794 return hr; |
793 } | 795 } |
794 | 796 |
795 hr = audio_render_client_for_loopback_->SetEventHandle( | 797 hr = audio_render_client_for_loopback_->SetEventHandle( |
796 audio_samples_ready_event_.Get()); | 798 audio_samples_ready_event_.Get()); |
797 } else { | 799 } else { |
798 hr = audio_client_->SetEventHandle(audio_samples_ready_event_.Get()); | 800 hr = audio_client_->SetEventHandle(audio_samples_ready_event_.Get()); |
799 } | 801 } |
800 | 802 |
801 if (FAILED(hr)) { | 803 if (FAILED(hr)) { |
802 open_result_ = OPEN_RESULT_SET_EVENT_HANDLE; | 804 open_result_ = OPEN_RESULT_SET_EVENT_HANDLE; |
803 return hr; | 805 return hr; |
804 } | 806 } |
805 | 807 |
806 // Get access to the IAudioCaptureClient interface. This interface | 808 // Get access to the IAudioCaptureClient interface. This interface |
807 // enables us to read input data from the capture endpoint buffer. | 809 // enables us to read input data from the capture endpoint buffer. |
808 hr = audio_client_->GetService(__uuidof(IAudioCaptureClient), | 810 hr = audio_client_->GetService(IID_PPV_ARGS(&audio_capture_client_)); |
809 audio_capture_client_.ReceiveVoid()); | |
810 if (FAILED(hr)) { | 811 if (FAILED(hr)) { |
811 open_result_ = OPEN_RESULT_NO_CAPTURE_CLIENT; | 812 open_result_ = OPEN_RESULT_NO_CAPTURE_CLIENT; |
812 return hr; | 813 return hr; |
813 } | 814 } |
814 | 815 |
815 // Obtain a reference to the ISimpleAudioVolume interface which enables | 816 // Obtain a reference to the ISimpleAudioVolume interface which enables |
816 // us to control the master volume level of an audio session. | 817 // us to control the master volume level of an audio session. |
817 hr = audio_client_->GetService(__uuidof(ISimpleAudioVolume), | 818 hr = audio_client_->GetService(IID_PPV_ARGS(&simple_audio_volume_)); |
818 simple_audio_volume_.ReceiveVoid()); | |
819 if (FAILED(hr)) | 819 if (FAILED(hr)) |
820 open_result_ = OPEN_RESULT_NO_AUDIO_VOLUME; | 820 open_result_ = OPEN_RESULT_NO_AUDIO_VOLUME; |
821 | 821 |
822 return hr; | 822 return hr; |
823 } | 823 } |
824 | 824 |
825 void WASAPIAudioInputStream::ReportOpenResult() const { | 825 void WASAPIAudioInputStream::ReportOpenResult() const { |
826 DCHECK(!opened_); // This method must be called before we set this flag. | 826 DCHECK(!opened_); // This method must be called before we set this flag. |
827 UMA_HISTOGRAM_ENUMERATION("Media.Audio.Capture.Win.Open", open_result_, | 827 UMA_HISTOGRAM_ENUMERATION("Media.Audio.Capture.Win.Open", open_result_, |
828 OPEN_RESULT_MAX + 1); | 828 OPEN_RESULT_MAX + 1); |
829 } | 829 } |
830 | 830 |
831 double WASAPIAudioInputStream::ProvideInput(AudioBus* audio_bus, | 831 double WASAPIAudioInputStream::ProvideInput(AudioBus* audio_bus, |
832 uint32_t frames_delayed) { | 832 uint32_t frames_delayed) { |
833 fifo_->Consume()->CopyTo(audio_bus); | 833 fifo_->Consume()->CopyTo(audio_bus); |
834 return 1.0; | 834 return 1.0; |
835 } | 835 } |
836 | 836 |
837 } // namespace media | 837 } // namespace media |
OLD | NEW |