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