LCOV - code coverage report
Current view: top level - dom/media/encoder - MediaEncoder.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 30 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 MediaEncoder_h_
       7             : #define MediaEncoder_h_
       8             : 
       9             : #include "mozilla/DebugOnly.h"
      10             : #include "TrackEncoder.h"
      11             : #include "ContainerWriter.h"
      12             : #include "CubebUtils.h"
      13             : #include "MediaStreamGraph.h"
      14             : #include "MediaStreamListener.h"
      15             : #include "nsAutoPtr.h"
      16             : #include "MediaStreamVideoSink.h"
      17             : #include "nsIMemoryReporter.h"
      18             : #include "mozilla/MemoryReporting.h"
      19             : #include "mozilla/Atomics.h"
      20             : 
      21             : namespace mozilla {
      22             : 
      23             : class MediaStreamVideoRecorderSink : public MediaStreamVideoSink
      24             : {
      25             : public:
      26           0 :   explicit MediaStreamVideoRecorderSink(VideoTrackEncoder* aEncoder)
      27           0 :     : mVideoEncoder(aEncoder)
      28           0 :     , mSuspended(false) {}
      29             : 
      30             :   // MediaStreamVideoSink methods
      31             :   virtual void SetCurrentFrames(const VideoSegment& aSegment) override;
      32           0 :   virtual void ClearFrames() override {}
      33             : 
      34           0 :   void Resume() { mSuspended = false; }
      35           0 :   void Suspend() { mSuspended = true; }
      36             : 
      37             : private:
      38           0 :   virtual ~MediaStreamVideoRecorderSink() {}
      39             :   VideoTrackEncoder* mVideoEncoder;
      40             :   Atomic<bool> mSuspended;
      41             : };
      42             : 
      43             : /**
      44             :  * MediaEncoder is the framework of encoding module, it controls and manages
      45             :  * procedures between ContainerWriter and TrackEncoder. ContainerWriter packs
      46             :  * the encoded track data with a specific container (e.g. ogg, mp4).
      47             :  * AudioTrackEncoder and VideoTrackEncoder are subclasses of TrackEncoder, and
      48             :  * are responsible for encoding raw data coming from MediaStreamGraph.
      49             :  *
      50             :  * Also, MediaEncoder is a type of MediaStreamListener, it starts to receive raw
      51             :  * segments after itself is added to the source stream. In the mean time,
      52             :  * encoded track data is pulled by its owner periodically on a worker thread. A
      53             :  * reentrant monitor is used to protect the push and pull of resource.
      54             :  *
      55             :  * MediaEncoder is designed to be a passive component, neither it owns nor in
      56             :  * charge of managing threads. However, a monitor is used in function
      57             :  * TrackEncoder::GetEncodedTrack() for the purpose of thread safety (e.g.
      58             :  * between callbacks of MediaStreamListener and others), a call to this function
      59             :  * might block. Therefore, MediaEncoder should not run on threads that forbid
      60             :  * blocking, such as main thread or I/O thread.
      61             :  *
      62             :  * For example, an usage from MediaRecorder of this component would be:
      63             :  * 1) Create an encoder with a valid MIME type.
      64             :  *    => encoder = MediaEncoder::CreateEncoder(aMIMEType);
      65             :  *    It then generate a ContainerWriter according to the MIME type, and an
      66             :  *    AudioTrackEncoder (or a VideoTrackEncoder too) associated with the media
      67             :  *    type.
      68             :  *
      69             :  * 2) Dispatch the task GetEncodedData() to a worker thread.
      70             :  *
      71             :  * 3) To start encoding, add this component to its source stream.
      72             :  *    => sourceStream->AddListener(encoder);
      73             :  *
      74             :  * 4) To stop encoding, remove this component from its source stream.
      75             :  *    => sourceStream->RemoveListener(encoder);
      76             :  */
      77             : class MediaEncoder : public DirectMediaStreamListener
      78             : {
      79             :   friend class MediaStreamVideoRecorderSink;
      80             : public :
      81             :   enum {
      82             :     ENCODE_METADDATA,
      83             :     ENCODE_TRACK,
      84             :     ENCODE_DONE,
      85             :     ENCODE_ERROR,
      86             :   };
      87             : 
      88           0 :   MediaEncoder(ContainerWriter* aWriter,
      89             :                AudioTrackEncoder* aAudioEncoder,
      90             :                VideoTrackEncoder* aVideoEncoder,
      91             :                const nsAString& aMIMEType,
      92             :                uint32_t aAudioBitrate,
      93             :                uint32_t aVideoBitrate,
      94             :                uint32_t aBitrate)
      95           0 :     : mWriter(aWriter)
      96             :     , mAudioEncoder(aAudioEncoder)
      97             :     , mVideoEncoder(aVideoEncoder)
      98           0 :     , mVideoSink(new MediaStreamVideoRecorderSink(mVideoEncoder))
      99             :     , mStartTime(TimeStamp::Now())
     100             :     , mMIMEType(aMIMEType)
     101             :     , mSizeOfBuffer(0)
     102             :     , mState(MediaEncoder::ENCODE_METADDATA)
     103             :     , mShutdown(false)
     104             :     , mDirectConnected(false)
     105             :     , mSuspended(false)
     106             :     , mMicrosecondsSpentPaused(0)
     107           0 :     , mLastMuxedTimestamp(0)
     108           0 : {}
     109             : 
     110           0 :   ~MediaEncoder() {};
     111             : 
     112             :   /* Note - called from control code, not on MSG threads. */
     113             :   void Suspend();
     114             : 
     115             :   /**
     116             :    * Note - called from control code, not on MSG threads.
     117             :    * Calculates time spent paused in order to offset frames. */
     118             :   void Resume();
     119             : 
     120             :   /**
     121             :    * Tells us which Notify to pay attention to for media
     122             :    */
     123             :   void SetDirectConnect(bool aConnected);
     124             : 
     125             :   /**
     126             :    * Notified by the AppendToTrack in MediaStreamGraph; aRealtimeMedia is the raw
     127             :    * track data in form of MediaSegment.
     128             :    */
     129             :   void NotifyRealtimeData(MediaStreamGraph* aGraph, TrackID aID,
     130             :                           StreamTime aTrackOffset,
     131             :                           uint32_t aTrackEvents,
     132             :                           const MediaSegment& aRealtimeMedia) override;
     133             : 
     134             :   /**
     135             :    * Notified by the control loop of MediaStreamGraph; aQueueMedia is the raw
     136             :    * track data in form of MediaSegment.
     137             :    */
     138             :   void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
     139             :                                 StreamTime aTrackOffset,
     140             :                                 TrackEventCommand aTrackEvents,
     141             :                                 const MediaSegment& aQueuedMedia,
     142             :                                 MediaStream* aInputStream,
     143             :                                 TrackID aInputTrackID) override;
     144             : 
     145             :   /**
     146             :    * Notifed by the control loop of MediaStreamGraph; aQueueMedia is the audio
     147             :    * data in the form of an AudioSegment.
     148             :    */
     149             :   void NotifyQueuedAudioData(MediaStreamGraph* aGraph, TrackID aID,
     150             :                              StreamTime aTrackOffset,
     151             :                              const AudioSegment& aQueuedMedia,
     152             :                              MediaStream* aInputStream,
     153             :                              TrackID aInputTrackID) override;
     154             : 
     155             :   /**
     156             :    * * Notified the stream is being removed.
     157             :    */
     158             :   void NotifyEvent(MediaStreamGraph* aGraph,
     159             :                    MediaStreamGraphEvent event) override;
     160             : 
     161             :   /**
     162             :    * Creates an encoder with a given MIME type. Returns null if we are unable
     163             :    * to create the encoder. For now, default aMIMEType to "audio/ogg" and use
     164             :    * Ogg+Opus if it is empty.
     165             :    */
     166             :   static already_AddRefed<MediaEncoder> CreateEncoder(const nsAString& aMIMEType,
     167             :                                                       uint32_t aAudioBitrate, uint32_t aVideoBitrate,
     168             :                                                       uint32_t aBitrate,
     169             :                                                       uint8_t aTrackTypes = ContainerWriter::CREATE_AUDIO_TRACK,
     170             :                                                       TrackRate aTrackRate = CubebUtils::PreferredSampleRate());
     171             :   /**
     172             :    * Encodes the raw track data and returns the final container data. Assuming
     173             :    * it is called on a single worker thread. The buffer of container data is
     174             :    * allocated in ContainerWriter::GetContainerData(), and is appended to
     175             :    * aOutputBufs. aMIMEType is the valid mime-type of this returned container
     176             :    * data.
     177             :    */
     178             :   void GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
     179             :                       nsAString& aMIMEType);
     180             : 
     181             :   /**
     182             :    * Return true if MediaEncoder has been shutdown. Reasons are encoding
     183             :    * complete, encounter an error, or being canceled by its caller.
     184             :    */
     185           0 :   bool IsShutdown()
     186             :   {
     187           0 :     return mShutdown;
     188             :   }
     189             : 
     190             :   /**
     191             :    * Cancel the encoding, and wakes up the lock of reentrant monitor in encoder.
     192             :    */
     193           0 :   void Cancel()
     194             :   {
     195           0 :     if (mAudioEncoder) {
     196           0 :       mAudioEncoder->NotifyCancel();
     197             :     }
     198           0 :     if (mVideoEncoder) {
     199           0 :       mVideoEncoder->NotifyCancel();
     200             :     }
     201           0 :   }
     202             : 
     203           0 :   bool HasError()
     204             :   {
     205           0 :     return mState == ENCODE_ERROR;
     206             :   }
     207             : 
     208             : #ifdef MOZ_WEBM_ENCODER
     209             :   static bool IsWebMEncoderEnabled();
     210             : #endif
     211             : 
     212           0 :   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
     213             :   /*
     214             :    * Measure the size of the buffer, and memory occupied by mAudioEncoder
     215             :    * and mVideoEncoder
     216             :    */
     217             :   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
     218             : 
     219           0 :   MediaStreamVideoRecorderSink* GetVideoSink() {
     220           0 :     return mVideoSink.get();
     221             :   }
     222             : 
     223             : private:
     224             :   // Get encoded data from trackEncoder and write to muxer
     225             :   nsresult WriteEncodedDataToMuxer(TrackEncoder *aTrackEncoder);
     226             :   // Get metadata from trackEncoder and copy to muxer
     227             :   nsresult CopyMetadataToMuxer(TrackEncoder* aTrackEncoder);
     228             :   nsAutoPtr<ContainerWriter> mWriter;
     229             :   nsAutoPtr<AudioTrackEncoder> mAudioEncoder;
     230             :   nsAutoPtr<VideoTrackEncoder> mVideoEncoder;
     231             :   RefPtr<MediaStreamVideoRecorderSink> mVideoSink;
     232             :   TimeStamp mStartTime;
     233             :   nsString mMIMEType;
     234             :   int64_t mSizeOfBuffer;
     235             :   int mState;
     236             :   bool mShutdown;
     237             :   bool mDirectConnected;
     238             :   // Tracks if the encoder is suspended (paused). Used on the main thread and
     239             :   // MediaRecorder's read thread.
     240             :   Atomic<bool> mSuspended;
     241             :   // Timestamp of when the last pause happened. Should only be accessed on the
     242             :   // main thread.
     243             :   TimeStamp mLastPauseStartTime;
     244             :   // Exposes the time spend paused in microseconds. Read by the main thread
     245             :   // and MediaRecorder's read thread. Should only be written by main thread.
     246             :   Atomic<uint64_t> mMicrosecondsSpentPaused;
     247             :   // The timestamp of the last muxed sample. Should only be used on
     248             :   // MediaRecorder's read thread.
     249             :   uint64_t mLastMuxedTimestamp;
     250             :   // Get duration from create encoder, for logging purpose
     251           0 :   double GetEncodeTimeStamp()
     252             :   {
     253           0 :     TimeDuration decodeTime;
     254           0 :     decodeTime = TimeStamp::Now() - mStartTime;
     255           0 :     return decodeTime.ToMilliseconds();
     256             :   }
     257             : };
     258             : 
     259             : } // namespace mozilla
     260             : 
     261             : #endif

Generated by: LCOV version 1.13