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