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

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
« remoting/host/audio_capturer_win.h ('K') | « 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..3bddd9b300b2e5afb8c95b927cd2bf2e1efca1b0 100644
--- a/remoting/host/audio_capturer_win.cc
+++ b/remoting/host/audio_capturer_win.cc
@@ -40,15 +40,73 @@ const int kMaxExpectedTimerLag = 30;
namespace remoting {
+class AudioCapturerWin::MMNotificationClient : public IMMNotificationClient {
+ public:
+ MMNotificationClient(AudioCapturerWin* owner);
+
+ HRESULT __stdcall OnDefaultDeviceChanged(EDataFlow flow,
+ ERole role,
+ LPCWSTR pwstrDefaultDevice) override;
+
+ HRESULT __stdcall QueryInterface(REFIID iid, void** object) override;
+
+ // 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; }
+
+ private:
+ AudioCapturerWin* owner_;
+};
+
+AudioCapturerWin::MMNotificationClient::MMNotificationClient(
+ AudioCapturerWin* owner)
+ : owner_(owner) {
Sergey Ulanov 2016/07/20 17:28:34 nit: Please either inline all methods in MMNotific
Hzj_jie 2016/07/20 20:43:14 Oh, I thought only functions with only return stat
Sergey Ulanov 2016/07/21 18:54:02 That's for when you define class in a header, whic
+ DCHECK(owner_);
+}
+
+HRESULT AudioCapturerWin::MMNotificationClient::OnDefaultDeviceChanged(
+ EDataFlow flow,
+ ERole role,
+ LPCWSTR pwstrDefaultDevice) {
+ owner_->default_audio_device_changed_ = true;
+ return S_OK;
+}
+
+HRESULT AudioCapturerWin::MMNotificationClient::QueryInterface(REFIID iid,
+ void** object) {
+ if (iid == IID_IUnknown || iid == __uuidof(IMMNotificationClient)) {
+ *object = static_cast<IMMNotificationClient*>(this);
+ return S_OK;
+ }
+ *object = nullptr;
+ return E_NOINTERFACE;
+}
+
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() {
DCHECK(thread_checker_.CalledOnValidThread());
+
if (audio_client_) {
audio_client_->Stop();
}
@@ -64,22 +122,44 @@ 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() {
+ default_audio_device_changed_ = false;
+ 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 +289,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 +359,11 @@ void AudioCapturerWin::DoCapture() {
DCHECK(AudioCapturer::IsValidSampleRate(sampling_rate_));
DCHECK(thread_checker_.CalledOnValidThread());
+ if (default_audio_device_changed_ && !ResetAndInitialize()) {
+ // Initialization failed, we should wait for next DoCapture call.
+ return;
+ }
+
// Fetch all packets from the audio capture endpoint buffer.
HRESULT hr = S_OK;
while (true) {
« remoting/host/audio_capturer_win.h ('K') | « remoting/host/audio_capturer_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698