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