tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

audio_device_pulse_linux.h (13000B)


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