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__