1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MediaRecorder_h 8 #define MediaRecorder_h 9 10 #include "mozilla/dom/MediaRecorderBinding.h" 11 #include "mozilla/DOMEventTargetHelper.h" 12 #include "mozilla/MemoryReporting.h" 13 #include "nsIDocumentActivity.h" 14 15 // Max size for allowing queue encoded data in memory 16 #define MAX_ALLOW_MEMORY_BUFFER 1024000 17 namespace mozilla { 18 19 class AudioNodeStream; 20 class DOMMediaStream; 21 class ErrorResult; 22 class MediaInputPort; 23 struct MediaRecorderOptions; 24 class MediaStream; 25 class GlobalObject; 26 27 namespace dom { 28 29 class AudioNode; 30 31 /** 32 * Implementation of https://dvcs.w3.org/hg/dap/raw-file/default/media-stream-capture/MediaRecorder.html 33 * The MediaRecorder accepts a mediaStream as input source passed from UA. When recorder starts, 34 * a MediaEncoder will be created and accept the mediaStream as input source. 35 * Encoder will get the raw data by track data changes, encode it by selected MIME Type, then store the encoded in EncodedBufferCache object. 36 * The encoded data will be extracted on every timeslice passed from Start function call or by RequestData function. 37 * Thread model: 38 * When the recorder starts, it creates a "Media Encoder" thread to read data from MediaEncoder object and store buffer in EncodedBufferCache object. 39 * Also extract the encoded data and create blobs on every timeslice passed from start function or RequestData function called by UA. 40 */ 41 42 class MediaRecorder final : public DOMEventTargetHelper, 43 public nsIDocumentActivity 44 { 45 class Session; 46 47 public: 48 MediaRecorder(DOMMediaStream& aSourceMediaStream, 49 nsPIDOMWindowInner* aOwnerWindow); 50 MediaRecorder(AudioNode& aSrcAudioNode, uint32_t aSrcOutput, 51 nsPIDOMWindowInner* aOwnerWindow); 52 53 // nsWrapperCache 54 JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; 55 GetParentObject()56 nsPIDOMWindowInner* GetParentObject() { return GetOwner(); } 57 58 NS_DECL_ISUPPORTS_INHERITED 59 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaRecorder, 60 DOMEventTargetHelper) 61 62 // WebIDL 63 // Start recording. If timeSlice has been provided, mediaRecorder will 64 // raise a dataavailable event containing the Blob of collected data on every timeSlice milliseconds. 65 // If timeSlice isn't provided, UA should call the RequestData to obtain the Blob data, also set the mTimeSlice to zero. 66 void Start(const Optional<int32_t>& timeSlice, ErrorResult & aResult); 67 // Stop the recording activiy. Including stop the Media Encoder thread, un-hook the mediaStreamListener to encoder. 68 void Stop(ErrorResult& aResult); 69 // Pause the mTrackUnionStream 70 void Pause(ErrorResult& aResult); 71 72 void Resume(ErrorResult& aResult); 73 // Extract encoded data Blob from EncodedBufferCache. 74 void RequestData(ErrorResult& aResult); 75 // Return the The DOMMediaStream passed from UA. Stream()76 DOMMediaStream* Stream() const { return mDOMStream; } 77 // The current state of the MediaRecorder object. State()78 RecordingState State() const { return mState; } 79 // Return the current encoding MIME type selected by the MediaEncoder. 80 void GetMimeType(nsString &aMimeType); 81 82 static bool IsTypeSupported(GlobalObject& aGlobal, const nsAString& aType); 83 static bool IsTypeSupported(const nsAString& aType); 84 85 // Construct a recorder with a DOM media stream object as its source. 86 static already_AddRefed<MediaRecorder> 87 Constructor(const GlobalObject& aGlobal, 88 DOMMediaStream& aStream, 89 const MediaRecorderOptions& aInitDict, 90 ErrorResult& aRv); 91 // Construct a recorder with a Web Audio destination node as its source. 92 static already_AddRefed<MediaRecorder> 93 Constructor(const GlobalObject& aGlobal, 94 AudioNode& aSrcAudioNode, 95 uint32_t aSrcOutput, 96 const MediaRecorderOptions& aInitDict, 97 ErrorResult& aRv); 98 99 /* 100 * Measure the size of the buffer, and memory occupied by mAudioEncoder 101 * and mVideoEncoder 102 */ 103 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 104 // EventHandler 105 IMPL_EVENT_HANDLER(dataavailable) IMPL_EVENT_HANDLER(error)106 IMPL_EVENT_HANDLER(error) 107 IMPL_EVENT_HANDLER(start) 108 IMPL_EVENT_HANDLER(stop) 109 IMPL_EVENT_HANDLER(warning) 110 111 NS_DECL_NSIDOCUMENTACTIVITY 112 113 uint32_t GetAudioBitrate() { return mAudioBitsPerSecond; } GetVideoBitrate()114 uint32_t GetVideoBitrate() { return mVideoBitsPerSecond; } GetBitrate()115 uint32_t GetBitrate() { return mBitsPerSecond; } 116 protected: 117 virtual ~MediaRecorder(); 118 119 MediaRecorder& operator = (const MediaRecorder& x) = delete; 120 // Create dataavailable event with Blob data and it runs in main thread 121 nsresult CreateAndDispatchBlobEvent(already_AddRefed<nsIDOMBlob>&& aBlob); 122 // Creating a simple event to notify UA simple event. 123 void DispatchSimpleEvent(const nsAString & aStr); 124 // Creating a error event with message. 125 void NotifyError(nsresult aRv); 126 // Set encoded MIME type. 127 void SetMimeType(const nsString &aMimeType); 128 void SetOptions(const MediaRecorderOptions& aInitDict); 129 130 MediaRecorder(const MediaRecorder& x) = delete; // prevent bad usage 131 // Remove session pointer. 132 void RemoveSession(Session* aSession); 133 // Functions for Session to query input source info. 134 MediaStream* GetSourceMediaStream(); 135 // DOM wrapper for source media stream. Will be null when input is audio node. 136 RefPtr<DOMMediaStream> mDOMStream; 137 // Source audio node. Will be null when input is a media stream. 138 RefPtr<AudioNode> mAudioNode; 139 // Pipe stream connecting non-destination source node and session track union 140 // stream of recorder. Will be null when input is media stream or destination 141 // node. 142 RefPtr<AudioNodeStream> mPipeStream; 143 // Connect source node to the pipe stream. 144 RefPtr<MediaInputPort> mInputPort; 145 146 // The current state of the MediaRecorder object. 147 RecordingState mState; 148 // Hold the sessions reference and clean it when the DestroyRunnable for a 149 // session is running. 150 nsTArray<RefPtr<Session> > mSessions; 151 152 nsCOMPtr<nsIDocument> mDocument; 153 154 // It specifies the container format as well as the audio and video capture formats. 155 nsString mMimeType; 156 157 uint32_t mAudioBitsPerSecond; 158 uint32_t mVideoBitsPerSecond; 159 uint32_t mBitsPerSecond; 160 private: 161 // Register MediaRecorder into Document to listen the activity changes. 162 void RegisterActivityObserver(); 163 void UnRegisterActivityObserver(); 164 165 bool CheckPermission(const nsString &aType); 166 }; 167 168 } // namespace dom 169 } // namespace mozilla 170 171 #endif 172