1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef AUDIO_DEVICE_AUDIO_DEVICE_PULSE_LINUX_H_ 12 #define AUDIO_DEVICE_AUDIO_DEVICE_PULSE_LINUX_H_ 13 14 #include <memory> 15 16 #include "modules/audio_device/audio_device_buffer.h" 17 #include "modules/audio_device/audio_device_generic.h" 18 #include "modules/audio_device/include/audio_device.h" 19 #include "modules/audio_device/include/audio_device_defines.h" 20 #include "modules/audio_device/linux/audio_mixer_manager_pulse_linux.h" 21 #include "modules/audio_device/linux/pulseaudiosymboltable_linux.h" 22 #include "rtc_base/event.h" 23 #include "rtc_base/platform_thread.h" 24 #include "rtc_base/synchronization/mutex.h" 25 #include "rtc_base/thread_annotations.h" 26 #include "rtc_base/thread_checker.h" 27 28 #if defined(WEBRTC_USE_X11) 29 #include <X11/Xlib.h> 30 #endif 31 32 #include <pulse/pulseaudio.h> 33 #include <stddef.h> 34 #include <stdint.h> 35 36 // We define this flag if it's missing from our headers, because we want to be 37 // able to compile against old headers but still use PA_STREAM_ADJUST_LATENCY 38 // if run against a recent version of the library. 39 #ifndef PA_STREAM_ADJUST_LATENCY 40 #define PA_STREAM_ADJUST_LATENCY 0x2000U 41 #endif 42 #ifndef PA_STREAM_START_MUTED 43 #define PA_STREAM_START_MUTED 0x1000U 44 #endif 45 46 // Set this constant to 0 to disable latency reading 47 const uint32_t WEBRTC_PA_REPORT_LATENCY = 1; 48 49 // Constants from implementation by Tristan Schmelcher [tschmelcher@google.com] 50 51 // First PulseAudio protocol version that supports PA_STREAM_ADJUST_LATENCY. 52 const uint32_t WEBRTC_PA_ADJUST_LATENCY_PROTOCOL_VERSION = 13; 53 54 // Some timing constants for optimal operation. See 55 // https://tango.0pointer.de/pipermail/pulseaudio-discuss/2008-January/001170.html 56 // for a good explanation of some of the factors that go into this. 57 58 // Playback. 59 60 // For playback, there is a round-trip delay to fill the server-side playback 61 // buffer, so setting too low of a latency is a buffer underflow risk. We will 62 // automatically increase the latency if a buffer underflow does occur, but we 63 // also enforce a sane minimum at start-up time. Anything lower would be 64 // virtually guaranteed to underflow at least once, so there's no point in 65 // allowing lower latencies. 66 const uint32_t WEBRTC_PA_PLAYBACK_LATENCY_MINIMUM_MSECS = 20; 67 68 // Every time a playback stream underflows, we will reconfigure it with target 69 // latency that is greater by this amount. 70 const uint32_t WEBRTC_PA_PLAYBACK_LATENCY_INCREMENT_MSECS = 20; 71 72 // We also need to configure a suitable request size. Too small and we'd burn 73 // CPU from the overhead of transfering small amounts of data at once. Too large 74 // and the amount of data remaining in the buffer right before refilling it 75 // would be a buffer underflow risk. We set it to half of the buffer size. 76 const uint32_t WEBRTC_PA_PLAYBACK_REQUEST_FACTOR = 2; 77 78 // Capture. 79 80 // For capture, low latency is not a buffer overflow risk, but it makes us burn 81 // CPU from the overhead of transfering small amounts of data at once, so we set 82 // a recommended value that we use for the kLowLatency constant (but if the user 83 // explicitly requests something lower then we will honour it). 84 // 1ms takes about 6-7% CPU. 5ms takes about 5%. 10ms takes about 4.x%. 85 const uint32_t WEBRTC_PA_LOW_CAPTURE_LATENCY_MSECS = 10; 86 87 // There is a round-trip delay to ack the data to the server, so the 88 // server-side buffer needs extra space to prevent buffer overflow. 20ms is 89 // sufficient, but there is no penalty to making it bigger, so we make it huge. 90 // (750ms is libpulse's default value for the _total_ buffer size in the 91 // kNoLatencyRequirements case.) 92 const uint32_t WEBRTC_PA_CAPTURE_BUFFER_EXTRA_MSECS = 750; 93 94 const uint32_t WEBRTC_PA_MSECS_PER_SEC = 1000; 95 96 // Init _configuredLatencyRec/Play to this value to disable latency requirements 97 const int32_t WEBRTC_PA_NO_LATENCY_REQUIREMENTS = -1; 98 99 // Set this const to 1 to account for peeked and used data in latency 100 // calculation 101 const uint32_t WEBRTC_PA_CAPTURE_BUFFER_LATENCY_ADJUSTMENT = 0; 102 103 typedef webrtc::adm_linux_pulse::PulseAudioSymbolTable WebRTCPulseSymbolTable; 104 WebRTCPulseSymbolTable* GetPulseSymbolTable(); 105 106 namespace webrtc { 107 108 class AudioDeviceLinuxPulse : public AudioDeviceGeneric { 109 public: 110 AudioDeviceLinuxPulse(); 111 virtual ~AudioDeviceLinuxPulse(); 112 113 // Retrieve the currently utilized audio layer 114 int32_t ActiveAudioLayer( 115 AudioDeviceModule::AudioLayer& audioLayer) const override; 116 117 // Main initializaton and termination 118 InitStatus Init() override; 119 int32_t Terminate() RTC_LOCKS_EXCLUDED(mutex_) override; 120 bool Initialized() const override; 121 122 // Device enumeration 123 int16_t PlayoutDevices() override; 124 int16_t RecordingDevices() override; 125 int32_t PlayoutDeviceName(uint16_t index, 126 char name[kAdmMaxDeviceNameSize], 127 char guid[kAdmMaxGuidSize]) override; 128 int32_t RecordingDeviceName(uint16_t index, 129 char name[kAdmMaxDeviceNameSize], 130 char guid[kAdmMaxGuidSize]) override; 131 132 // Device selection 133 int32_t SetPlayoutDevice(uint16_t index) override; 134 int32_t SetPlayoutDevice( 135 AudioDeviceModule::WindowsDeviceType device) override; 136 int32_t SetRecordingDevice(uint16_t index) override; 137 int32_t SetRecordingDevice( 138 AudioDeviceModule::WindowsDeviceType device) override; 139 140 // Audio transport initialization 141 int32_t PlayoutIsAvailable(bool& available) override; 142 int32_t InitPlayout() RTC_LOCKS_EXCLUDED(mutex_) override; 143 bool PlayoutIsInitialized() const override; 144 int32_t RecordingIsAvailable(bool& available) override; 145 int32_t InitRecording() override; 146 bool RecordingIsInitialized() const override; 147 148 // Audio transport control 149 int32_t StartPlayout() RTC_LOCKS_EXCLUDED(mutex_) override; 150 int32_t StopPlayout() RTC_LOCKS_EXCLUDED(mutex_) override; 151 bool Playing() const override; 152 int32_t StartRecording() RTC_LOCKS_EXCLUDED(mutex_) override; 153 int32_t StopRecording() RTC_LOCKS_EXCLUDED(mutex_) override; 154 bool Recording() const override; 155 156 // Audio mixer initialization 157 int32_t InitSpeaker() override; 158 bool SpeakerIsInitialized() const override; 159 int32_t InitMicrophone() override; 160 bool MicrophoneIsInitialized() const override; 161 162 // Speaker volume controls 163 int32_t SpeakerVolumeIsAvailable(bool& available) override; 164 int32_t SetSpeakerVolume(uint32_t volume) override; 165 int32_t SpeakerVolume(uint32_t& volume) const override; 166 int32_t MaxSpeakerVolume(uint32_t& maxVolume) const override; 167 int32_t MinSpeakerVolume(uint32_t& minVolume) const override; 168 169 // Microphone volume controls 170 int32_t MicrophoneVolumeIsAvailable(bool& available) override; 171 int32_t SetMicrophoneVolume(uint32_t volume) override; 172 int32_t MicrophoneVolume(uint32_t& volume) const override; 173 int32_t MaxMicrophoneVolume(uint32_t& maxVolume) const override; 174 int32_t MinMicrophoneVolume(uint32_t& minVolume) const override; 175 176 // Speaker mute control 177 int32_t SpeakerMuteIsAvailable(bool& available) override; 178 int32_t SetSpeakerMute(bool enable) override; 179 int32_t SpeakerMute(bool& enabled) const override; 180 181 // Microphone mute control 182 int32_t MicrophoneMuteIsAvailable(bool& available) override; 183 int32_t SetMicrophoneMute(bool enable) override; 184 int32_t MicrophoneMute(bool& enabled) const override; 185 186 // Stereo support 187 int32_t StereoPlayoutIsAvailable(bool& available) override; 188 int32_t SetStereoPlayout(bool enable) override; 189 int32_t StereoPlayout(bool& enabled) const override; 190 int32_t StereoRecordingIsAvailable(bool& available) override; 191 int32_t SetStereoRecording(bool enable) override; 192 int32_t StereoRecording(bool& enabled) const override; 193 194 // Delay information and control 195 int32_t PlayoutDelay(uint16_t& delayMS) const 196 RTC_LOCKS_EXCLUDED(mutex_) override; 197 198 void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override; 199 200 private: Lock()201 void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION(mutex_) { mutex_.Lock(); } UnLock()202 void UnLock() RTC_UNLOCK_FUNCTION(mutex_) { mutex_.Unlock(); } 203 void WaitForOperationCompletion(pa_operation* paOperation) const; 204 void WaitForSuccess(pa_operation* paOperation) const; 205 206 bool KeyPressed() const; 207 208 static void PaContextStateCallback(pa_context* c, void* pThis); 209 static void PaSinkInfoCallback(pa_context* c, 210 const pa_sink_info* i, 211 int eol, 212 void* pThis); 213 static void PaSourceInfoCallback(pa_context* c, 214 const pa_source_info* i, 215 int eol, 216 void* pThis); 217 static void PaServerInfoCallback(pa_context* c, 218 const pa_server_info* i, 219 void* pThis); 220 static void PaStreamStateCallback(pa_stream* p, void* pThis); 221 void PaContextStateCallbackHandler(pa_context* c); 222 void PaSinkInfoCallbackHandler(const pa_sink_info* i, int eol); 223 void PaSourceInfoCallbackHandler(const pa_source_info* i, int eol); 224 void PaServerInfoCallbackHandler(const pa_server_info* i); 225 void PaStreamStateCallbackHandler(pa_stream* p); 226 227 void EnableWriteCallback(); 228 void DisableWriteCallback(); 229 static void PaStreamWriteCallback(pa_stream* unused, 230 size_t buffer_space, 231 void* pThis); 232 void PaStreamWriteCallbackHandler(size_t buffer_space); 233 static void PaStreamUnderflowCallback(pa_stream* unused, void* pThis); 234 void PaStreamUnderflowCallbackHandler(); 235 void EnableReadCallback(); 236 void DisableReadCallback(); 237 static void PaStreamReadCallback(pa_stream* unused1, 238 size_t unused2, 239 void* pThis); 240 void PaStreamReadCallbackHandler(); 241 static void PaStreamOverflowCallback(pa_stream* unused, void* pThis); 242 void PaStreamOverflowCallbackHandler(); 243 int32_t LatencyUsecs(pa_stream* stream); 244 int32_t ReadRecordedData(const void* bufferData, size_t bufferSize); 245 int32_t ProcessRecordedData(int8_t* bufferData, 246 uint32_t bufferSizeInSamples, 247 uint32_t recDelay); 248 249 int32_t CheckPulseAudioVersion(); 250 int32_t InitSamplingFrequency(); 251 int32_t GetDefaultDeviceInfo(bool recDevice, char* name, uint16_t& index); 252 int32_t InitPulseAudio(); 253 int32_t TerminatePulseAudio(); 254 255 void PaLock(); 256 void PaUnLock(); 257 258 static void RecThreadFunc(void*); 259 static void PlayThreadFunc(void*); 260 bool RecThreadProcess() RTC_LOCKS_EXCLUDED(mutex_); 261 bool PlayThreadProcess() RTC_LOCKS_EXCLUDED(mutex_); 262 263 AudioDeviceBuffer* _ptrAudioBuffer; 264 265 mutable Mutex mutex_; 266 rtc::Event _timeEventRec; 267 rtc::Event _timeEventPlay; 268 rtc::Event _recStartEvent; 269 rtc::Event _playStartEvent; 270 271 // TODO(pbos): Remove unique_ptr and use directly without resetting. 272 std::unique_ptr<rtc::PlatformThread> _ptrThreadPlay; 273 std::unique_ptr<rtc::PlatformThread> _ptrThreadRec; 274 275 AudioMixerManagerLinuxPulse _mixerManager; 276 277 uint16_t _inputDeviceIndex; 278 uint16_t _outputDeviceIndex; 279 bool _inputDeviceIsSpecified; 280 bool _outputDeviceIsSpecified; 281 282 int sample_rate_hz_; 283 uint8_t _recChannels; 284 uint8_t _playChannels; 285 286 // Stores thread ID in constructor. 287 // We can then use ThreadChecker::IsCurrent() to ensure that 288 // other methods are called from the same thread. 289 // Currently only does RTC_DCHECK(thread_checker_.IsCurrent()). 290 rtc::ThreadChecker thread_checker_; 291 292 bool _initialized; 293 bool _recording; 294 bool _playing; 295 bool _recIsInitialized; 296 bool _playIsInitialized; 297 bool _startRec; 298 bool _startPlay; 299 bool update_speaker_volume_at_startup_; 300 bool quit_ RTC_GUARDED_BY(&mutex_); 301 302 uint32_t _sndCardPlayDelay RTC_GUARDED_BY(&mutex_); 303 304 int32_t _writeErrors; 305 306 uint16_t _deviceIndex; 307 int16_t _numPlayDevices; 308 int16_t _numRecDevices; 309 char* _playDeviceName; 310 char* _recDeviceName; 311 char* _playDisplayDeviceName; 312 char* _recDisplayDeviceName; 313 char _paServerVersion[32]; 314 315 int8_t* _playBuffer; 316 size_t _playbackBufferSize; 317 size_t _playbackBufferUnused; 318 size_t _tempBufferSpace; 319 int8_t* _recBuffer; 320 size_t _recordBufferSize; 321 size_t _recordBufferUsed; 322 const void* _tempSampleData; 323 size_t _tempSampleDataSize; 324 int32_t _configuredLatencyPlay; 325 int32_t _configuredLatencyRec; 326 327 // PulseAudio 328 uint16_t _paDeviceIndex; 329 bool _paStateChanged; 330 331 pa_threaded_mainloop* _paMainloop; 332 pa_mainloop_api* _paMainloopApi; 333 pa_context* _paContext; 334 335 pa_stream* _recStream; 336 pa_stream* _playStream; 337 uint32_t _recStreamFlags; 338 uint32_t _playStreamFlags; 339 pa_buffer_attr _playBufferAttr; 340 pa_buffer_attr _recBufferAttr; 341 342 char _oldKeyState[32]; 343 #if defined(WEBRTC_USE_X11) 344 Display* _XDisplay; 345 #endif 346 }; 347 348 } // namespace webrtc 349 350 #endif // MODULES_AUDIO_DEVICE_MAIN_SOURCE_LINUX_AUDIO_DEVICE_PULSE_LINUX_H_ 351