|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef TrackEncoder_h_ |
|
7 #define TrackEncoder_h_ |
|
8 |
|
9 #include "mozilla/ReentrantMonitor.h" |
|
10 |
|
11 #include "AudioSegment.h" |
|
12 #include "EncodedFrameContainer.h" |
|
13 #include "StreamBuffer.h" |
|
14 #include "TrackMetadataBase.h" |
|
15 #include "VideoSegment.h" |
|
16 |
|
17 namespace mozilla { |
|
18 |
|
19 class MediaStreamGraph; |
|
20 |
|
21 /** |
|
22 * Base class of AudioTrackEncoder and VideoTrackEncoder. Lifetimes managed by |
|
23 * MediaEncoder. Most methods can only be called on the MediaEncoder's thread, |
|
24 * but some subclass methods can be called on other threads when noted. |
|
25 * |
|
26 * NotifyQueuedTrackChanges is called on subclasses of this class from the |
|
27 * MediaStreamGraph thread, and AppendAudioSegment/AppendVideoSegment is then |
|
28 * called to store media data in the TrackEncoder. Later on, GetEncodedTrack is |
|
29 * called on MediaEncoder's thread to encode and retrieve the encoded data. |
|
30 */ |
|
31 class TrackEncoder |
|
32 { |
|
33 public: |
|
34 TrackEncoder(); |
|
35 |
|
36 virtual ~TrackEncoder() {} |
|
37 |
|
38 /** |
|
39 * Notified by the same callbcak of MediaEncoder when it has received a track |
|
40 * change from MediaStreamGraph. Called on the MediaStreamGraph thread. |
|
41 */ |
|
42 virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, |
|
43 TrackRate aTrackRate, |
|
44 TrackTicks aTrackOffset, |
|
45 uint32_t aTrackEvents, |
|
46 const MediaSegment& aQueuedMedia) = 0; |
|
47 |
|
48 /** |
|
49 * Notified by the same callback of MediaEncoder when it has been removed from |
|
50 * MediaStreamGraph. Called on the MediaStreamGraph thread. |
|
51 */ |
|
52 void NotifyRemoved(MediaStreamGraph* aGraph) { NotifyEndOfStream(); } |
|
53 |
|
54 /** |
|
55 * Creates and sets up meta data for a specific codec, called on the worker |
|
56 * thread. |
|
57 */ |
|
58 virtual already_AddRefed<TrackMetadataBase> GetMetadata() = 0; |
|
59 |
|
60 /** |
|
61 * Encodes raw segments. Result data is returned in aData, and called on the |
|
62 * worker thread. |
|
63 */ |
|
64 virtual nsresult GetEncodedTrack(EncodedFrameContainer& aData) = 0; |
|
65 |
|
66 /** |
|
67 * True if the track encoder has encoded all source segments coming from |
|
68 * MediaStreamGraph. Call on the worker thread. |
|
69 */ |
|
70 bool IsEncodingComplete() { return mEncodingComplete; } |
|
71 |
|
72 /** |
|
73 * Notifies from MediaEncoder to cancel the encoding, and wakes up |
|
74 * mReentrantMonitor if encoder is waiting on it. |
|
75 */ |
|
76 void NotifyCancel() |
|
77 { |
|
78 ReentrantMonitorAutoEnter mon(mReentrantMonitor); |
|
79 mCanceled = true; |
|
80 mReentrantMonitor.NotifyAll(); |
|
81 } |
|
82 |
|
83 protected: |
|
84 /** |
|
85 * Notifies track encoder that we have reached the end of source stream, and |
|
86 * wakes up mReentrantMonitor if encoder is waiting for any source data. |
|
87 */ |
|
88 virtual void NotifyEndOfStream() = 0; |
|
89 |
|
90 /** |
|
91 * A ReentrantMonitor to protect the pushing and pulling of mRawSegment which |
|
92 * is declared in its subclasses, and the following flags: mInitialized, |
|
93 * EndOfStream and mCanceled. The control of protection is managed by its |
|
94 * subclasses. |
|
95 */ |
|
96 ReentrantMonitor mReentrantMonitor; |
|
97 |
|
98 /** |
|
99 * True if the track encoder has encoded all source data. |
|
100 */ |
|
101 bool mEncodingComplete; |
|
102 |
|
103 /** |
|
104 * True if flag of EOS or any form of indicating EOS has set in the codec- |
|
105 * encoder. |
|
106 */ |
|
107 bool mEosSetInEncoder; |
|
108 |
|
109 /** |
|
110 * True if the track encoder has initialized successfully, protected by |
|
111 * mReentrantMonitor. |
|
112 */ |
|
113 bool mInitialized; |
|
114 |
|
115 /** |
|
116 * True if the TrackEncoder has received an event of TRACK_EVENT_ENDED from |
|
117 * MediaStreamGraph, or the MediaEncoder is removed from its source stream, |
|
118 * protected by mReentrantMonitor. |
|
119 */ |
|
120 bool mEndOfStream; |
|
121 |
|
122 /** |
|
123 * True if a cancellation of encoding is sent from MediaEncoder, protected by |
|
124 * mReentrantMonitor. |
|
125 */ |
|
126 bool mCanceled; |
|
127 |
|
128 #ifdef PR_LOGGING |
|
129 // How many times we have tried to initialize the encoder. |
|
130 uint32_t mAudioInitCounter; |
|
131 uint32_t mVideoInitCounter; |
|
132 #endif |
|
133 }; |
|
134 |
|
135 class AudioTrackEncoder : public TrackEncoder |
|
136 { |
|
137 public: |
|
138 AudioTrackEncoder() |
|
139 : TrackEncoder() |
|
140 , mChannels(0) |
|
141 , mSamplingRate(0) |
|
142 {} |
|
143 |
|
144 void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, |
|
145 TrackRate aTrackRate, |
|
146 TrackTicks aTrackOffset, |
|
147 uint32_t aTrackEvents, |
|
148 const MediaSegment& aQueuedMedia) MOZ_OVERRIDE; |
|
149 |
|
150 /** |
|
151 * Interleaves the track data and stores the result into aOutput. Might need |
|
152 * to up-mix or down-mix the channel data if the channels number of this chunk |
|
153 * is different from aOutputChannels. The channel data from aChunk might be |
|
154 * modified by up-mixing. |
|
155 */ |
|
156 static void InterleaveTrackData(AudioChunk& aChunk, int32_t aDuration, |
|
157 uint32_t aOutputChannels, |
|
158 AudioDataValue* aOutput); |
|
159 |
|
160 /** |
|
161 * De-interleaves the aInput data and stores the result into aOutput. |
|
162 * No up-mix or down-mix operations inside. |
|
163 */ |
|
164 static void DeInterleaveTrackData(AudioDataValue* aInput, int32_t aDuration, |
|
165 int32_t aChannels, AudioDataValue* aOutput); |
|
166 |
|
167 protected: |
|
168 /** |
|
169 * Number of samples per channel in a pcm buffer. This is also the value of |
|
170 * frame size required by audio encoder, and mReentrantMonitor will be |
|
171 * notified when at least this much data has been added to mRawSegment. |
|
172 */ |
|
173 virtual int GetPacketDuration() { return 0; } |
|
174 |
|
175 /** |
|
176 * Initializes the audio encoder. The call of this method is delayed until we |
|
177 * have received the first valid track from MediaStreamGraph, and the |
|
178 * mReentrantMonitor will be notified if other methods is waiting for encoder |
|
179 * to be completely initialized. This method is called on the MediaStreamGraph |
|
180 * thread. |
|
181 */ |
|
182 virtual nsresult Init(int aChannels, int aSamplingRate) = 0; |
|
183 |
|
184 /** |
|
185 * Appends and consumes track data from aSegment, this method is called on |
|
186 * the MediaStreamGraph thread. mReentrantMonitor will be notified when at |
|
187 * least GetPacketDuration() data has been added to mRawSegment, wake up other |
|
188 * method which is waiting for more data from mRawSegment. |
|
189 */ |
|
190 nsresult AppendAudioSegment(const AudioSegment& aSegment); |
|
191 |
|
192 /** |
|
193 * Notifies the audio encoder that we have reached the end of source stream, |
|
194 * and wakes up mReentrantMonitor if encoder is waiting for more track data. |
|
195 */ |
|
196 virtual void NotifyEndOfStream() MOZ_OVERRIDE; |
|
197 |
|
198 /** |
|
199 * The number of channels are used for processing PCM data in the audio encoder. |
|
200 * This value comes from the first valid audio chunk. If encoder can't support |
|
201 * the channels in the chunk, downmix PCM stream can be performed. |
|
202 * This value also be used to initialize the audio encoder. |
|
203 */ |
|
204 int mChannels; |
|
205 |
|
206 /** |
|
207 * The sampling rate of source audio data. |
|
208 */ |
|
209 int mSamplingRate; |
|
210 |
|
211 /** |
|
212 * A segment queue of audio track data, protected by mReentrantMonitor. |
|
213 */ |
|
214 AudioSegment mRawSegment; |
|
215 }; |
|
216 |
|
217 class VideoTrackEncoder : public TrackEncoder |
|
218 { |
|
219 public: |
|
220 VideoTrackEncoder() |
|
221 : TrackEncoder() |
|
222 , mFrameWidth(0) |
|
223 , mFrameHeight(0) |
|
224 , mDisplayWidth(0) |
|
225 , mDisplayHeight(0) |
|
226 , mTrackRate(0) |
|
227 , mTotalFrameDuration(0) |
|
228 {} |
|
229 |
|
230 /** |
|
231 * Notified by the same callbcak of MediaEncoder when it has received a track |
|
232 * change from MediaStreamGraph. Called on the MediaStreamGraph thread. |
|
233 */ |
|
234 void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, |
|
235 TrackRate aTrackRate, |
|
236 TrackTicks aTrackOffset, |
|
237 uint32_t aTrackEvents, |
|
238 const MediaSegment& aQueuedMedia) MOZ_OVERRIDE; |
|
239 |
|
240 protected: |
|
241 /** |
|
242 * Initialized the video encoder. In order to collect the value of width and |
|
243 * height of source frames, this initialization is delayed until we have |
|
244 * received the first valid video frame from MediaStreamGraph; |
|
245 * mReentrantMonitor will be notified after it has successfully initialized, |
|
246 * and this method is called on the MediaStramGraph thread. |
|
247 */ |
|
248 virtual nsresult Init(int aWidth, int aHeight, int aDisplayWidth, |
|
249 int aDisplayHeight, TrackRate aTrackRate) = 0; |
|
250 |
|
251 /** |
|
252 * Appends source video frames to mRawSegment. We only append the source chunk |
|
253 * if it is unique to mLastChunk. Called on the MediaStreamGraph thread. |
|
254 */ |
|
255 nsresult AppendVideoSegment(const VideoSegment& aSegment); |
|
256 |
|
257 /** |
|
258 * Tells the video track encoder that we've reached the end of source stream, |
|
259 * and wakes up mReentrantMonitor if encoder is waiting for more track data. |
|
260 * Called on the MediaStreamGraph thread. |
|
261 */ |
|
262 virtual void NotifyEndOfStream() MOZ_OVERRIDE; |
|
263 |
|
264 /** |
|
265 * Create a buffer of black image in format of YUV:420. Called on the worker |
|
266 * thread. |
|
267 */ |
|
268 void CreateMutedFrame(nsTArray<uint8_t>* aOutputBuffer); |
|
269 |
|
270 /** |
|
271 * The width of source video frame, ceiled if the source width is odd. |
|
272 */ |
|
273 int mFrameWidth; |
|
274 |
|
275 /** |
|
276 * The height of source video frame, ceiled if the source height is odd. |
|
277 */ |
|
278 int mFrameHeight; |
|
279 |
|
280 /** |
|
281 * The display width of source video frame. |
|
282 */ |
|
283 int mDisplayWidth; |
|
284 |
|
285 /** |
|
286 * The display height of source video frame. |
|
287 */ |
|
288 int mDisplayHeight; |
|
289 |
|
290 /** |
|
291 * The track rate of source video. |
|
292 */ |
|
293 TrackRate mTrackRate; |
|
294 |
|
295 /** |
|
296 * The total duration of frames in encoded video in TrackTicks, kept track of |
|
297 * in subclasses. |
|
298 */ |
|
299 TrackTicks mTotalFrameDuration; |
|
300 |
|
301 /** |
|
302 * The last unique frame we've sent to track encoder, kept track of in |
|
303 * subclasses. |
|
304 */ |
|
305 VideoFrame mLastFrame; |
|
306 |
|
307 /** |
|
308 * A segment queue of audio track data, protected by mReentrantMonitor. |
|
309 */ |
|
310 VideoSegment mRawSegment; |
|
311 }; |
|
312 |
|
313 } |
|
314 #endif |