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

     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

mercurial