From cf1b6aec300a843134c4143bd738cd69b9c36382 Mon Sep 17 00:00:00 2001 From: "xians@webrtc.org" Date: Mon, 27 Feb 2012 17:22:49 +0000 Subject: [PATCH] iReduced the flakiness of the volume tests in linux pulseaudio Review URL: https://webrtc-codereview.appspot.com/390013 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1774 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../source/linux/audio_device_pulse_linux.cc | 37 +++- .../linux/audio_mixer_manager_pulse_linux.cc | 194 +++++++++--------- .../linux/audio_mixer_manager_pulse_linux.h | 6 +- 3 files changed, 124 insertions(+), 113 deletions(-) diff --git a/src/modules/audio_device/main/source/linux/audio_device_pulse_linux.cc b/src/modules/audio_device/main/source/linux/audio_device_pulse_linux.cc index 337410a13a..16e1d33cab 100644 --- a/src/modules/audio_device/main/source/linux/audio_device_pulse_linux.cc +++ b/src/modules/audio_device/main/source/linux/audio_device_pulse_linux.cc @@ -784,7 +784,14 @@ WebRtc_Word32 AudioDeviceLinuxPulse::MicrophoneBoost(bool& enabled) const WebRtc_Word32 AudioDeviceLinuxPulse::StereoRecordingIsAvailable(bool& available) { + if (_recChannels == 2 && _recording) { + available = true; + return 0; + } + + available = false; bool wasInitialized = _mixerManager.MicrophoneIsInitialized(); + int error = 0; if (!wasInitialized && InitMicrophone() == -1) { @@ -794,10 +801,11 @@ WebRtc_Word32 AudioDeviceLinuxPulse::StereoRecordingIsAvailable(bool& available) } #ifndef WEBRTC_PA_GTALK - // Check if the selected microphone can record stereo + // Check if the selected microphone can record stereo. bool isAvailable(false); - _mixerManager.StereoRecordingIsAvailable(isAvailable); - available = isAvailable; + error = _mixerManager.StereoRecordingIsAvailable(isAvailable); + if (!error) + available = isAvailable; #endif // Close the initialized input mixer @@ -806,7 +814,7 @@ WebRtc_Word32 AudioDeviceLinuxPulse::StereoRecordingIsAvailable(bool& available) _mixerManager.CloseMicrophone(); } - return 0; + return error; } WebRtc_Word32 AudioDeviceLinuxPulse::SetStereoRecording(bool enable) @@ -836,20 +844,27 @@ WebRtc_Word32 AudioDeviceLinuxPulse::StereoRecording(bool& enabled) const WebRtc_Word32 AudioDeviceLinuxPulse::StereoPlayoutIsAvailable(bool& available) { + if (_playChannels == 2 && _playing) { + available = true; + return 0; + } + + available = false; bool wasInitialized = _mixerManager.SpeakerIsInitialized(); + int error = 0; if (!wasInitialized && InitSpeaker() == -1) { - // Cannot open the specified device - available = false; - return 0; + // Cannot open the specified device. + return -1; } #ifndef WEBRTC_PA_GTALK - // Check if the selected microphone can record stereo + // Check if the selected speaker can play stereo. bool isAvailable(false); - _mixerManager.StereoPlayoutIsAvailable(isAvailable); - available = isAvailable; + error = _mixerManager.StereoPlayoutIsAvailable(isAvailable); + if (!error) + available = isAvailable; #endif // Close the initialized input mixer @@ -858,7 +873,7 @@ WebRtc_Word32 AudioDeviceLinuxPulse::StereoPlayoutIsAvailable(bool& available) _mixerManager.CloseSpeaker(); } - return 0; + return error; } WebRtc_Word32 AudioDeviceLinuxPulse::SetStereoPlayout(bool enable) diff --git a/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.cc b/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.cc index ba59ffa720..01f5172702 100644 --- a/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.cc +++ b/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.cc @@ -24,6 +24,8 @@ extern webrtc_adm_linux_pulse::PulseAudioSymbolTable PaSymbolTable; namespace webrtc { +enum { kMaxRetryOnFailure = 2 }; + AudioMixerManagerLinuxPulse::AudioMixerManagerLinuxPulse(const WebRtc_Word32 id) : _critSect(*CriticalSectionWrapper::CreateCriticalSection()), _id(id), @@ -315,27 +317,8 @@ AudioMixerManagerLinuxPulse::SpeakerVolume(WebRtc_UWord32& volume) const != PA_STREAM_UNCONNECTED)) { // We can only get the volume if we have a connected stream - pa_operation* paOperation = NULL; - ResetCallbackVariables(); - PaLock(); - - // Get info for this stream (sink input) - paOperation = LATE(pa_context_get_sink_input_info)( - _paContext, - LATE(pa_stream_get_index)(_paPlayStream), - PaSinkInputInfoCallback, - (void*) this); - - WaitForOperationCompletion(paOperation); - PaUnLock(); - - if (!_callbackValues) - { - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, - "Error getting output volume: %d", - LATE(pa_context_errno)(_paContext)); - return -1; - } + if (!GetSinkInputInfo()) + return -1; volume = static_cast (_paVolume); ResetCallbackVariables(); @@ -513,27 +496,8 @@ WebRtc_Word32 AudioMixerManagerLinuxPulse::SpeakerMute(bool& enabled) const != PA_STREAM_UNCONNECTED)) { // We can only get the mute status if we have a connected stream - pa_operation* paOperation = NULL; - ResetCallbackVariables(); - PaLock(); - - // Get info for this stream (sink input) - paOperation = LATE(pa_context_get_sink_input_info)( - _paContext, - LATE(pa_stream_get_index)(_paPlayStream), - PaSinkInputInfoCallback, - (void*) this); - - WaitForOperationCompletion(paOperation); - PaUnLock(); - - if (!_callbackValues) - { - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, - "Error getting output volume: %d", - LATE(pa_context_errno)(_paContext)); - return -1; - } + if (!GetSinkInputInfo()) + return -1; enabled = static_cast (_paMute); ResetCallbackVariables(); @@ -572,33 +536,13 @@ AudioMixerManagerLinuxPulse::StereoPlayoutIsAvailable(bool& available) deviceIndex = LATE(pa_stream_get_device_index)(_paPlayStream); } - pa_operation* paOperation = NULL; - ResetCallbackVariables(); - - // Get info for this sink - // We want to know if the actual device can play out in stereo - paOperation = LATE(pa_context_get_sink_info_by_index)(_paContext, - deviceIndex, - PaSinkInfoCallback, - (void*) this); - - WaitForOperationCompletion(paOperation); PaUnLock(); - if (!_callbackValues) - { - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, - "Error getting number of output channels: %d", - LATE(pa_context_errno)(_paContext)); - return -1; - } + if (!GetSinkInfoByIndex(deviceIndex)) + return -1; available = static_cast (_paChannels == 2); - WEBRTC_TRACE(kTraceInfo, kTraceAudioDevice, _id, - " AudioMixerManagerLinuxPulse::StereoPlayoutIsAvailable() " - "=> available=%i, available"); - // Reset members modified by callback ResetCallbackVariables(); @@ -762,26 +706,10 @@ WebRtc_Word32 AudioMixerManagerLinuxPulse::MicrophoneMute(bool& enabled) const deviceIndex = LATE(pa_stream_get_device_index)(_paRecStream); } - pa_operation* paOperation = NULL; - ResetCallbackVariables(); - - // Get info for this source - paOperation - = LATE(pa_context_get_source_info_by_index)(_paContext, deviceIndex, - PaSourceInfoCallback, - (void*) this); - - WaitForOperationCompletion(paOperation); - PaUnLock(); - if (!_callbackValues) - { - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, - "Error getting input mute status: %d", - LATE(pa_context_errno)(_paContext)); - return -1; - } + if (!GetSourceInfoByIndex(deviceIndex)) + return -1; enabled = static_cast (_paMute); @@ -997,26 +925,10 @@ AudioMixerManagerLinuxPulse::MicrophoneVolume(WebRtc_UWord32& volume) const deviceIndex = LATE(pa_stream_get_device_index)(_paRecStream); } - pa_operation* paOperation = NULL; - ResetCallbackVariables(); - - // Get info for this source - paOperation - = LATE(pa_context_get_source_info_by_index)(_paContext, deviceIndex, - PaSourceInfoCallback, - (void*) this); - - WaitForOperationCompletion(paOperation); - PaUnLock(); - if (!_callbackValues) - { - WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, - "Error getting input volume: %d", - LATE(pa_context_errno)(_paContext)); - return -1; - } + if (!GetSourceInfoByIndex(deviceIndex)) + return -1; volume = static_cast (_paVolume); @@ -1197,7 +1109,7 @@ void AudioMixerManagerLinuxPulse::PaSinkInputInfoCallbackHandler( { if (eol) { - // Signal that we are done + // Signal that we are done. LATE(pa_threaded_mainloop_signal)(_paMainloop, 0); return; } @@ -1276,4 +1188,84 @@ void AudioMixerManagerLinuxPulse::PaUnLock() const LATE(pa_threaded_mainloop_unlock)(_paMainloop); } +bool AudioMixerManagerLinuxPulse::GetSinkInputInfo() const { + pa_operation* paOperation = NULL; + ResetCallbackVariables(); + + PaLock(); + for (int retries = 0; retries < kMaxRetryOnFailure && !_callbackValues; + retries ++) { + // Get info for this stream (sink input). + paOperation = LATE(pa_context_get_sink_input_info)( + _paContext, + LATE(pa_stream_get_index)(_paPlayStream), + PaSinkInputInfoCallback, + (void*) this); + + WaitForOperationCompletion(paOperation); + } + PaUnLock(); + + if (!_callbackValues) { + WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, + "GetSinkInputInfo failed to get volume info : %d", + LATE(pa_context_errno)(_paContext)); + return false; + } + + return true; } + +bool AudioMixerManagerLinuxPulse::GetSinkInfoByIndex( + int device_index) const { + pa_operation* paOperation = NULL; + ResetCallbackVariables(); + + PaLock(); + for (int retries = 0; retries < kMaxRetryOnFailure && !_callbackValues; + retries ++) { + paOperation = LATE(pa_context_get_sink_info_by_index)(_paContext, + device_index, PaSinkInfoCallback, (void*) this); + + WaitForOperationCompletion(paOperation); + } + PaUnLock(); + + if (!_callbackValues) { + WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, + "GetSinkInfoByIndex failed to get volume info: %d", + LATE(pa_context_errno)(_paContext)); + return false; + } + + return true; +} + +bool AudioMixerManagerLinuxPulse::GetSourceInfoByIndex( + int device_index) const { + pa_operation* paOperation = NULL; + ResetCallbackVariables(); + + PaLock(); + for (int retries = 0; retries < kMaxRetryOnFailure && !_callbackValues; + retries ++) { + paOperation = LATE(pa_context_get_source_info_by_index)( + _paContext, device_index, PaSourceInfoCallback, (void*) this); + + WaitForOperationCompletion(paOperation); + } + + PaUnLock(); + + if (!_callbackValues) { + WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id, + "GetSourceInfoByIndex error: %d", + LATE(pa_context_errno)(_paContext)); + return false; + } + + return true; +} + +} + diff --git a/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.h b/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.h index a2f71f3adc..22d6da59a8 100644 --- a/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.h +++ b/src/modules/audio_device/main/source/linux/audio_mixer_manager_pulse_linux.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -87,6 +87,10 @@ private: void PaLock() const; void PaUnLock() const; + bool GetSinkInputInfo() const; + bool GetSinkInfoByIndex(int device_index)const ; + bool GetSourceInfoByIndex(int device_index) const; + private: CriticalSectionWrapper& _critSect; WebRtc_Word32 _id;