content/media/encoder/MediaEncoder.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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 MediaEncoder_h_
michael@0 7 #define MediaEncoder_h_
michael@0 8
michael@0 9 #include "mozilla/DebugOnly.h"
michael@0 10 #include "TrackEncoder.h"
michael@0 11 #include "ContainerWriter.h"
michael@0 12 #include "MediaStreamGraph.h"
michael@0 13
michael@0 14 namespace mozilla {
michael@0 15
michael@0 16 /**
michael@0 17 * MediaEncoder is the framework of encoding module, it controls and manages
michael@0 18 * procedures between ContainerWriter and TrackEncoder. ContainerWriter packs
michael@0 19 * the encoded track data with a specific container (e.g. ogg, mp4).
michael@0 20 * AudioTrackEncoder and VideoTrackEncoder are subclasses of TrackEncoder, and
michael@0 21 * are responsible for encoding raw data coming from MediaStreamGraph.
michael@0 22 *
michael@0 23 * Also, MediaEncoder is a type of MediaStreamListener, it starts to receive raw
michael@0 24 * segments after itself is added to the source stream. In the mean time,
michael@0 25 * encoded track data is pulled by its owner periodically on a worker thread. A
michael@0 26 * reentrant monitor is used to protect the push and pull of resource.
michael@0 27 *
michael@0 28 * MediaEncoder is designed to be a passive component, neither it owns nor in
michael@0 29 * charge of managing threads. However, a monitor is used in function
michael@0 30 * TrackEncoder::GetEncodedTrack() for the purpose of thread safety (e.g.
michael@0 31 * between callbacks of MediaStreamListener and others), a call to this function
michael@0 32 * might block. Therefore, MediaEncoder should not run on threads that forbid
michael@0 33 * blocking, such as main thread or I/O thread.
michael@0 34 *
michael@0 35 * For example, an usage from MediaRecorder of this component would be:
michael@0 36 * 1) Create an encoder with a valid MIME type.
michael@0 37 * => encoder = MediaEncoder::CreateEncoder(aMIMEType);
michael@0 38 * It then generate a ContainerWriter according to the MIME type, and an
michael@0 39 * AudioTrackEncoder (or a VideoTrackEncoder too) associated with the media
michael@0 40 * type.
michael@0 41 *
michael@0 42 * 2) Dispatch the task GetEncodedData() to a worker thread.
michael@0 43 *
michael@0 44 * 3) To start encoding, add this component to its source stream.
michael@0 45 * => sourceStream->AddListener(encoder);
michael@0 46 *
michael@0 47 * 4) To stop encoding, remove this component from its source stream.
michael@0 48 * => sourceStream->RemoveListener(encoder);
michael@0 49 */
michael@0 50 class MediaEncoder : public MediaStreamListener
michael@0 51 {
michael@0 52 public :
michael@0 53 enum {
michael@0 54 ENCODE_METADDATA,
michael@0 55 ENCODE_TRACK,
michael@0 56 ENCODE_DONE,
michael@0 57 ENCODE_ERROR,
michael@0 58 };
michael@0 59
michael@0 60 MediaEncoder(ContainerWriter* aWriter,
michael@0 61 AudioTrackEncoder* aAudioEncoder,
michael@0 62 VideoTrackEncoder* aVideoEncoder,
michael@0 63 const nsAString& aMIMEType)
michael@0 64 : mWriter(aWriter)
michael@0 65 , mAudioEncoder(aAudioEncoder)
michael@0 66 , mVideoEncoder(aVideoEncoder)
michael@0 67 , mStartTime(TimeStamp::Now())
michael@0 68 , mMIMEType(aMIMEType)
michael@0 69 , mState(MediaEncoder::ENCODE_METADDATA)
michael@0 70 , mShutdown(false)
michael@0 71 {}
michael@0 72
michael@0 73 ~MediaEncoder() {};
michael@0 74
michael@0 75 /**
michael@0 76 * Notified by the control loop of MediaStreamGraph; aQueueMedia is the raw
michael@0 77 * track data in form of MediaSegment.
michael@0 78 */
michael@0 79 virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
michael@0 80 TrackRate aTrackRate,
michael@0 81 TrackTicks aTrackOffset,
michael@0 82 uint32_t aTrackEvents,
michael@0 83 const MediaSegment& aQueuedMedia);
michael@0 84
michael@0 85 /**
michael@0 86 * Notified the stream is being removed.
michael@0 87 */
michael@0 88 virtual void NotifyRemoved(MediaStreamGraph* aGraph);
michael@0 89
michael@0 90 /**
michael@0 91 * Creates an encoder with a given MIME type. Returns null if we are unable
michael@0 92 * to create the encoder. For now, default aMIMEType to "audio/ogg" and use
michael@0 93 * Ogg+Opus if it is empty.
michael@0 94 */
michael@0 95 static already_AddRefed<MediaEncoder> CreateEncoder(const nsAString& aMIMEType,
michael@0 96 uint8_t aTrackTypes = ContainerWriter::CREATE_AUDIO_TRACK);
michael@0 97 /**
michael@0 98 * Encodes the raw track data and returns the final container data. Assuming
michael@0 99 * it is called on a single worker thread. The buffer of container data is
michael@0 100 * allocated in ContainerWriter::GetContainerData(), and is appended to
michael@0 101 * aOutputBufs. aMIMEType is the valid mime-type of this returned container
michael@0 102 * data.
michael@0 103 */
michael@0 104 void GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs,
michael@0 105 nsAString& aMIMEType);
michael@0 106
michael@0 107 /**
michael@0 108 * Return true if MediaEncoder has been shutdown. Reasons are encoding
michael@0 109 * complete, encounter an error, or being canceled by its caller.
michael@0 110 */
michael@0 111 bool IsShutdown()
michael@0 112 {
michael@0 113 return mShutdown;
michael@0 114 }
michael@0 115
michael@0 116 /**
michael@0 117 * Cancel the encoding, and wakes up the lock of reentrant monitor in encoder.
michael@0 118 */
michael@0 119 void Cancel()
michael@0 120 {
michael@0 121 if (mAudioEncoder) {
michael@0 122 mAudioEncoder->NotifyCancel();
michael@0 123 }
michael@0 124 if (mVideoEncoder) {
michael@0 125 mVideoEncoder->NotifyCancel();
michael@0 126 }
michael@0 127 }
michael@0 128
michael@0 129 bool HasError()
michael@0 130 {
michael@0 131 return mState == ENCODE_ERROR;
michael@0 132 }
michael@0 133
michael@0 134 #ifdef MOZ_WEBM_ENCODER
michael@0 135 static bool IsWebMEncoderEnabled();
michael@0 136 #endif
michael@0 137
michael@0 138 #ifdef MOZ_OMX_ENCODER
michael@0 139 static bool IsOMXEncoderEnabled();
michael@0 140 #endif
michael@0 141
michael@0 142 private:
michael@0 143 // Get encoded data from trackEncoder and write to muxer
michael@0 144 nsresult WriteEncodedDataToMuxer(TrackEncoder *aTrackEncoder);
michael@0 145 // Get metadata from trackEncoder and copy to muxer
michael@0 146 nsresult CopyMetadataToMuxer(TrackEncoder* aTrackEncoder);
michael@0 147 nsAutoPtr<ContainerWriter> mWriter;
michael@0 148 nsAutoPtr<AudioTrackEncoder> mAudioEncoder;
michael@0 149 nsAutoPtr<VideoTrackEncoder> mVideoEncoder;
michael@0 150 TimeStamp mStartTime;
michael@0 151 nsString mMIMEType;
michael@0 152 int mState;
michael@0 153 bool mShutdown;
michael@0 154 // Get duration from create encoder, for logging purpose
michael@0 155 double GetEncodeTimeStamp()
michael@0 156 {
michael@0 157 TimeDuration decodeTime;
michael@0 158 decodeTime = TimeStamp::Now() - mStartTime;
michael@0 159 return decodeTime.ToMilliseconds();
michael@0 160 }
michael@0 161 };
michael@0 162
michael@0 163 }
michael@0 164 #endif

mercurial