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