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