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() 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() 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() override; 150 int32_t StopPlayout() override; 151 bool Playing() const override; 152 int32_t StartRecording() override; 153 int32_t StopRecording() 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 override; 196 197 void AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) override; 198 199 private: Lock()200 void Lock() RTC_EXCLUSIVE_LOCK_FUNCTION(mutex_) { mutex_.Lock(); } UnLock()201 void UnLock() RTC_UNLOCK_FUNCTION(mutex_) { mutex_.Unlock(); } 202 void WaitForOperationCompletion(pa_operation* paOperation) const; 203 void WaitForSuccess(pa_operation* paOperation) const; 204 205 bool KeyPressed() const; 206 207 static void PaContextStateCallback(pa_context* c, void* pThis); 208 static void PaSinkInfoCallback(pa_context* c, 209 const pa_sink_info* i, 210 int eol, 211 void* pThis); 212 static void PaSourceInfoCallback(pa_context* c, 213 const pa_source_info* i, 214 int eol, 215 void* pThis); 216 static void PaServerInfoCallback(pa_context* c, 217 const pa_server_info* i, 218 void* pThis); 219 static void PaStreamStateCallback(pa_stream* p, void* pThis); 220 void PaContextStateCallbackHandler(pa_context* c); 221 void PaSinkInfoCallbackHandler(const pa_sink_info* i, int eol); 222 void PaSourceInfoCallbackHandler(const pa_source_info* i, int eol); 223 void PaServerInfoCallbackHandler(const pa_server_info* i); 224 void PaStreamStateCallbackHandler(pa_stream* p); 225 226 void EnableWriteCallback(); 227 void DisableWriteCallback(); 228 static void PaStreamWriteCallback(pa_stream* unused, 229 size_t buffer_space, 230 void* pThis); 231 void PaStreamWriteCallbackHandler(size_t buffer_space); 232 static void PaStreamUnderflowCallback(pa_stream* unused, void* pThis); 233 void PaStreamUnderflowCallbackHandler(); 234 void EnableReadCallback(); 235 void DisableReadCallback(); 236 static void PaStreamReadCallback(pa_stream* unused1, 237 size_t unused2, 238 void* pThis); 239 void PaStreamReadCallbackHandler(); 240 static void PaStreamOverflowCallback(pa_stream* unused, void* pThis); 241 void PaStreamOverflowCallbackHandler(); 242 int32_t LatencyUsecs(pa_stream* stream); 243 int32_t ReadRecordedData(const void* bufferData, size_t bufferSize); 244 int32_t ProcessRecordedData(int8_t* bufferData, 245 uint32_t bufferSizeInSamples, 246 uint32_t recDelay); 247 248 int32_t CheckPulseAudioVersion(); 249 int32_t InitSamplingFrequency(); 250 int32_t GetDefaultDeviceInfo(bool recDevice, char* name, uint16_t& index); 251 int32_t InitPulseAudio(); 252 int32_t TerminatePulseAudio(); 253 254 void PaLock(); 255 void PaUnLock(); 256 257 static void RecThreadFunc(void*); 258 static void PlayThreadFunc(void*); 259 bool RecThreadProcess(); 260 bool PlayThreadProcess(); 261 262 AudioDeviceBuffer* _ptrAudioBuffer; 263 264 mutable Mutex mutex_; 265 rtc::Event _timeEventRec; 266 rtc::Event _timeEventPlay; 267 rtc::Event _recStartEvent; 268 rtc::Event _playStartEvent; 269 270 // TODO(pbos): Remove unique_ptr and use directly without resetting. 271 std::unique_ptr<rtc::PlatformThread> _ptrThreadPlay; 272 std::unique_ptr<rtc::PlatformThread> _ptrThreadRec; 273 274 AudioMixerManagerLinuxPulse _mixerManager; 275 276 uint16_t _inputDeviceIndex; 277 uint16_t _outputDeviceIndex; 278 bool _inputDeviceIsSpecified; 279 bool _outputDeviceIsSpecified; 280 281 int sample_rate_hz_; 282 uint8_t _recChannels; 283 uint8_t _playChannels; 284 285 // Stores thread ID in constructor. 286 // We can then use ThreadChecker::IsCurrent() to ensure that 287 // other methods are called from the same thread. 288 // Currently only does RTC_DCHECK(thread_checker_.IsCurrent()). 289 rtc::ThreadChecker thread_checker_; 290 291 bool _initialized; 292 bool _recording; 293 bool _playing; 294 bool _recIsInitialized; 295 bool _playIsInitialized; 296 bool _startRec; 297 bool _startPlay; 298 bool update_speaker_volume_at_startup_; 299 bool quit_ RTC_GUARDED_BY(&mutex_); 300 301 uint32_t _sndCardPlayDelay RTC_GUARDED_BY(&mutex_); 302 303 int32_t _writeErrors; 304 305 uint16_t _deviceIndex; 306 int16_t _numPlayDevices; 307 int16_t _numRecDevices; 308 char* _playDeviceName; 309 char* _recDeviceName; 310 char* _playDisplayDeviceName; 311 char* _recDisplayDeviceName; 312 char _paServerVersion[32]; 313 314 int8_t* _playBuffer; 315 size_t _playbackBufferSize; 316 size_t _playbackBufferUnused; 317 size_t _tempBufferSpace; 318 int8_t* _recBuffer; 319 size_t _recordBufferSize; 320 size_t _recordBufferUsed; 321 const void* _tempSampleData; 322 size_t _tempSampleDataSize; 323 int32_t _configuredLatencyPlay; 324 int32_t _configuredLatencyRec; 325 326 // PulseAudio 327 uint16_t _paDeviceIndex; 328 bool _paStateChanged; 329 330 pa_threaded_mainloop* _paMainloop; 331 pa_mainloop_api* _paMainloopApi; 332 pa_context* _paContext; 333 334 pa_stream* _recStream; 335 pa_stream* _playStream; 336 uint32_t _recStreamFlags; 337 uint32_t _playStreamFlags; 338 pa_buffer_attr _playBufferAttr; 339 pa_buffer_attr _recBufferAttr; 340 341 char _oldKeyState[32]; 342 #if defined(WEBRTC_USE_X11) 343 Display* _XDisplay; 344 #endif 345 }; 346 347 } // namespace webrtc 348 349 #endif // MODULES_AUDIO_DEVICE_MAIN_SOURCE_LINUX_AUDIO_DEVICE_PULSE_LINUX_H_ 350