1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/media/encoder/MediaEncoder.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,164 @@ 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 MediaEncoder_h_ 1.10 +#define MediaEncoder_h_ 1.11 + 1.12 +#include "mozilla/DebugOnly.h" 1.13 +#include "TrackEncoder.h" 1.14 +#include "ContainerWriter.h" 1.15 +#include "MediaStreamGraph.h" 1.16 + 1.17 +namespace mozilla { 1.18 + 1.19 +/** 1.20 + * MediaEncoder is the framework of encoding module, it controls and manages 1.21 + * procedures between ContainerWriter and TrackEncoder. ContainerWriter packs 1.22 + * the encoded track data with a specific container (e.g. ogg, mp4). 1.23 + * AudioTrackEncoder and VideoTrackEncoder are subclasses of TrackEncoder, and 1.24 + * are responsible for encoding raw data coming from MediaStreamGraph. 1.25 + * 1.26 + * Also, MediaEncoder is a type of MediaStreamListener, it starts to receive raw 1.27 + * segments after itself is added to the source stream. In the mean time, 1.28 + * encoded track data is pulled by its owner periodically on a worker thread. A 1.29 + * reentrant monitor is used to protect the push and pull of resource. 1.30 + * 1.31 + * MediaEncoder is designed to be a passive component, neither it owns nor in 1.32 + * charge of managing threads. However, a monitor is used in function 1.33 + * TrackEncoder::GetEncodedTrack() for the purpose of thread safety (e.g. 1.34 + * between callbacks of MediaStreamListener and others), a call to this function 1.35 + * might block. Therefore, MediaEncoder should not run on threads that forbid 1.36 + * blocking, such as main thread or I/O thread. 1.37 + * 1.38 + * For example, an usage from MediaRecorder of this component would be: 1.39 + * 1) Create an encoder with a valid MIME type. 1.40 + * => encoder = MediaEncoder::CreateEncoder(aMIMEType); 1.41 + * It then generate a ContainerWriter according to the MIME type, and an 1.42 + * AudioTrackEncoder (or a VideoTrackEncoder too) associated with the media 1.43 + * type. 1.44 + * 1.45 + * 2) Dispatch the task GetEncodedData() to a worker thread. 1.46 + * 1.47 + * 3) To start encoding, add this component to its source stream. 1.48 + * => sourceStream->AddListener(encoder); 1.49 + * 1.50 + * 4) To stop encoding, remove this component from its source stream. 1.51 + * => sourceStream->RemoveListener(encoder); 1.52 + */ 1.53 +class MediaEncoder : public MediaStreamListener 1.54 +{ 1.55 +public : 1.56 + enum { 1.57 + ENCODE_METADDATA, 1.58 + ENCODE_TRACK, 1.59 + ENCODE_DONE, 1.60 + ENCODE_ERROR, 1.61 + }; 1.62 + 1.63 + MediaEncoder(ContainerWriter* aWriter, 1.64 + AudioTrackEncoder* aAudioEncoder, 1.65 + VideoTrackEncoder* aVideoEncoder, 1.66 + const nsAString& aMIMEType) 1.67 + : mWriter(aWriter) 1.68 + , mAudioEncoder(aAudioEncoder) 1.69 + , mVideoEncoder(aVideoEncoder) 1.70 + , mStartTime(TimeStamp::Now()) 1.71 + , mMIMEType(aMIMEType) 1.72 + , mState(MediaEncoder::ENCODE_METADDATA) 1.73 + , mShutdown(false) 1.74 + {} 1.75 + 1.76 + ~MediaEncoder() {}; 1.77 + 1.78 + /** 1.79 + * Notified by the control loop of MediaStreamGraph; aQueueMedia is the raw 1.80 + * track data in form of MediaSegment. 1.81 + */ 1.82 + virtual void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID, 1.83 + TrackRate aTrackRate, 1.84 + TrackTicks aTrackOffset, 1.85 + uint32_t aTrackEvents, 1.86 + const MediaSegment& aQueuedMedia); 1.87 + 1.88 + /** 1.89 + * Notified the stream is being removed. 1.90 + */ 1.91 + virtual void NotifyRemoved(MediaStreamGraph* aGraph); 1.92 + 1.93 + /** 1.94 + * Creates an encoder with a given MIME type. Returns null if we are unable 1.95 + * to create the encoder. For now, default aMIMEType to "audio/ogg" and use 1.96 + * Ogg+Opus if it is empty. 1.97 + */ 1.98 + static already_AddRefed<MediaEncoder> CreateEncoder(const nsAString& aMIMEType, 1.99 + uint8_t aTrackTypes = ContainerWriter::CREATE_AUDIO_TRACK); 1.100 + /** 1.101 + * Encodes the raw track data and returns the final container data. Assuming 1.102 + * it is called on a single worker thread. The buffer of container data is 1.103 + * allocated in ContainerWriter::GetContainerData(), and is appended to 1.104 + * aOutputBufs. aMIMEType is the valid mime-type of this returned container 1.105 + * data. 1.106 + */ 1.107 + void GetEncodedData(nsTArray<nsTArray<uint8_t> >* aOutputBufs, 1.108 + nsAString& aMIMEType); 1.109 + 1.110 + /** 1.111 + * Return true if MediaEncoder has been shutdown. Reasons are encoding 1.112 + * complete, encounter an error, or being canceled by its caller. 1.113 + */ 1.114 + bool IsShutdown() 1.115 + { 1.116 + return mShutdown; 1.117 + } 1.118 + 1.119 + /** 1.120 + * Cancel the encoding, and wakes up the lock of reentrant monitor in encoder. 1.121 + */ 1.122 + void Cancel() 1.123 + { 1.124 + if (mAudioEncoder) { 1.125 + mAudioEncoder->NotifyCancel(); 1.126 + } 1.127 + if (mVideoEncoder) { 1.128 + mVideoEncoder->NotifyCancel(); 1.129 + } 1.130 + } 1.131 + 1.132 + bool HasError() 1.133 + { 1.134 + return mState == ENCODE_ERROR; 1.135 + } 1.136 + 1.137 +#ifdef MOZ_WEBM_ENCODER 1.138 + static bool IsWebMEncoderEnabled(); 1.139 +#endif 1.140 + 1.141 +#ifdef MOZ_OMX_ENCODER 1.142 + static bool IsOMXEncoderEnabled(); 1.143 +#endif 1.144 + 1.145 +private: 1.146 + // Get encoded data from trackEncoder and write to muxer 1.147 + nsresult WriteEncodedDataToMuxer(TrackEncoder *aTrackEncoder); 1.148 + // Get metadata from trackEncoder and copy to muxer 1.149 + nsresult CopyMetadataToMuxer(TrackEncoder* aTrackEncoder); 1.150 + nsAutoPtr<ContainerWriter> mWriter; 1.151 + nsAutoPtr<AudioTrackEncoder> mAudioEncoder; 1.152 + nsAutoPtr<VideoTrackEncoder> mVideoEncoder; 1.153 + TimeStamp mStartTime; 1.154 + nsString mMIMEType; 1.155 + int mState; 1.156 + bool mShutdown; 1.157 + // Get duration from create encoder, for logging purpose 1.158 + double GetEncodeTimeStamp() 1.159 + { 1.160 + TimeDuration decodeTime; 1.161 + decodeTime = TimeStamp::Now() - mStartTime; 1.162 + return decodeTime.ToMilliseconds(); 1.163 + } 1.164 +}; 1.165 + 1.166 +} 1.167 +#endif