content/media/encoder/TrackEncoder.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial