Fri, 16 Jan 2015 04:50:19 +0100
Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32
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/. */
6 #ifndef TrackEncoder_h_
7 #define TrackEncoder_h_
9 #include "mozilla/ReentrantMonitor.h"
11 #include "AudioSegment.h"
12 #include "EncodedFrameContainer.h"
13 #include "StreamBuffer.h"
14 #include "TrackMetadataBase.h"
15 #include "VideoSegment.h"
17 namespace mozilla {
19 class MediaStreamGraph;
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();
36 virtual ~TrackEncoder() {}
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;
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(); }
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;
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;
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; }
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 }
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;
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;
98 /**
99 * True if the track encoder has encoded all source data.
100 */
101 bool mEncodingComplete;
103 /**
104 * True if flag of EOS or any form of indicating EOS has set in the codec-
105 * encoder.
106 */
107 bool mEosSetInEncoder;
109 /**
110 * True if the track encoder has initialized successfully, protected by
111 * mReentrantMonitor.
112 */
113 bool mInitialized;
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;
122 /**
123 * True if a cancellation of encoding is sent from MediaEncoder, protected by
124 * mReentrantMonitor.
125 */
126 bool mCanceled;
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 };
135 class AudioTrackEncoder : public TrackEncoder
136 {
137 public:
138 AudioTrackEncoder()
139 : TrackEncoder()
140 , mChannels(0)
141 , mSamplingRate(0)
142 {}
144 void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
145 TrackRate aTrackRate,
146 TrackTicks aTrackOffset,
147 uint32_t aTrackEvents,
148 const MediaSegment& aQueuedMedia) MOZ_OVERRIDE;
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);
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);
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; }
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;
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);
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;
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;
206 /**
207 * The sampling rate of source audio data.
208 */
209 int mSamplingRate;
211 /**
212 * A segment queue of audio track data, protected by mReentrantMonitor.
213 */
214 AudioSegment mRawSegment;
215 };
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 {}
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;
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;
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);
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;
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);
270 /**
271 * The width of source video frame, ceiled if the source width is odd.
272 */
273 int mFrameWidth;
275 /**
276 * The height of source video frame, ceiled if the source height is odd.
277 */
278 int mFrameHeight;
280 /**
281 * The display width of source video frame.
282 */
283 int mDisplayWidth;
285 /**
286 * The display height of source video frame.
287 */
288 int mDisplayHeight;
290 /**
291 * The track rate of source video.
292 */
293 TrackRate mTrackRate;
295 /**
296 * The total duration of frames in encoded video in TrackTicks, kept track of
297 * in subclasses.
298 */
299 TrackTicks mTotalFrameDuration;
301 /**
302 * The last unique frame we've sent to track encoder, kept track of in
303 * subclasses.
304 */
305 VideoFrame mLastFrame;
307 /**
308 * A segment queue of audio track data, protected by mReentrantMonitor.
309 */
310 VideoSegment mRawSegment;
311 };
313 }
314 #endif