|
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 NSDOMMEDIASTREAM_H_ |
|
7 #define NSDOMMEDIASTREAM_H_ |
|
8 |
|
9 #include "nsIDOMMediaStream.h" |
|
10 #include "nsCycleCollectionParticipant.h" |
|
11 #include "nsWrapperCache.h" |
|
12 #include "StreamBuffer.h" |
|
13 #include "nsIDOMWindow.h" |
|
14 |
|
15 class nsXPCClassInfo; |
|
16 class nsIPrincipal; |
|
17 |
|
18 // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to |
|
19 // GetTickCount() and conflicts with NS_DECL_NSIDOMMEDIASTREAM, containing |
|
20 // currentTime getter. |
|
21 #ifdef GetCurrentTime |
|
22 #undef GetCurrentTime |
|
23 #endif |
|
24 // X11 has a #define for CurrentTime. Unbelievable :-(. |
|
25 // See content/media/webaudio/AudioContext.h for more fun! |
|
26 #ifdef CurrentTime |
|
27 #undef CurrentTime |
|
28 #endif |
|
29 |
|
30 namespace mozilla { |
|
31 |
|
32 class MediaStream; |
|
33 |
|
34 namespace dom { |
|
35 class AudioNode; |
|
36 class MediaStreamTrack; |
|
37 class AudioStreamTrack; |
|
38 class VideoStreamTrack; |
|
39 } |
|
40 |
|
41 class MediaStreamDirectListener; |
|
42 |
|
43 /** |
|
44 * DOM wrapper for MediaStreams. |
|
45 */ |
|
46 class DOMMediaStream : public nsIDOMMediaStream, |
|
47 public nsWrapperCache |
|
48 { |
|
49 friend class DOMLocalMediaStream; |
|
50 typedef dom::MediaStreamTrack MediaStreamTrack; |
|
51 typedef dom::AudioStreamTrack AudioStreamTrack; |
|
52 typedef dom::VideoStreamTrack VideoStreamTrack; |
|
53 |
|
54 public: |
|
55 typedef uint8_t TrackTypeHints; |
|
56 |
|
57 DOMMediaStream(); |
|
58 virtual ~DOMMediaStream(); |
|
59 |
|
60 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMMediaStream) |
|
61 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
62 |
|
63 nsIDOMWindow* GetParentObject() const |
|
64 { |
|
65 return mWindow; |
|
66 } |
|
67 virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; |
|
68 |
|
69 // WebIDL |
|
70 double CurrentTime(); |
|
71 |
|
72 void GetAudioTracks(nsTArray<nsRefPtr<AudioStreamTrack> >& aTracks); |
|
73 void GetVideoTracks(nsTArray<nsRefPtr<VideoStreamTrack> >& aTracks); |
|
74 |
|
75 MediaStream* GetStream() const { return mStream; } |
|
76 |
|
77 /** |
|
78 * Overridden in DOMLocalMediaStreams to allow getUserMedia to pass |
|
79 * data directly to RTCPeerConnection without going through graph queuing. |
|
80 * Returns a bool to let us know if direct data will be delivered. |
|
81 */ |
|
82 virtual bool AddDirectListener(MediaStreamDirectListener *aListener) { return false; } |
|
83 virtual void RemoveDirectListener(MediaStreamDirectListener *aListener) {} |
|
84 |
|
85 /** |
|
86 * Overridden in DOMLocalMediaStreams to allow getUserMedia to disable |
|
87 * media at the SourceMediaStream. |
|
88 */ |
|
89 virtual void SetTrackEnabled(TrackID aTrackID, bool aEnabled); |
|
90 |
|
91 bool IsFinished(); |
|
92 /** |
|
93 * Returns a principal indicating who may access this stream. The stream contents |
|
94 * can only be accessed by principals subsuming this principal. |
|
95 */ |
|
96 nsIPrincipal* GetPrincipal() { return mPrincipal; } |
|
97 |
|
98 /** |
|
99 * Indicate that data will be contributed to this stream from origin aPrincipal. |
|
100 * If aPrincipal is null, this is ignored. Otherwise, from now on the contents |
|
101 * of this stream can only be accessed by principals that subsume aPrincipal. |
|
102 * Returns true if the stream's principal changed. |
|
103 */ |
|
104 bool CombineWithPrincipal(nsIPrincipal* aPrincipal); |
|
105 |
|
106 /** |
|
107 * Called when this stream's MediaStreamGraph has been shut down. Normally |
|
108 * MSGs are only shut down when all streams have been removed, so this |
|
109 * will only be called during a forced shutdown due to application exit. |
|
110 */ |
|
111 void NotifyMediaStreamGraphShutdown(); |
|
112 /** |
|
113 * Called when the main-thread state of the MediaStream changed. |
|
114 */ |
|
115 void NotifyStreamStateChanged(); |
|
116 |
|
117 // Indicate what track types we eventually expect to add to this stream |
|
118 enum { |
|
119 HINT_CONTENTS_AUDIO = 1 << 0, |
|
120 HINT_CONTENTS_VIDEO = 1 << 1 |
|
121 }; |
|
122 TrackTypeHints GetHintContents() const { return mHintContents; } |
|
123 void SetHintContents(TrackTypeHints aHintContents) { mHintContents = aHintContents; } |
|
124 |
|
125 /** |
|
126 * Create an nsDOMMediaStream whose underlying stream is a SourceMediaStream. |
|
127 */ |
|
128 static already_AddRefed<DOMMediaStream> |
|
129 CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); |
|
130 |
|
131 /** |
|
132 * Create an nsDOMMediaStream whose underlying stream is a TrackUnionStream. |
|
133 */ |
|
134 static already_AddRefed<DOMMediaStream> |
|
135 CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0); |
|
136 |
|
137 void SetLogicalStreamStartTime(StreamTime aTime) |
|
138 { |
|
139 mLogicalStreamStartTime = aTime; |
|
140 } |
|
141 |
|
142 // Notifications from StreamListener. |
|
143 // CreateDOMTrack should only be called when it's safe to run script. |
|
144 MediaStreamTrack* CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType); |
|
145 MediaStreamTrack* GetDOMTrackFor(TrackID aTrackID); |
|
146 |
|
147 class OnTracksAvailableCallback { |
|
148 public: |
|
149 OnTracksAvailableCallback(uint8_t aExpectedTracks = 0) |
|
150 : mExpectedTracks(aExpectedTracks) {} |
|
151 virtual ~OnTracksAvailableCallback() {} |
|
152 virtual void NotifyTracksAvailable(DOMMediaStream* aStream) = 0; |
|
153 TrackTypeHints GetExpectedTracks() { return mExpectedTracks; } |
|
154 void SetExpectedTracks(TrackTypeHints aExpectedTracks) { mExpectedTracks = aExpectedTracks; } |
|
155 private: |
|
156 TrackTypeHints mExpectedTracks; |
|
157 }; |
|
158 // When one track of the appropriate type has been added for each bit set |
|
159 // in aCallback->GetExpectedTracks(), run aCallback->NotifyTracksAvailable. |
|
160 // It is allowed to do anything, including run script. |
|
161 // aCallback may run immediately during this call if tracks are already |
|
162 // available! |
|
163 // We only care about track additions, we'll fire the notification even if |
|
164 // some of the tracks have been removed. |
|
165 // Takes ownership of aCallback. |
|
166 // If GetExpectedTracks() returns 0, the callback will be fired as soon as there are any tracks. |
|
167 void OnTracksAvailable(OnTracksAvailableCallback* aCallback); |
|
168 |
|
169 /** |
|
170 * Add an nsISupports object that this stream will keep alive as long as |
|
171 * the stream is not finished. |
|
172 */ |
|
173 void AddConsumerToKeepAlive(nsISupports* aConsumer) |
|
174 { |
|
175 if (!IsFinished() && !mNotifiedOfMediaStreamGraphShutdown) { |
|
176 mConsumersToKeepAlive.AppendElement(aConsumer); |
|
177 } |
|
178 } |
|
179 |
|
180 protected: |
|
181 void Destroy(); |
|
182 void InitSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); |
|
183 void InitTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); |
|
184 void InitStreamCommon(MediaStream* aStream); |
|
185 |
|
186 void CheckTracksAvailable(); |
|
187 |
|
188 class StreamListener; |
|
189 friend class StreamListener; |
|
190 |
|
191 // StreamTime at which the currentTime attribute would return 0. |
|
192 StreamTime mLogicalStreamStartTime; |
|
193 |
|
194 // We need this to track our parent object. |
|
195 nsCOMPtr<nsIDOMWindow> mWindow; |
|
196 |
|
197 // MediaStream is owned by the graph, but we tell it when to die, and it won't |
|
198 // die until we let it. |
|
199 MediaStream* mStream; |
|
200 // Principal identifying who may access the contents of this stream. |
|
201 // If null, this stream can be used by anyone because it has no content yet. |
|
202 nsCOMPtr<nsIPrincipal> mPrincipal; |
|
203 |
|
204 nsAutoTArray<nsRefPtr<MediaStreamTrack>,2> mTracks; |
|
205 nsRefPtr<StreamListener> mListener; |
|
206 |
|
207 nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable; |
|
208 |
|
209 // Keep these alive until the stream finishes |
|
210 nsTArray<nsCOMPtr<nsISupports> > mConsumersToKeepAlive; |
|
211 |
|
212 // Indicate what track types we eventually expect to add to this stream |
|
213 uint8_t mHintContents; |
|
214 // Indicate what track types have been added to this stream |
|
215 uint8_t mTrackTypesAvailable; |
|
216 bool mNotifiedOfMediaStreamGraphShutdown; |
|
217 }; |
|
218 |
|
219 class DOMLocalMediaStream : public DOMMediaStream, |
|
220 public nsIDOMLocalMediaStream |
|
221 { |
|
222 public: |
|
223 DOMLocalMediaStream() {} |
|
224 virtual ~DOMLocalMediaStream(); |
|
225 |
|
226 NS_DECL_ISUPPORTS_INHERITED |
|
227 |
|
228 virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE; |
|
229 |
|
230 virtual void Stop(); |
|
231 |
|
232 /** |
|
233 * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream. |
|
234 */ |
|
235 static already_AddRefed<DOMLocalMediaStream> |
|
236 CreateSourceStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents); |
|
237 |
|
238 /** |
|
239 * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream. |
|
240 */ |
|
241 static already_AddRefed<DOMLocalMediaStream> |
|
242 CreateTrackUnionStream(nsIDOMWindow* aWindow, TrackTypeHints aHintContents = 0); |
|
243 }; |
|
244 |
|
245 class DOMAudioNodeMediaStream : public DOMMediaStream |
|
246 { |
|
247 typedef dom::AudioNode AudioNode; |
|
248 public: |
|
249 DOMAudioNodeMediaStream(AudioNode* aNode); |
|
250 |
|
251 NS_DECL_ISUPPORTS_INHERITED |
|
252 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream) |
|
253 |
|
254 /** |
|
255 * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream. |
|
256 */ |
|
257 static already_AddRefed<DOMAudioNodeMediaStream> |
|
258 CreateTrackUnionStream(nsIDOMWindow* aWindow, |
|
259 AudioNode* aNode, |
|
260 TrackTypeHints aHintContents = 0); |
|
261 |
|
262 private: |
|
263 // If this object wraps a stream owned by an AudioNode, we need to ensure that |
|
264 // the node isn't cycle-collected too early. |
|
265 nsRefPtr<AudioNode> mStreamNode; |
|
266 }; |
|
267 |
|
268 } |
|
269 |
|
270 #endif /* NSDOMMEDIASTREAM_H_ */ |