1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/encoder/TrackEncoder.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,314 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.7 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef TrackEncoder_h_ 1.10 +#define TrackEncoder_h_ 1.11 + 1.12 +#include "mozilla/ReentrantMonitor.h" 1.13 + 1.14 +#include "AudioSegment.h" 1.15 +#include "EncodedFrameContainer.h" 1.16 +#include "StreamBuffer.h" 1.17 +#include "TrackMetadataBase.h" 1.18 +#include "VideoSegment.h" 1.19 + 1.20 +namespace mozilla { 1.21 + 1.22 +class MediaStreamGraph; 1.23 + 1.24 +/** 1.25 + * Base class of AudioTrackEncoder and VideoTrackEncoder. Lifetimes managed by 1.26 + * MediaEncoder. Most methods can only be called on the MediaEncoder's thread, 1.27 + * but some subclass methods can be called on other threads when noted. 1.28 + * 1.29 + * NotifyQueuedTrackChanges is called on subclasses of this class from the 1.30 + * MediaStreamGraph thread, and AppendAudioSegment/AppendVideoSegment is then 1.31 + * called to store media data in the TrackEncoder. Later on, GetEncodedTrack is 1.32 + * called on MediaEncoder's thread to encode and retrieve the encoded data. 1.33 + */ 1.34 +class TrackEncoder 1.35 +{ 1.36 +public: 1.37 + TrackEncoder(); 1.38 + 1.39 + virtual ~TrackEncoder() {} 1.40 + 1.41 + /** 1.42 + * Notified by the same callbcak of MediaEncoder when it has received a track 1.43 + * change from MediaStreamGraph. Called on the MediaStreamGraph thread. 1.44 + */ 1.45 + virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, 1.46 + TrackRate aTrackRate, 1.47 + TrackTicks aTrackOffset, 1.48 + uint32_t aTrackEvents, 1.49 + const MediaSegment& aQueuedMedia) = 0; 1.50 + 1.51 + /** 1.52 + * Notified by the same callback of MediaEncoder when it has been removed from 1.53 + * MediaStreamGraph. Called on the MediaStreamGraph thread. 1.54 + */ 1.55 + void NotifyRemoved(MediaStreamGraph* aGraph) { NotifyEndOfStream(); } 1.56 + 1.57 + /** 1.58 + * Creates and sets up meta data for a specific codec, called on the worker 1.59 + * thread. 1.60 + */ 1.61 + virtual already_AddRefed<TrackMetadataBase> GetMetadata() = 0; 1.62 + 1.63 + /** 1.64 + * Encodes raw segments. Result data is returned in aData, and called on the 1.65 + * worker thread. 1.66 + */ 1.67 + virtual nsresult GetEncodedTrack(EncodedFrameContainer& aData) = 0; 1.68 + 1.69 + /** 1.70 + * True if the track encoder has encoded all source segments coming from 1.71 + * MediaStreamGraph. Call on the worker thread. 1.72 + */ 1.73 + bool IsEncodingComplete() { return mEncodingComplete; } 1.74 + 1.75 + /** 1.76 + * Notifies from MediaEncoder to cancel the encoding, and wakes up 1.77 + * mReentrantMonitor if encoder is waiting on it. 1.78 + */ 1.79 + void NotifyCancel() 1.80 + { 1.81 + ReentrantMonitorAutoEnter mon(mReentrantMonitor); 1.82 + mCanceled = true; 1.83 + mReentrantMonitor.NotifyAll(); 1.84 + } 1.85 + 1.86 +protected: 1.87 + /** 1.88 + * Notifies track encoder that we have reached the end of source stream, and 1.89 + * wakes up mReentrantMonitor if encoder is waiting for any source data. 1.90 + */ 1.91 + virtual void NotifyEndOfStream() = 0; 1.92 + 1.93 + /** 1.94 + * A ReentrantMonitor to protect the pushing and pulling of mRawSegment which 1.95 + * is declared in its subclasses, and the following flags: mInitialized, 1.96 + * EndOfStream and mCanceled. The control of protection is managed by its 1.97 + * subclasses. 1.98 + */ 1.99 + ReentrantMonitor mReentrantMonitor; 1.100 + 1.101 + /** 1.102 + * True if the track encoder has encoded all source data. 1.103 + */ 1.104 + bool mEncodingComplete; 1.105 + 1.106 + /** 1.107 + * True if flag of EOS or any form of indicating EOS has set in the codec- 1.108 + * encoder. 1.109 + */ 1.110 + bool mEosSetInEncoder; 1.111 + 1.112 + /** 1.113 + * True if the track encoder has initialized successfully, protected by 1.114 + * mReentrantMonitor. 1.115 + */ 1.116 + bool mInitialized; 1.117 + 1.118 + /** 1.119 + * True if the TrackEncoder has received an event of TRACK_EVENT_ENDED from 1.120 + * MediaStreamGraph, or the MediaEncoder is removed from its source stream, 1.121 + * protected by mReentrantMonitor. 1.122 + */ 1.123 + bool mEndOfStream; 1.124 + 1.125 + /** 1.126 + * True if a cancellation of encoding is sent from MediaEncoder, protected by 1.127 + * mReentrantMonitor. 1.128 + */ 1.129 + bool mCanceled; 1.130 + 1.131 +#ifdef PR_LOGGING 1.132 + // How many times we have tried to initialize the encoder. 1.133 + uint32_t mAudioInitCounter; 1.134 + uint32_t mVideoInitCounter; 1.135 +#endif 1.136 +}; 1.137 + 1.138 +class AudioTrackEncoder : public TrackEncoder 1.139 +{ 1.140 +public: 1.141 + AudioTrackEncoder() 1.142 + : TrackEncoder() 1.143 + , mChannels(0) 1.144 + , mSamplingRate(0) 1.145 + {} 1.146 + 1.147 + void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, 1.148 + TrackRate aTrackRate, 1.149 + TrackTicks aTrackOffset, 1.150 + uint32_t aTrackEvents, 1.151 + const MediaSegment& aQueuedMedia) MOZ_OVERRIDE; 1.152 + 1.153 + /** 1.154 + * Interleaves the track data and stores the result into aOutput. Might need 1.155 + * to up-mix or down-mix the channel data if the channels number of this chunk 1.156 + * is different from aOutputChannels. The channel data from aChunk might be 1.157 + * modified by up-mixing. 1.158 + */ 1.159 + static void InterleaveTrackData(AudioChunk& aChunk, int32_t aDuration, 1.160 + uint32_t aOutputChannels, 1.161 + AudioDataValue* aOutput); 1.162 + 1.163 + /** 1.164 + * De-interleaves the aInput data and stores the result into aOutput. 1.165 + * No up-mix or down-mix operations inside. 1.166 + */ 1.167 + static void DeInterleaveTrackData(AudioDataValue* aInput, int32_t aDuration, 1.168 + int32_t aChannels, AudioDataValue* aOutput); 1.169 + 1.170 +protected: 1.171 + /** 1.172 + * Number of samples per channel in a pcm buffer. This is also the value of 1.173 + * frame size required by audio encoder, and mReentrantMonitor will be 1.174 + * notified when at least this much data has been added to mRawSegment. 1.175 + */ 1.176 + virtual int GetPacketDuration() { return 0; } 1.177 + 1.178 + /** 1.179 + * Initializes the audio encoder. The call of this method is delayed until we 1.180 + * have received the first valid track from MediaStreamGraph, and the 1.181 + * mReentrantMonitor will be notified if other methods is waiting for encoder 1.182 + * to be completely initialized. This method is called on the MediaStreamGraph 1.183 + * thread. 1.184 + */ 1.185 + virtual nsresult Init(int aChannels, int aSamplingRate) = 0; 1.186 + 1.187 + /** 1.188 + * Appends and consumes track data from aSegment, this method is called on 1.189 + * the MediaStreamGraph thread. mReentrantMonitor will be notified when at 1.190 + * least GetPacketDuration() data has been added to mRawSegment, wake up other 1.191 + * method which is waiting for more data from mRawSegment. 1.192 + */ 1.193 + nsresult AppendAudioSegment(const AudioSegment& aSegment); 1.194 + 1.195 + /** 1.196 + * Notifies the audio encoder that we have reached the end of source stream, 1.197 + * and wakes up mReentrantMonitor if encoder is waiting for more track data. 1.198 + */ 1.199 + virtual void NotifyEndOfStream() MOZ_OVERRIDE; 1.200 + 1.201 + /** 1.202 + * The number of channels are used for processing PCM data in the audio encoder. 1.203 + * This value comes from the first valid audio chunk. If encoder can't support 1.204 + * the channels in the chunk, downmix PCM stream can be performed. 1.205 + * This value also be used to initialize the audio encoder. 1.206 + */ 1.207 + int mChannels; 1.208 + 1.209 + /** 1.210 + * The sampling rate of source audio data. 1.211 + */ 1.212 + int mSamplingRate; 1.213 + 1.214 + /** 1.215 + * A segment queue of audio track data, protected by mReentrantMonitor. 1.216 + */ 1.217 + AudioSegment mRawSegment; 1.218 +}; 1.219 + 1.220 +class VideoTrackEncoder : public TrackEncoder 1.221 +{ 1.222 +public: 1.223 + VideoTrackEncoder() 1.224 + : TrackEncoder() 1.225 + , mFrameWidth(0) 1.226 + , mFrameHeight(0) 1.227 + , mDisplayWidth(0) 1.228 + , mDisplayHeight(0) 1.229 + , mTrackRate(0) 1.230 + , mTotalFrameDuration(0) 1.231 + {} 1.232 + 1.233 + /** 1.234 + * Notified by the same callbcak of MediaEncoder when it has received a track 1.235 + * change from MediaStreamGraph. Called on the MediaStreamGraph thread. 1.236 + */ 1.237 + void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, 1.238 + TrackRate aTrackRate, 1.239 + TrackTicks aTrackOffset, 1.240 + uint32_t aTrackEvents, 1.241 + const MediaSegment& aQueuedMedia) MOZ_OVERRIDE; 1.242 + 1.243 +protected: 1.244 + /** 1.245 + * Initialized the video encoder. In order to collect the value of width and 1.246 + * height of source frames, this initialization is delayed until we have 1.247 + * received the first valid video frame from MediaStreamGraph; 1.248 + * mReentrantMonitor will be notified after it has successfully initialized, 1.249 + * and this method is called on the MediaStramGraph thread. 1.250 + */ 1.251 + virtual nsresult Init(int aWidth, int aHeight, int aDisplayWidth, 1.252 + int aDisplayHeight, TrackRate aTrackRate) = 0; 1.253 + 1.254 + /** 1.255 + * Appends source video frames to mRawSegment. We only append the source chunk 1.256 + * if it is unique to mLastChunk. Called on the MediaStreamGraph thread. 1.257 + */ 1.258 + nsresult AppendVideoSegment(const VideoSegment& aSegment); 1.259 + 1.260 + /** 1.261 + * Tells the video track encoder that we've reached the end of source stream, 1.262 + * and wakes up mReentrantMonitor if encoder is waiting for more track data. 1.263 + * Called on the MediaStreamGraph thread. 1.264 + */ 1.265 + virtual void NotifyEndOfStream() MOZ_OVERRIDE; 1.266 + 1.267 + /** 1.268 + * Create a buffer of black image in format of YUV:420. Called on the worker 1.269 + * thread. 1.270 + */ 1.271 + void CreateMutedFrame(nsTArray<uint8_t>* aOutputBuffer); 1.272 + 1.273 + /** 1.274 + * The width of source video frame, ceiled if the source width is odd. 1.275 + */ 1.276 + int mFrameWidth; 1.277 + 1.278 + /** 1.279 + * The height of source video frame, ceiled if the source height is odd. 1.280 + */ 1.281 + int mFrameHeight; 1.282 + 1.283 + /** 1.284 + * The display width of source video frame. 1.285 + */ 1.286 + int mDisplayWidth; 1.287 + 1.288 + /** 1.289 + * The display height of source video frame. 1.290 + */ 1.291 + int mDisplayHeight; 1.292 + 1.293 + /** 1.294 + * The track rate of source video. 1.295 + */ 1.296 + TrackRate mTrackRate; 1.297 + 1.298 + /** 1.299 + * The total duration of frames in encoded video in TrackTicks, kept track of 1.300 + * in subclasses. 1.301 + */ 1.302 + TrackTicks mTotalFrameDuration; 1.303 + 1.304 + /** 1.305 + * The last unique frame we've sent to track encoder, kept track of in 1.306 + * subclasses. 1.307 + */ 1.308 + VideoFrame mLastFrame; 1.309 + 1.310 + /** 1.311 + * A segment queue of audio track data, protected by mReentrantMonitor. 1.312 + */ 1.313 + VideoSegment mRawSegment; 1.314 +}; 1.315 + 1.316 +} 1.317 +#endif