Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1225)

Unified Diff: remoting/host/audio_capturer_win.cc

Issue 2163473002: [Chromoting] Audio playback won't work after switching default playback device (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Resolve review comments Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/audio_capturer_win.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/audio_capturer_win.cc
diff --git a/remoting/host/audio_capturer_win.cc b/remoting/host/audio_capturer_win.cc
index f6ea113160b6662e1e3f31ff5625f3755d6e7497..a7f36f4b6a5784affa17d6be74d16a6df9962244 100644
--- a/remoting/host/audio_capturer_win.cc
+++ b/remoting/host/audio_capturer_win.cc
@@ -16,6 +16,7 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/synchronization/lock.h"
namespace {
const int kChannels = 2;
@@ -40,11 +41,74 @@ const int kMaxExpectedTimerLag = 30;
namespace remoting {
+class AudioCapturerWin::MMNotificationClient : public IMMNotificationClient {
+ public:
+ MMNotificationClient(AudioCapturerWin* owner)
Sergey Ulanov 2016/07/22 17:38:37 owner_ is not needed anymore. Remove it?
Hzj_jie 2016/07/22 21:03:11 Yep, sorry.
+ : owner_(owner) {
+ DCHECK(owner_);
+ }
+
+ HRESULT __stdcall OnDefaultDeviceChanged(
+ EDataFlow flow,
+ ERole role,
+ LPCWSTR pwstrDefaultDevice) override {
+ SetDefaultAudioDeviceChanged();
+ return S_OK;
+ }
+
+ HRESULT __stdcall QueryInterface(REFIID iid, void** object) override {
+ if (iid == IID_IUnknown || iid == __uuidof(IMMNotificationClient)) {
+ *object = static_cast<IMMNotificationClient*>(this);
+ return S_OK;
+ }
+ *object = nullptr;
+ return E_NOINTERFACE;
+ }
+
+ // No Ops overrides.
+ HRESULT __stdcall OnDeviceAdded(LPCWSTR pwstrDeviceId) override {
+ return S_OK;
+ }
+ HRESULT __stdcall OnDeviceRemoved(LPCWSTR pwstrDeviceId) override {
+ return S_OK;
+ }
+ HRESULT __stdcall OnDeviceStateChanged(LPCWSTR pwstrDeviceId,
+ DWORD dwNewState) override {
+ return S_OK;
+ }
+ HRESULT __stdcall OnPropertyValueChanged(LPCWSTR pwstrDeviceId,
+ const PROPERTYKEY key) override {
+ return S_OK;
+ }
+ ULONG __stdcall AddRef() override { return 1; }
+ ULONG __stdcall Release() override { return 1; }
+
+ bool GetAndResetDefaultAudioDeviceChanged() {
+ base::AutoLock lock(lock_);
+ if (default_audio_device_changed_) {
+ default_audio_device_changed_ = false;
+ return true;
+ }
+ return false;
+ }
+
+ void SetDefaultAudioDeviceChanged() {
+ base::AutoLock lock(lock_);
+ default_audio_device_changed_ = true;
+ }
+
+ private:
+ AudioCapturerWin* const owner_;
+ bool default_audio_device_changed_ = false; // GUARDED_BY(lock_)
Sergey Ulanov 2016/07/22 17:38:37 replace GUARDED_BY with a comment (e.g. "|lock_| m
Hzj_jie 2016/07/22 21:03:11 Done.
+ base::Lock lock_;
+};
+
AudioCapturerWin::AudioCapturerWin()
: sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID),
silence_detector_(kSilenceThreshold),
+ mm_notification_client_(new MMNotificationClient(this)),
last_capture_error_(S_OK) {
- thread_checker_.DetachFromThread();
+ thread_checker_.DetachFromThread();
}
AudioCapturerWin::~AudioCapturerWin() {
@@ -64,22 +128,43 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) {
callback_ = callback;
- // Initialize the capture timer.
+ if (!ResetAndInitialize()) {
+ return false;
+ }
+
+ // Initialize the capture timer and start capturing.
capture_timer_.reset(new base::RepeatingTimer());
+ capture_timer_->Start(FROM_HERE, audio_device_period_, this,
+ &AudioCapturerWin::DoCapture);
+ return true;
+}
- HRESULT hr = S_OK;
+bool AudioCapturerWin::ResetAndInitialize() {
+ wave_format_ex_.Reset(nullptr);
+ mm_device_enumerator_.Release();
+ audio_capture_client_.Release();
+ audio_client_.Release();
+ mm_device_.Release();
+ audio_volume_.Release();
- base::win::ScopedComPtr<IMMDeviceEnumerator> mm_device_enumerator;
- hr = mm_device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator));
+ HRESULT hr = S_OK;
+ hr = mm_device_enumerator_.CreateInstance(__uuidof(MMDeviceEnumerator));
if (FAILED(hr)) {
LOG(ERROR) << "Failed to create IMMDeviceEnumerator. Error " << hr;
return false;
}
+ hr = mm_device_enumerator_->RegisterEndpointNotificationCallback(
+ mm_notification_client_.get());
+ if (FAILED(hr)) {
+ // We cannot predict which kind of error the API may return, but this is
+ // not a fatal error.
+ LOG(ERROR) << "Failed to register IMMNotificationClient. Error " << hr;
+ }
+
// Get the audio endpoint.
- hr = mm_device_enumerator->GetDefaultAudioEndpoint(eRender,
- eConsole,
- mm_device_.Receive());
+ hr = mm_device_enumerator_->GetDefaultAudioEndpoint(eRender, eConsole,
+ mm_device_.Receive());
if (FAILED(hr)) {
LOG(ERROR) << "Failed to get IMMDevice. Error " << hr;
return false;
@@ -209,11 +294,6 @@ bool AudioCapturerWin::Start(const PacketCapturedCallback& callback) {
silence_detector_.Reset(sampling_rate_, kChannels);
- // Start capturing.
- capture_timer_->Start(FROM_HERE,
- audio_device_period_,
- this,
- &AudioCapturerWin::DoCapture);
return true;
}
@@ -284,6 +364,13 @@ void AudioCapturerWin::DoCapture() {
DCHECK(AudioCapturer::IsValidSampleRate(sampling_rate_));
DCHECK(thread_checker_.CalledOnValidThread());
+ if (mm_notification_client_->GetAndResetDefaultAudioDeviceChanged() &&
+ !ResetAndInitialize()) {
Sergey Ulanov 2016/07/22 17:38:37 This expression is hard to read: it's not obvious
Hzj_jie 2016/07/22 21:03:11 Done.
+ // Initialization failed, we should wait for next DoCapture call.
Sergey Ulanov 2016/07/22 17:38:37 When DoCapture() is called again this code won't c
Hzj_jie 2016/07/22 21:03:11 No, SetDefaultAudioDeviceChanged in line 370 will
Sergey Ulanov 2016/07/22 21:29:27 I see. It seems error-prone to piggy-back on that
+ mm_notification_client_->SetDefaultAudioDeviceChanged();
+ return;
+ }
+
// Fetch all packets from the audio capture endpoint buffer.
HRESULT hr = S_OK;
while (true) {
« no previous file with comments | « remoting/host/audio_capturer_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698