tor-browser

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

AudioInputSource.h (5777B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef DOM_MEDIA_AudioInputSource_H_
      8 #define DOM_MEDIA_AudioInputSource_H_
      9 
     10 #include "AudioDriftCorrection.h"
     11 #include "AudioSegment.h"
     12 #include "CubebInputStream.h"
     13 #include "CubebUtils.h"
     14 #include "TimeUnits.h"
     15 #include "mozilla/MozPromise.h"
     16 #include "mozilla/ProfilerUtils.h"
     17 #include "mozilla/RefPtr.h"
     18 #include "mozilla/SPSCQueue.h"
     19 #include "mozilla/SharedThreadPool.h"
     20 #include "mozilla/Variant.h"
     21 
     22 namespace mozilla {
     23 
     24 // This is an interface to operate an input-only audio stream within a
     25 // cubeb-task thread on a specific thread. Once the class instance is created,
     26 // all its operations must be called on the same thread.
     27 //
     28 // The audio data is periodically produced by the underlying audio stream on the
     29 // stream's callback thread, and can be safely read by GetAudioSegment() on a
     30 // specific thread.
     31 class AudioInputSource : public CubebInputStream::Listener {
     32 public:
     33  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioInputSource, override);
     34 
     35  using Id = uint32_t;
     36 
     37  class EventListener {
     38   public:
     39    NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING;
     40 
     41    // This two events will be fired on main thread.
     42    virtual void AudioDeviceChanged(Id aId) = 0;
     43    enum class State { Started, Stopped, Drained, Error };
     44    virtual void AudioStateCallback(Id aId, State aState) = 0;
     45 
     46   protected:
     47    EventListener() = default;
     48    virtual ~EventListener() = default;
     49  };
     50 
     51  AudioInputSource(RefPtr<EventListener>&& aListener, Id aSourceId,
     52                   CubebUtils::AudioDeviceID aDeviceId, uint32_t aChannelCount,
     53                   bool aIsVoice, const PrincipalHandle& aPrincipalHandle,
     54                   TrackRate aSourceRate, TrackRate aTargetRate);
     55 
     56  // The following functions should always be called in the same thread: They
     57  // are always run on MediaTrackGraph's graph thread.
     58  // Sets up mStream.
     59  void Init();
     60  // Starts producing audio data.
     61  void Start();
     62  // Stops producing audio data.
     63  void Stop();
     64  // Set the params to be applied in the platform for this source.
     65  using SetRequestedProcessingParamsPromise =
     66      MozPromise<cubeb_input_processing_params, int, true>;
     67  RefPtr<SetRequestedProcessingParamsPromise> SetRequestedProcessingParams(
     68      cubeb_input_processing_params aParams);
     69  // Returns the AudioSegment with aDuration of data inside.
     70  // The graph thread can change behind the scene, e.g., cubeb stream reinit due
     71  // to default output device changed). When this happens, we need to notify
     72  // mSPSCQueue to change its data consumer.
     73  enum class Consumer { Same, Changed };
     74  AudioSegment GetAudioSegment(TrackTime aDuration, Consumer aConsumer);
     75 
     76  // CubebInputStream::Listener interface: These are used only for the
     77  // underlying audio stream. No user should call these APIs.
     78  // This will be fired on audio callback thread.
     79  long DataCallback(const void* aBuffer, long aFrames) override;
     80  // This can be fired on any thread.
     81  void StateCallback(cubeb_state aState) override;
     82  // This can be fired on any thread.
     83  void DeviceChangedCallback() override;
     84 
     85  // Any threads:
     86  // The unique id of this source.
     87  const Id mId;
     88  // The id of this audio device producing the data.
     89  const CubebUtils::AudioDeviceID mDeviceId;
     90  // The channel count of audio data produced.
     91  const uint32_t mChannelCount;
     92  // The sample rate of the audio data produced.
     93  const TrackRate mRate;
     94  // Indicate whether the audio stream is for voice or not.
     95  const bool mIsVoice;
     96  // The principal of the audio data produced.
     97  const PrincipalHandle mPrincipalHandle;
     98 
     99 protected:
    100  ~AudioInputSource() = default;
    101 
    102 private:
    103  // Underlying audio thread only.
    104  bool CheckThreadIdChanged();
    105 
    106  // Any thread.
    107  const bool mSandboxed;
    108 
    109  // Thread id of the underlying audio thread. Underlying audio thread only.
    110  std::atomic<ProfilerThreadId> mAudioThreadId;
    111 
    112  // Forward the underlying event from main thread.
    113  const RefPtr<EventListener> mEventListener;
    114 
    115  // Shared thread pool containing only one thread for cubeb operations.
    116  // The cubeb operations: Start() and Stop() will be called on
    117  // MediaTrackGraph's graph thread, which can be the cubeb stream's callback
    118  // thread. Running cubeb operations within cubeb stream callback thread can
    119  // cause the deadlock on Linux, so we dispatch those operations to the task
    120  // thread.
    121  const RefPtr<SharedThreadPool> mTaskThread;
    122 
    123  // Correct the drift between the underlying audio stream and its reader.
    124  AudioDriftCorrection mDriftCorrector;
    125 
    126  // An input-only cubeb stream operated within mTaskThread.
    127  UniquePtr<CubebInputStream> mStream;
    128 
    129  // The params configured on the cubeb stream, after filtering away unsupported
    130  // params. mTaskThread only.
    131  cubeb_input_processing_params mConfiguredProcessingParams =
    132      CUBEB_INPUT_PROCESSING_PARAM_NONE;
    133 
    134  struct Empty {};
    135 
    136  struct LatencyChangeData {
    137    media::TimeUnit mLatency;
    138  };
    139 
    140  struct Data : public Variant<AudioChunk, LatencyChangeData, Empty> {
    141    Data() : Variant(AsVariant(Empty())) {}
    142    explicit Data(AudioChunk&& aChunk)
    143        : Variant(AsVariant(std::move(aChunk))) {}
    144    explicit Data(LatencyChangeData aLatencyChangeData)
    145        : Variant(AsVariant(std::move(aLatencyChangeData))) {}
    146  };
    147 
    148  // A single-producer-single-consumer lock-free queue whose data is produced by
    149  // the audio callback thread and consumed by AudioInputSource's data reader.
    150  SPSCQueue<Data> mSPSCQueue{30};
    151 };
    152 
    153 }  // namespace mozilla
    154 
    155 #endif  // DOM_MEDIA_AudioInputSource_H_