Line data Source code
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 "AudioStream.h"
10 : #include "MediaEventSource.h"
11 : #include "MediaQueue.h"
12 : #include "MediaInfo.h"
13 : #include "MediaSink.h"
14 :
15 : #include "mozilla/dom/AudioChannelBinding.h"
16 : #include "mozilla/Atomics.h"
17 : #include "mozilla/Maybe.h"
18 : #include "mozilla/MozPromise.h"
19 : #include "mozilla/Monitor.h"
20 : #include "mozilla/RefPtr.h"
21 : #include "nsISupportsImpl.h"
22 :
23 : namespace mozilla {
24 :
25 : class AudioConverter;
26 :
27 : namespace media {
28 :
29 : class AudioSink : private AudioStream::DataSource {
30 : using PlaybackParams = MediaSink::PlaybackParams;
31 :
32 : public:
33 : AudioSink(AbstractThread* aThread,
34 : MediaQueue<AudioData>& aAudioQueue,
35 : const TimeUnit& aStartTime,
36 : const AudioInfo& aInfo,
37 : dom::AudioChannel aChannel);
38 :
39 : ~AudioSink();
40 :
41 : // Return a promise which will be resolved when AudioSink
42 : // finishes playing, or rejected if any error.
43 : RefPtr<GenericPromise> Init(const PlaybackParams& aParams);
44 :
45 : /*
46 : * All public functions are not thread-safe.
47 : * Called on the task queue of MDSM only.
48 : */
49 : TimeUnit GetPosition();
50 : TimeUnit GetEndTime() const;
51 :
52 : // Check whether we've pushed more frames to the audio hardware than it has
53 : // played.
54 : bool HasUnplayedFrames();
55 :
56 : // Shut down the AudioSink's resources.
57 : void Shutdown();
58 :
59 : void SetVolume(double aVolume);
60 : void SetPlaybackRate(double aPlaybackRate);
61 : void SetPreservesPitch(bool aPreservesPitch);
62 : void SetPlaying(bool aPlaying);
63 :
64 0 : MediaEventSource<bool>& AudibleEvent() {
65 0 : return mAudibleEvent;
66 : }
67 :
68 : private:
69 : // Allocate and initialize mAudioStream. Returns NS_OK on success.
70 : nsresult InitializeAudioStream(const PlaybackParams& aParams);
71 :
72 : // Interface of AudioStream::DataSource.
73 : // Called on the callback thread of cubeb.
74 : UniquePtr<AudioStream::Chunk> PopFrames(uint32_t aFrames) override;
75 : bool Ended() const override;
76 : void Drained() override;
77 :
78 : void CheckIsAudible(const AudioData* aData);
79 :
80 : // The audio stream resource. Used on the task queue of MDSM only.
81 : RefPtr<AudioStream> mAudioStream;
82 :
83 : // The presentation time of the first audio frame that was played.
84 : // We can add this to the audio stream position to determine
85 : // the current audio time.
86 : const TimeUnit mStartTime;
87 :
88 : // Keep the last good position returned from the audio stream. Used to ensure
89 : // position returned by GetPosition() is mono-increasing in spite of audio
90 : // stream error. Used on the task queue of MDSM only.
91 : TimeUnit mLastGoodPosition;
92 :
93 : const AudioInfo mInfo;
94 :
95 : const dom::AudioChannel mChannel;
96 :
97 : // Used on the task queue of MDSM only.
98 : bool mPlaying;
99 :
100 : MozPromiseHolder<GenericPromise> mEndPromise;
101 :
102 : /*
103 : * Members to implement AudioStream::DataSource.
104 : * Used on the callback thread of cubeb.
105 : */
106 : // The AudioData at which AudioStream::DataSource is reading.
107 : RefPtr<AudioData> mCurrentData;
108 :
109 : // Monitor protecting access to mCursor and mWritten.
110 : // mCursor is created/destroyed on the cubeb thread, while we must also
111 : // ensure that mWritten and mCursor::Available() get modified simultaneously.
112 : // (written on cubeb thread, and read on MDSM task queue).
113 : mutable Monitor mMonitor;
114 : // Keep track of the read position of mCurrentData.
115 : UniquePtr<AudioBufferCursor> mCursor;
116 :
117 : // PCM frames written to the stream so far.
118 : int64_t mWritten;
119 :
120 : // True if there is any error in processing audio data like overflow.
121 : Atomic<bool> mErrored;
122 :
123 : // Set on the callback thread of cubeb once the stream has drained.
124 : Atomic<bool> mPlaybackComplete;
125 :
126 : const RefPtr<AbstractThread> mOwnerThread;
127 :
128 : // Audio Processing objects and methods
129 : void OnAudioPopped(const RefPtr<AudioData>& aSample);
130 : void OnAudioPushed(const RefPtr<AudioData>& aSample);
131 : void NotifyAudioNeeded();
132 : // Drain the converter and add the output to the processed audio queue.
133 : // A maximum of aMaxFrames will be added.
134 : uint32_t DrainConverter(uint32_t aMaxFrames = UINT32_MAX);
135 : already_AddRefed<AudioData> CreateAudioFromBuffer(AlignedAudioBuffer&& aBuffer,
136 : AudioData* aReference);
137 : // Add data to the processsed queue, update mProcessedQueueLength and
138 : // return the number of frames added.
139 : uint32_t PushProcessedAudio(AudioData* aData);
140 : UniquePtr<AudioConverter> mConverter;
141 : MediaQueue<AudioData> mProcessedQueue;
142 : // Length in microseconds of the ProcessedQueue
143 : Atomic<int32_t> mProcessedQueueLength;
144 : MediaEventListener mAudioQueueListener;
145 : MediaEventListener mAudioQueueFinishListener;
146 : MediaEventListener mProcessedQueueListener;
147 : // Number of frames processed from mAudioQueue. Used to determine gaps in
148 : // the input stream. It indicates the time in frames since playback started
149 : // at the current input framerate.
150 : int64_t mFramesParsed;
151 : Maybe<RefPtr<AudioData>> mLastProcessedPacket;
152 : TimeUnit mLastEndTime;
153 : // Never modifed after construction.
154 : uint32_t mOutputRate;
155 : uint32_t mOutputChannels;
156 :
157 : // True when audio is producing audible sound, false when audio is silent.
158 : bool mIsAudioDataAudible;
159 :
160 : MediaEventProducer<bool> mAudibleEvent;
161 :
162 : MediaQueue<AudioData>& mAudioQueue;
163 : };
164 :
165 : } // namespace media
166 : } // namespace mozilla
167 :
168 : #endif // AudioSink_h__
|