tor-browser

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

AudioSink.h (6446B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
      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 http://mozilla.org/MPL/2.0/. */
      6 #ifndef AudioSink_h__
      7 #define AudioSink_h__
      8 
      9 #include "AudibilityMonitor.h"
     10 #include "AudioStream.h"
     11 #include "MediaEventSource.h"
     12 #include "MediaInfo.h"
     13 #include "MediaQueue.h"
     14 #include "MediaSink.h"
     15 #include "mozilla/Atomics.h"
     16 #include "mozilla/Maybe.h"
     17 #include "mozilla/Monitor.h"
     18 #include "mozilla/MozPromise.h"
     19 #include "mozilla/RefPtr.h"
     20 #include "nsISupportsImpl.h"
     21 
     22 namespace mozilla {
     23 
     24 class AudioConverter;
     25 
     26 class AudioSink : private AudioStream::DataSource {
     27 public:
     28  enum class InitializationType {
     29    // This AudioSink is being initialized for the first time
     30    INITIAL,
     31    UNMUTING
     32  };
     33  struct PlaybackParams {
     34    PlaybackParams(double aVolume, double aPlaybackRate, bool aPreservesPitch)
     35        : mVolume(aVolume),
     36          mPlaybackRate(aPlaybackRate),
     37          mPreservesPitch(aPreservesPitch) {}
     38    double mVolume;
     39    double mPlaybackRate;
     40    bool mPreservesPitch;
     41  };
     42 
     43  AudioSink(AbstractThread* aThread, MediaQueue<AudioData>& aAudioQueue,
     44            const AudioInfo& aInfo, bool aShouldResistFingerprinting);
     45 
     46  ~AudioSink();
     47 
     48  // Allocate and initialize mAudioStream. Returns NS_OK on success.
     49  nsresult InitializeAudioStream(const RefPtr<AudioDeviceInfo>& aAudioDevice,
     50                                 InitializationType aInitializationType);
     51 
     52  // Start audio playback.  aStartTime is compared with MediaData::mTime to
     53  // identify the first audio frame to be played.
     54  RefPtr<MediaSink::EndedPromise> Start(const PlaybackParams& aParams,
     55                                        const media::TimeUnit& aStartTime);
     56 
     57  /*
     58   * All public functions are not thread-safe.
     59   * Called on the task queue of MDSM only.
     60   */
     61  media::TimeUnit GetPosition();
     62  media::TimeUnit GetEndTime() const;
     63 
     64  // Check whether we've pushed more frames to the audio stream than it
     65  // has played.
     66  bool HasUnplayedFrames();
     67 
     68  // The duration of the buffered frames.
     69  media::TimeUnit UnplayedDuration() const;
     70 
     71  // Shut down the AudioSink's resources.
     72  void ShutDown();
     73 
     74  void SetVolume(double aVolume);
     75  void SetStreamName(const nsAString& aStreamName);
     76  void SetPlaybackRate(double aPlaybackRate);
     77  void SetPreservesPitch(bool aPreservesPitch);
     78  void SetPlaying(bool aPlaying);
     79 
     80  MediaEventSource<bool>& AudibleEvent() { return mAudibleEvent; }
     81 
     82  void GetDebugInfo(dom::MediaSinkDebugInfo& aInfo);
     83 
     84  // This returns true if the audio callbacks are being called, and so the
     85  // audio stream-based clock is moving forward.
     86  bool AudioStreamCallbackStarted() {
     87    return mAudioStream && mAudioStream->CallbackStarted();
     88  }
     89 
     90  void UpdateStartTime(const media::TimeUnit& aStartTime) {
     91    mStartTime = aStartTime;
     92  }
     93 
     94 private:
     95  // Interface of AudioStream::DataSource.
     96  // Called on the callback thread of cubeb. Returns the number of frames that
     97  // were available.
     98  uint32_t PopFrames(AudioDataValue* aBuffer, uint32_t aFrames,
     99                     bool aAudioThreadChanged) override;
    100  bool Ended() const override;
    101 
    102  // When shutting down, it's important to not lose any audio data, it might be
    103  // still of use, in two scenarios:
    104  // - If the audio is now captured to a MediaStream, whatever is enqueued in
    105  // the ring buffer needs to be played out now ;
    106  // - If the AudioSink is shutting down because the audio is muted, it's
    107  // important to keep the audio around in case it's quickly unmuted,
    108  // and in general to keep A/V sync correct when unmuted.
    109  void ReenqueueUnplayedAudioDataIfNeeded();
    110 
    111  void CheckIsAudible(const Span<AudioDataValue>& aInterleaved,
    112                      size_t aChannel);
    113 
    114  // The audio stream resource. Used on the task queue of MDSM only.
    115  RefPtr<AudioStream> mAudioStream;
    116 
    117  // The media data time of the first audio frame that was played.
    118  // We can add this to the audio stream position to determine
    119  // the current audio data time.
    120  media::TimeUnit mStartTime;
    121 
    122  // Keep the last good position returned from the audio stream. Used to ensure
    123  // position returned by GetPosition() is mono-increasing in spite of audio
    124  // stream error. Used on the task queue of MDSM only.
    125  media::TimeUnit mLastGoodPosition;
    126 
    127  // Used on the task queue of MDSM only.
    128  bool mPlaying;
    129 
    130  // PCM frames written to the stream so far. Written on the callback thread,
    131  // read on the MDSM thread.
    132  Atomic<int64_t> mWritten;
    133 
    134  // True if there is any error in processing audio data like overflow.
    135  Atomic<bool> mErrored;
    136 
    137  const RefPtr<AbstractThread> mOwnerThread;
    138 
    139  // Audio Processing objects and methods
    140  void OnAudioPopped();
    141  void OnAudioPushed(const RefPtr<AudioData>& aSample);
    142  void NotifyAudioNeeded();
    143  // Drain the converter and add the output to the processed audio queue.
    144  // A maximum of aMaxFrames will be added.
    145  uint32_t DrainConverter(uint32_t aMaxFrames = UINT32_MAX);
    146  already_AddRefed<AudioData> CreateAudioFromBuffer(
    147      AlignedAudioBuffer&& aBuffer, AudioData* aReference);
    148  // Add data to the processsed queue return the number of frames added.
    149  uint32_t PushProcessedAudio(AudioData* aData);
    150  uint32_t AudioQueuedInRingBufferMS() const;
    151  uint32_t SampleToFrame(uint32_t aSamples) const;
    152  UniquePtr<AudioConverter> mConverter;
    153  UniquePtr<SPSCQueue<AudioDataValue>> mProcessedSPSCQueue;
    154  MediaEventListener mAudioQueueListener;
    155  MediaEventListener mAudioQueueFinishListener;
    156  MediaEventListener mProcessedQueueListener;
    157  // Number of frames processed from mAudioQueue. Used to determine gaps in
    158  // the input stream. It indicates the time in frames since playback started
    159  // at the current input framerate.
    160  int64_t mFramesParsed;
    161  Maybe<RefPtr<AudioData>> mLastProcessedPacket;
    162  media::TimeUnit mLastEndTime;
    163  // Never modifed after construction.
    164  uint32_t mOutputRate;
    165  uint32_t mOutputChannels;
    166  AudibilityMonitor mAudibilityMonitor;
    167  bool mIsAudioDataAudible;
    168  MediaEventProducer<bool> mAudibleEvent;
    169  // Only signed on the real-time audio thread.
    170  MediaEventProducer<void> mAudioPopped;
    171 
    172  Atomic<bool> mProcessedQueueFinished;
    173  MediaQueue<AudioData>& mAudioQueue;
    174  const float mProcessedQueueThresholdMS;
    175 };
    176 
    177 }  // namespace mozilla
    178 
    179 #endif  // AudioSink_h__