/work/obj-fuzz/dist/include/DOMMediaStream.h
Line | Count | Source (jump to first uncovered line) |
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 "ImageContainer.h" |
10 | | |
11 | | #include "nsAutoPtr.h" |
12 | | #include "nsCycleCollectionParticipant.h" |
13 | | #include "nsWrapperCache.h" |
14 | | #include "StreamTracks.h" |
15 | | #include "nsIDOMWindow.h" |
16 | | #include "nsIPrincipal.h" |
17 | | #include "MediaTrackConstraints.h" |
18 | | #include "mozilla/DOMEventTargetHelper.h" |
19 | | #include "mozilla/RelativeTimeline.h" |
20 | | #include "PrincipalChangeObserver.h" |
21 | | |
22 | | // X11 has a #define for CurrentTime. Unbelievable :-(. |
23 | | // See dom/media/webaudio/AudioContext.h for more fun! |
24 | | #ifdef CurrentTime |
25 | | #undef CurrentTime |
26 | | #endif |
27 | | |
28 | | namespace mozilla { |
29 | | |
30 | | class AbstractThread; |
31 | | class DOMLocalMediaStream; |
32 | | class DOMMediaStream; |
33 | | class MediaStream; |
34 | | class MediaInputPort; |
35 | | class MediaStreamGraph; |
36 | | class ProcessedMediaStream; |
37 | | |
38 | | enum class BlockingMode; |
39 | | |
40 | | namespace dom { |
41 | | class AudioNode; |
42 | | class HTMLCanvasElement; |
43 | | class MediaStreamTrack; |
44 | | class MediaStreamTrackSource; |
45 | | class AudioStreamTrack; |
46 | | class VideoStreamTrack; |
47 | | class AudioTrack; |
48 | | class VideoTrack; |
49 | | class AudioTrackList; |
50 | | class VideoTrackList; |
51 | | class MediaTrackListListener; |
52 | | } // namespace dom |
53 | | |
54 | | namespace layers { |
55 | | class ImageContainer; |
56 | | class OverlayImage; |
57 | | } // namespace layers |
58 | | |
59 | | namespace media { |
60 | | template<typename V, typename E> class Pledge; |
61 | | } // namespace media |
62 | | |
63 | | #define NS_DOMMEDIASTREAM_IID \ |
64 | | { 0x8cb65468, 0x66c0, 0x444e, \ |
65 | | { 0x89, 0x9f, 0x89, 0x1d, 0x9e, 0xd2, 0xbe, 0x7c } } |
66 | | |
67 | | class OnTracksAvailableCallback { |
68 | | public: |
69 | | virtual ~OnTracksAvailableCallback() {} |
70 | | virtual void NotifyTracksAvailable(DOMMediaStream* aStream) = 0; |
71 | | }; |
72 | | |
73 | | /** |
74 | | * Interface through which a DOMMediaStream can query its producer for a |
75 | | * MediaStreamTrackSource. This will be used whenever a track occurs in the |
76 | | * DOMMediaStream's owned stream that has not yet been created on the main |
77 | | * thread (see DOMMediaStream::CreateOwnDOMTrack). |
78 | | */ |
79 | | class MediaStreamTrackSourceGetter : public nsISupports |
80 | | { |
81 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
82 | | NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackSourceGetter) |
83 | | |
84 | | public: |
85 | | MediaStreamTrackSourceGetter() |
86 | | { |
87 | | } |
88 | | |
89 | | virtual already_AddRefed<dom::MediaStreamTrackSource> |
90 | | GetMediaStreamTrackSource(TrackID aInputTrackID) = 0; |
91 | | |
92 | | protected: |
93 | | virtual ~MediaStreamTrackSourceGetter() |
94 | | { |
95 | | } |
96 | | }; |
97 | | |
98 | | /** |
99 | | * DOM wrapper for MediaStreams. |
100 | | * |
101 | | * To account for track operations such as clone(), addTrack() and |
102 | | * removeTrack(), a DOMMediaStream wraps three internal (and chained) |
103 | | * MediaStreams: |
104 | | * 1. mInputStream |
105 | | * - Controlled by the owner/source of the DOMMediaStream. |
106 | | * It's a stream of the type indicated by |
107 | | * - DOMMediaStream::CreateSourceStream/CreateTrackUnionStream. A source |
108 | | * typically creates its DOMMediaStream, creates the MediaStreamTracks |
109 | | * owned by said stream, then gets the internal input stream to which it |
110 | | * feeds data for the previously created tracks. |
111 | | * - When necessary it can create tracks on the internal stream only and |
112 | | * their corresponding MediaStreamTracks will be asynchronously created. |
113 | | * 2. mOwnedStream |
114 | | * - A TrackUnionStream containing tracks owned by this stream. |
115 | | * - The internal model of a MediaStreamTrack consists of its owning |
116 | | * DOMMediaStream and the TrackID of the corresponding internal track in |
117 | | * the owning DOMMediaStream's mOwnedStream. |
118 | | * - The owned stream is different from the input stream since a cloned |
119 | | * DOMMediaStream is also the owner of its (cloned) MediaStreamTracks. |
120 | | * - Stopping an original track shall not stop its clone. This is |
121 | | * solved by stopping it at the owned stream, while the clone's owned |
122 | | * stream gets data directly from the original input stream. |
123 | | * - A DOMMediaStream (original or clone) gets all tracks dynamically |
124 | | * added by the source automatically forwarded by having a TRACK_ANY |
125 | | * MediaInputPort set up from the owning DOMMediaStream's input stream |
126 | | * to this DOMMediaStream's owned stream. |
127 | | * 3. mPlaybackStream |
128 | | * - A TrackUnionStream containing the tracks corresponding to the |
129 | | * MediaStreamTracks currently in this DOMMediaStream (per getTracks()). |
130 | | * - Similarly as for mOwnedStream, there's a TRACK_ANY MediaInputPort set |
131 | | * up from the owned stream to the playback stream to allow tracks |
132 | | * dynamically added by the source to be automatically forwarded to any |
133 | | * audio or video sinks. |
134 | | * - MediaStreamTracks added by addTrack() are set up with a MediaInputPort |
135 | | * locked to their internal TrackID, from their owning DOMMediaStream's |
136 | | * owned stream to this playback stream. |
137 | | * |
138 | | * |
139 | | * A graphical representation of how tracks are connected in various cases as |
140 | | * follows: |
141 | | * |
142 | | * addTrack()ed case: |
143 | | * DOMStream A |
144 | | * Input Owned Playback |
145 | | * t1 ---------> t1 ------------> t1 <- MediaStreamTrack X |
146 | | * (pointing to t1 in A) |
147 | | * --------> t2 <- MediaStreamTrack Y |
148 | | * / (pointing to t1 in B) |
149 | | * DOMStream B / |
150 | | * Input Owned / Playback |
151 | | * t1 ---------> t1 ------------> t1 <- MediaStreamTrack Y |
152 | | * (pointing to t1 in B) |
153 | | * |
154 | | * removeTrack()ed case: |
155 | | * DOMStream A |
156 | | * Input Owned Playback |
157 | | * t1 ---------> t1 <- No tracks |
158 | | * |
159 | | * |
160 | | * clone()d case: |
161 | | * DOMStream A |
162 | | * Input Owned Playback |
163 | | * t1 ---------> t1 ------------> t1 <- MediaStreamTrack X |
164 | | * \ (pointing to t1 in A) |
165 | | * ----- |
166 | | * DOMStream B \ |
167 | | * Input \ Owned Playback |
168 | | * -> t1 ------------> t1 <- MediaStreamTrack Y |
169 | | * (pointing to t1 in B) |
170 | | * |
171 | | * |
172 | | * addTrack()ed, removeTrack()ed and clone()d case: |
173 | | * |
174 | | * Here we have done the following: |
175 | | * var A = someStreamWithTwoTracks; |
176 | | * var B = someStreamWithOneTrack; |
177 | | * var X = A.getTracks()[0]; |
178 | | * var Y = A.getTracks()[1]; |
179 | | * var Z = B.getTracks()[0]; |
180 | | * A.addTrack(Z); |
181 | | * A.removeTrack(X); |
182 | | * B.removeTrack(Z); |
183 | | * var A' = A.clone(); |
184 | | * |
185 | | * DOMStream A |
186 | | * Input Owned Playback |
187 | | * t1 ---------> t1 <- MediaStreamTrack X (removed) |
188 | | * (pointing to t1 in A) |
189 | | * t2 ---------> t2 ------------> t2 <- MediaStreamTrack Y |
190 | | * \ (pointing to t2 in A) |
191 | | * \ ------> t3 <- MediaStreamTrack Z |
192 | | * \ / (pointing to t1 in B) |
193 | | * DOMStream B \ / |
194 | | * Input \ Owned / Playback |
195 | | * t1 ---^-----> t1 --- <- MediaStreamTrack Z (removed) |
196 | | * \ \ (pointing to t1 in B) |
197 | | * \ \ |
198 | | * DOMStream A' \ \ |
199 | | * Input \ \ Owned Playback |
200 | | * \ -> t1 ------------> t1 <- MediaStreamTrack Y' |
201 | | * \ (pointing to t1 in A') |
202 | | * ----> t2 ------------> t2 <- MediaStreamTrack Z' |
203 | | * (pointing to t2 in A') |
204 | | */ |
205 | | class DOMMediaStream : public DOMEventTargetHelper, |
206 | | public dom::PrincipalChangeObserver<dom::MediaStreamTrack>, |
207 | | public RelativeTimeline |
208 | | { |
209 | | friend class DOMLocalMediaStream; |
210 | | friend class dom::MediaStreamTrack; |
211 | | typedef dom::MediaStreamTrack MediaStreamTrack; |
212 | | typedef dom::AudioStreamTrack AudioStreamTrack; |
213 | | typedef dom::VideoStreamTrack VideoStreamTrack; |
214 | | typedef dom::MediaStreamTrackSource MediaStreamTrackSource; |
215 | | typedef dom::AudioTrack AudioTrack; |
216 | | typedef dom::VideoTrack VideoTrack; |
217 | | typedef dom::AudioTrackList AudioTrackList; |
218 | | typedef dom::VideoTrackList VideoTrackList; |
219 | | |
220 | | public: |
221 | | typedef dom::MediaTrackConstraints MediaTrackConstraints; |
222 | | |
223 | | class TrackListener { |
224 | | public: |
225 | | virtual ~TrackListener() {} |
226 | | |
227 | | /** |
228 | | * Called when the DOMMediaStream has a live track added, either by |
229 | | * script (addTrack()) or the source creating one. |
230 | | */ |
231 | | virtual void |
232 | | NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack) {}; |
233 | | |
234 | | /** |
235 | | * Called when the DOMMediaStream removes a live track from playback, either |
236 | | * by script (removeTrack(), track.stop()) or the source ending it. |
237 | | */ |
238 | | virtual void |
239 | | NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack) {}; |
240 | | |
241 | | /** |
242 | | * Called when the DOMMediaStream has become active. |
243 | | */ |
244 | | virtual void |
245 | | NotifyActive() {}; |
246 | | |
247 | | /** |
248 | | * Called when the DOMMediaStream has become inactive. |
249 | | */ |
250 | | virtual void |
251 | | NotifyInactive() {}; |
252 | | }; |
253 | | |
254 | | /** |
255 | | * TrackPort is a representation of a MediaStreamTrack-MediaInputPort pair |
256 | | * that make up a link between the Owned stream and the Playback stream. |
257 | | * |
258 | | * Semantically, the track is the identifier/key and the port the value of this |
259 | | * connection. |
260 | | * |
261 | | * The input port can be shared between several TrackPorts. This is the case |
262 | | * for DOMMediaStream's mPlaybackPort which forwards all tracks in its |
263 | | * mOwnedStream automatically. |
264 | | * |
265 | | * If the MediaStreamTrack is owned by another DOMMediaStream (called A) than |
266 | | * the one owning the TrackPort (called B), the input port (locked to the |
267 | | * MediaStreamTrack's TrackID) connects A's mOwnedStream to B's mPlaybackStream. |
268 | | * |
269 | | * A TrackPort may never leave the DOMMediaStream it was created in. Internal |
270 | | * use only. |
271 | | */ |
272 | | class TrackPort |
273 | | { |
274 | | public: |
275 | | NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(TrackPort) |
276 | | NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(TrackPort) |
277 | | |
278 | | /** |
279 | | * Indicates MediaInputPort ownership to the TrackPort. |
280 | | * |
281 | | * OWNED - Owned by the TrackPort itself. TrackPort must destroy the |
282 | | * input port when it's destructed. |
283 | | * EXTERNAL - Owned by another entity. It's the caller's responsibility to |
284 | | * ensure the the MediaInputPort outlives the TrackPort. |
285 | | */ |
286 | | enum class InputPortOwnership { |
287 | | OWNED = 1, |
288 | | EXTERNAL |
289 | | }; |
290 | | |
291 | | TrackPort(MediaInputPort* aInputPort, |
292 | | MediaStreamTrack* aTrack, |
293 | | const InputPortOwnership aOwnership); |
294 | | |
295 | | protected: |
296 | | virtual ~TrackPort(); |
297 | | |
298 | | public: |
299 | | void DestroyInputPort(); |
300 | | |
301 | | /** |
302 | | * Returns the source stream of the input port. |
303 | | */ |
304 | | MediaStream* GetSource() const; |
305 | | |
306 | | /** |
307 | | * Returns the track ID this track is locked to in the source stream of the |
308 | | * input port. |
309 | | */ |
310 | | TrackID GetSourceTrackId() const; |
311 | | |
312 | | MediaInputPort* GetInputPort() const { return mInputPort; } |
313 | | MediaStreamTrack* GetTrack() const { return mTrack; } |
314 | | |
315 | | /** |
316 | | * Blocks aTrackId from going into mInputPort unless the port has been |
317 | | * destroyed. Returns a pledge that gets resolved when the MediaStreamGraph |
318 | | * has applied the block in the playback stream. |
319 | | */ |
320 | | already_AddRefed<media::Pledge<bool, nsresult>> |
321 | | BlockSourceTrackId(TrackID aTrackId, BlockingMode aBlockingMode); |
322 | | |
323 | | private: |
324 | | RefPtr<MediaInputPort> mInputPort; |
325 | | RefPtr<MediaStreamTrack> mTrack; |
326 | | |
327 | | // Defines if we've been given ownership of the input port or if it's owned |
328 | | // externally. The owner is responsible for destroying the port. |
329 | | const InputPortOwnership mOwnership; |
330 | | }; |
331 | | |
332 | | DOMMediaStream(nsPIDOMWindowInner* aWindow, |
333 | | MediaStreamTrackSourceGetter* aTrackSourceGetter); |
334 | | |
335 | | NS_DECL_ISUPPORTS_INHERITED |
336 | | NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMMediaStream, |
337 | | DOMEventTargetHelper) |
338 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMMEDIASTREAM_IID) |
339 | | |
340 | | nsPIDOMWindowInner* GetParentObject() const |
341 | 0 | { |
342 | 0 | return mWindow; |
343 | 0 | } |
344 | | virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; |
345 | | |
346 | | // WebIDL |
347 | | |
348 | | static already_AddRefed<DOMMediaStream> |
349 | | Constructor(const dom::GlobalObject& aGlobal, |
350 | | ErrorResult& aRv); |
351 | | |
352 | | static already_AddRefed<DOMMediaStream> |
353 | | Constructor(const dom::GlobalObject& aGlobal, |
354 | | const DOMMediaStream& aStream, |
355 | | ErrorResult& aRv); |
356 | | |
357 | | static already_AddRefed<DOMMediaStream> |
358 | | Constructor(const dom::GlobalObject& aGlobal, |
359 | | const dom::Sequence<OwningNonNull<MediaStreamTrack>>& aTracks, |
360 | | ErrorResult& aRv); |
361 | | |
362 | | double CurrentTime(); |
363 | | |
364 | | static already_AddRefed<dom::Promise> |
365 | | CountUnderlyingStreams(const dom::GlobalObject& aGlobal, ErrorResult& aRv); |
366 | | |
367 | | void GetId(nsAString& aID) const; |
368 | | |
369 | | void GetAudioTracks(nsTArray<RefPtr<AudioStreamTrack> >& aTracks) const; |
370 | | void GetVideoTracks(nsTArray<RefPtr<VideoStreamTrack> >& aTracks) const; |
371 | | void GetTracks(nsTArray<RefPtr<MediaStreamTrack> >& aTracks) const; |
372 | | MediaStreamTrack* GetTrackById(const nsAString& aId) const; |
373 | | void AddTrack(MediaStreamTrack& aTrack); |
374 | | void RemoveTrack(MediaStreamTrack& aTrack); |
375 | | |
376 | | /** Identical to CloneInternal(TrackForwardingOption::EXPLICIT) */ |
377 | | already_AddRefed<DOMMediaStream> Clone(); |
378 | | |
379 | | bool Active() const; |
380 | | |
381 | | IMPL_EVENT_HANDLER(addtrack) |
382 | | IMPL_EVENT_HANDLER(removetrack) |
383 | | |
384 | | // NON-WebIDL |
385 | | |
386 | | /** |
387 | | * Option to provide to CloneInternal() of which tracks should be forwarded |
388 | | * from the source stream (`this`) to the returned stream clone. |
389 | | * |
390 | | * CURRENT forwards the tracks currently in the source stream's track set. |
391 | | * ALL forwards like EXPLICIT plus any and all future tracks originating |
392 | | * from the same input stream as the source DOMMediaStream (`this`). |
393 | | */ |
394 | | enum class TrackForwardingOption { |
395 | | CURRENT, |
396 | | ALL |
397 | | }; |
398 | | already_AddRefed<DOMMediaStream> CloneInternal(TrackForwardingOption aForwarding); |
399 | | |
400 | | MediaStreamTrack* GetOwnedTrackById(const nsAString& aId); |
401 | | |
402 | | /** |
403 | | * Returns true if this DOMMediaStream has aTrack in its mPlaybackStream. |
404 | | */ |
405 | | bool HasTrack(const MediaStreamTrack& aTrack) const; |
406 | | |
407 | | /** |
408 | | * Returns true if this DOMMediaStream owns aTrack. |
409 | | */ |
410 | | bool OwnsTrack(const MediaStreamTrack& aTrack) const; |
411 | | |
412 | | /** |
413 | | * Returns the corresponding MediaStreamTrack if it's in our mOwnedStream. |
414 | | * aInputTrackID should match the track's TrackID in its input stream, |
415 | | * and aTrackID the TrackID in mOwnedStream. |
416 | | * |
417 | | * When aTrackID is not supplied or set to TRACK_ANY, we return the first |
418 | | * MediaStreamTrack that matches the given input track. Note that there may |
419 | | * be multiple MediaStreamTracks matching the same input track, but that they |
420 | | * in that case all share the same MediaStreamTrackSource. |
421 | | */ |
422 | | MediaStreamTrack* FindOwnedDOMTrack(MediaStream* aInputStream, |
423 | | TrackID aInputTrackID, |
424 | | TrackID aTrackID = TRACK_ANY) const; |
425 | | |
426 | | /** |
427 | | * Returns the TrackPort connecting aTrack's input stream to mOwnedStream, |
428 | | * or nullptr if aTrack is not owned by this DOMMediaStream. |
429 | | */ |
430 | | TrackPort* FindOwnedTrackPort(const MediaStreamTrack& aTrack) const; |
431 | | |
432 | | /** |
433 | | * Returns the corresponding MediaStreamTrack if it's in our mPlaybackStream. |
434 | | * aInputTrackID should match the track's TrackID in its owned stream. |
435 | | */ |
436 | | MediaStreamTrack* FindPlaybackDOMTrack(MediaStream* aInputStream, |
437 | | TrackID aInputTrackID) const; |
438 | | |
439 | | /** |
440 | | * Returns the TrackPort connecting mOwnedStream to mPlaybackStream for aTrack. |
441 | | */ |
442 | | TrackPort* FindPlaybackTrackPort(const MediaStreamTrack& aTrack) const; |
443 | | |
444 | 0 | MediaStream* GetInputStream() const { return mInputStream; } |
445 | | ProcessedMediaStream* GetOwnedStream() const { return mOwnedStream; } |
446 | | ProcessedMediaStream* GetPlaybackStream() const { return mPlaybackStream; } |
447 | | |
448 | | /** |
449 | | * Allows a video element to identify this stream as a camera stream, which |
450 | | * needs special treatment. |
451 | | */ |
452 | | virtual MediaStream* GetCameraStream() const { return nullptr; } |
453 | | |
454 | | /** |
455 | | * Legacy method that returns true when the playback stream has finished. |
456 | | */ |
457 | | bool IsFinished() const; |
458 | | |
459 | | /** |
460 | | * Becomes inactive only when the playback stream has finished. |
461 | | */ |
462 | | void SetInactiveOnFinish(); |
463 | | |
464 | | TrackRate GraphRate(); |
465 | | |
466 | | /** |
467 | | * Returns a principal indicating who may access this stream. The stream contents |
468 | | * can only be accessed by principals subsuming this principal. |
469 | | */ |
470 | | nsIPrincipal* GetPrincipal() { return mPrincipal; } |
471 | | |
472 | | /** |
473 | | * Returns a principal indicating who may access video data of this stream. |
474 | | * The video principal will be a combination of all live video tracks. |
475 | | */ |
476 | | nsIPrincipal* GetVideoPrincipal() { return mVideoPrincipal; } |
477 | | |
478 | | // From PrincipalChangeObserver<MediaStreamTrack>. |
479 | | void PrincipalChanged(MediaStreamTrack* aTrack) override; |
480 | | |
481 | | /** |
482 | | * Add a PrincipalChangeObserver to this stream. |
483 | | * |
484 | | * Returns true if it was successfully added. |
485 | | * |
486 | | * Ownership of the PrincipalChangeObserver remains with the caller, and it's |
487 | | * the caller's responsibility to remove the observer before it dies. |
488 | | */ |
489 | | bool AddPrincipalChangeObserver(dom::PrincipalChangeObserver<DOMMediaStream>* aObserver); |
490 | | |
491 | | /** |
492 | | * Remove an added PrincipalChangeObserver from this stream. |
493 | | * |
494 | | * Returns true if it was successfully removed. |
495 | | */ |
496 | | bool RemovePrincipalChangeObserver(dom::PrincipalChangeObserver<DOMMediaStream>* aObserver); |
497 | | |
498 | | // Webrtc allows the remote side to name a stream whatever it wants, and we |
499 | | // need to surface this to content. |
500 | 0 | void AssignId(const nsAString& aID) { mID = aID; } |
501 | | |
502 | | /** |
503 | | * Create a DOMMediaStream whose underlying input stream is a SourceMediaStream. |
504 | | */ |
505 | | static already_AddRefed<DOMMediaStream> CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow, |
506 | | MediaStreamGraph* aGraph, |
507 | | MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); |
508 | | |
509 | | /** |
510 | | * Create a DOMMediaStream whose underlying input stream is a TrackUnionStream. |
511 | | */ |
512 | | static already_AddRefed<DOMMediaStream> CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow, |
513 | | MediaStreamGraph* aGraph, |
514 | | MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); |
515 | | |
516 | | /** |
517 | | * Create an DOMMediaStream whose underlying input stream is an |
518 | | * AudioCaptureStream. |
519 | | */ |
520 | | static already_AddRefed<DOMMediaStream> |
521 | | CreateAudioCaptureStreamAsInput(nsPIDOMWindowInner* aWindow, |
522 | | nsIPrincipal* aPrincipal, |
523 | | MediaStreamGraph* aGraph); |
524 | | |
525 | | void SetLogicalStreamStartTime(StreamTime aTime) |
526 | | { |
527 | | mLogicalStreamStartTime = aTime; |
528 | | } |
529 | | |
530 | | /** |
531 | | * Adds a MediaStreamTrack to mTracks and raises "addtrack". |
532 | | * |
533 | | * Note that "addtrack" is raised synchronously and only has an effect if |
534 | | * this MediaStream is already exposed to script. For spec compliance this is |
535 | | * to be called from an async task. |
536 | | */ |
537 | | void AddTrackInternal(MediaStreamTrack* aTrack); |
538 | | |
539 | | /** |
540 | | * Called for each track in our owned stream to indicate to JS that we |
541 | | * are carrying that track. |
542 | | * |
543 | | * Pre-creates a MediaStreamTrack and returns it. |
544 | | * It is up to the caller to make sure it is added through AddTrackInternal. |
545 | | */ |
546 | | already_AddRefed<MediaStreamTrack> CreateDOMTrack(TrackID aTrackID, |
547 | | MediaSegment::Type aType, |
548 | | MediaStreamTrackSource* aSource, |
549 | | const MediaTrackConstraints& aConstraints = MediaTrackConstraints()); |
550 | | |
551 | | /** |
552 | | * Creates a MediaStreamTrack cloned from aTrack, adds it to mTracks and |
553 | | * returns it. |
554 | | * aCloneTrackID is the TrackID the new track will get in mOwnedStream. |
555 | | */ |
556 | | already_AddRefed<MediaStreamTrack> CloneDOMTrack(MediaStreamTrack& aTrack, |
557 | | TrackID aCloneTrackID); |
558 | | |
559 | | // When the initial set of tracks has been added, run |
560 | | // aCallback->NotifyTracksAvailable. |
561 | | // It is allowed to do anything, including run script. |
562 | | // aCallback may run immediately during this call if tracks are already |
563 | | // available! |
564 | | // We only care about track additions, we'll fire the notification even if |
565 | | // some of the tracks have been removed. |
566 | | // Takes ownership of aCallback. |
567 | | void OnTracksAvailable(OnTracksAvailableCallback* aCallback); |
568 | | |
569 | | /** |
570 | | * Add an nsISupports object that this stream will keep alive as long as |
571 | | * the stream itself is alive. |
572 | | */ |
573 | | void AddConsumerToKeepAlive(nsISupports* aConsumer) |
574 | | { |
575 | | mConsumersToKeepAlive.AppendElement(aConsumer); |
576 | | } |
577 | | |
578 | | // Registers a track listener to this MediaStream, for listening to changes |
579 | | // to our track set. The caller must call UnregisterTrackListener before |
580 | | // being destroyed, so we don't hold on to a dead pointer. Main thread only. |
581 | | void RegisterTrackListener(TrackListener* aListener); |
582 | | |
583 | | // Unregisters a track listener from this MediaStream. The caller must call |
584 | | // UnregisterTrackListener before being destroyed, so we don't hold on to |
585 | | // a dead pointer. Main thread only. |
586 | | void UnregisterTrackListener(TrackListener* aListener); |
587 | | |
588 | | protected: |
589 | | virtual ~DOMMediaStream(); |
590 | | |
591 | | void Destroy(); |
592 | | void InitSourceStream(MediaStreamGraph* aGraph); |
593 | | void InitTrackUnionStream(MediaStreamGraph* aGraph); |
594 | | void InitAudioCaptureStream(nsIPrincipal* aPrincipal, MediaStreamGraph* aGraph); |
595 | | |
596 | | // Sets up aStream as mInputStream. A producer may append data to a |
597 | | // SourceMediaStream input stream, or connect another stream to a |
598 | | // TrackUnionStream input stream. |
599 | | void InitInputStreamCommon(MediaStream* aStream, MediaStreamGraph* aGraph); |
600 | | |
601 | | // Sets up a new TrackUnionStream as mOwnedStream and connects it to |
602 | | // mInputStream with a TRACK_ANY MediaInputPort if available. |
603 | | // If this DOMMediaStream should have an input stream (producing data), |
604 | | // it has to be initiated before the owned stream. |
605 | | void InitOwnedStreamCommon(MediaStreamGraph* aGraph); |
606 | | |
607 | | // Sets up a new TrackUnionStream as mPlaybackStream and connects it to |
608 | | // mOwnedStream with a TRACK_ANY MediaInputPort if available. |
609 | | // If this DOMMediaStream should have an owned stream (producer or clone), |
610 | | // it has to be initiated before the playback stream. |
611 | | void InitPlaybackStreamCommon(MediaStreamGraph* aGraph); |
612 | | |
613 | | void CheckTracksAvailable(); |
614 | | |
615 | | // Called when MediaStreamGraph has finished an iteration where tracks were |
616 | | // created. |
617 | | void NotifyTracksCreated(); |
618 | | |
619 | | // Called when our playback stream has finished in the MediaStreamGraph. |
620 | | void NotifyFinished(); |
621 | | |
622 | | // Dispatches NotifyActive() to all registered track listeners. |
623 | | void NotifyActive(); |
624 | | |
625 | | // Dispatches NotifyInactive() to all registered track listeners. |
626 | | void NotifyInactive(); |
627 | | |
628 | | // Dispatches NotifyTrackAdded() to all registered track listeners. |
629 | | void NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack); |
630 | | |
631 | | // Dispatches NotifyTrackRemoved() to all registered track listeners. |
632 | | void NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack); |
633 | | |
634 | | // Dispatches "addtrack" or "removetrack". |
635 | | nsresult DispatchTrackEvent(const nsAString& aName, |
636 | | const RefPtr<MediaStreamTrack>& aTrack); |
637 | | |
638 | | class OwnedStreamListener; |
639 | | friend class OwnedStreamListener; |
640 | | |
641 | | class PlaybackStreamListener; |
642 | | friend class PlaybackStreamListener; |
643 | | |
644 | | class PlaybackTrackListener; |
645 | | friend class PlaybackTrackListener; |
646 | | |
647 | | /** |
648 | | * Block a track in our playback stream. Calls NotifyPlaybackTrackBlocked() |
649 | | * after the MediaStreamGraph has applied the block and the track is no longer |
650 | | * live. |
651 | | */ |
652 | | void BlockPlaybackTrack(TrackPort* aTrack); |
653 | | |
654 | | /** |
655 | | * Called on main thread after MediaStreamGraph has applied a track block in |
656 | | * our playback stream. |
657 | | */ |
658 | | void NotifyPlaybackTrackBlocked(); |
659 | | |
660 | | // Recomputes the current principal of this stream based on the set of tracks |
661 | | // it currently contains. PrincipalChangeObservers will be notified only if |
662 | | // the principal changes. |
663 | | void RecomputePrincipal(); |
664 | | |
665 | | // StreamTime at which the currentTime attribute would return 0. |
666 | | StreamTime mLogicalStreamStartTime; |
667 | | |
668 | | // We need this to track our parent object. |
669 | | nsCOMPtr<nsPIDOMWindowInner> mWindow; |
670 | | |
671 | | // MediaStreams are owned by the graph, but we tell them when to die, |
672 | | // and they won't die until we let them. |
673 | | |
674 | | // This stream contains tracks used as input by us. Cloning happens from this |
675 | | // stream. Tracks may exist in these stream but not in |mOwnedStream| if they |
676 | | // have been stopped. |
677 | | MediaStream* mInputStream; |
678 | | |
679 | | // This stream contains tracks owned by us (if we were created directly from |
680 | | // source, or cloned from some other stream). Tracks map to |mOwnedTracks|. |
681 | | ProcessedMediaStream* mOwnedStream; |
682 | | |
683 | | // This stream contains tracks currently played by us, despite of owner. |
684 | | // Tracks map to |mTracks|. |
685 | | ProcessedMediaStream* mPlaybackStream; |
686 | | |
687 | | // This port connects mInputStream to mOwnedStream. All tracks forwarded. |
688 | | RefPtr<MediaInputPort> mOwnedPort; |
689 | | |
690 | | // This port connects mOwnedStream to mPlaybackStream. All tracks not |
691 | | // explicitly blocked due to removal are forwarded. |
692 | | RefPtr<MediaInputPort> mPlaybackPort; |
693 | | |
694 | | // MediaStreamTracks corresponding to tracks in our mOwnedStream. |
695 | | AutoTArray<RefPtr<TrackPort>, 2> mOwnedTracks; |
696 | | |
697 | | // MediaStreamTracks corresponding to tracks in our mPlaybackStream. |
698 | | AutoTArray<RefPtr<TrackPort>, 2> mTracks; |
699 | | |
700 | | // Number of MediaStreamTracks that have been removed on main thread but are |
701 | | // waiting to be removed on MediaStreamGraph thread. |
702 | | size_t mTracksPendingRemoval; |
703 | | |
704 | | // The interface through which we can query the stream producer for |
705 | | // track sources. |
706 | | RefPtr<MediaStreamTrackSourceGetter> mTrackSourceGetter; |
707 | | |
708 | | // Listener tracking changes to mOwnedStream. We use this to notify the |
709 | | // MediaStreamTracks we own about state changes. |
710 | | RefPtr<OwnedStreamListener> mOwnedListener; |
711 | | |
712 | | // Listener tracking changes to mPlaybackStream. This drives state changes |
713 | | // in this DOMMediaStream and notifications to mTrackListeners. |
714 | | RefPtr<PlaybackStreamListener> mPlaybackListener; |
715 | | |
716 | | // Listener tracking when live MediaStreamTracks in mTracks end. |
717 | | RefPtr<PlaybackTrackListener> mPlaybackTrackListener; |
718 | | |
719 | | nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable; |
720 | | |
721 | | // Set to true after MediaStreamGraph has created tracks for mPlaybackStream. |
722 | | bool mTracksCreated; |
723 | | |
724 | | nsString mID; |
725 | | |
726 | | // Keep these alive while the stream is alive. |
727 | | nsTArray<nsCOMPtr<nsISupports>> mConsumersToKeepAlive; |
728 | | |
729 | | bool mNotifiedOfMediaStreamGraphShutdown; |
730 | | |
731 | | // The track listeners subscribe to changes in this stream's track set. |
732 | | nsTArray<TrackListener*> mTrackListeners; |
733 | | |
734 | | // True if this stream has live tracks. |
735 | | bool mActive; |
736 | | |
737 | | // True if this stream only sets mActive to false when its playback stream |
738 | | // finishes. This is a hack to maintain legacy functionality for playing a |
739 | | // HTMLMediaElement::MozCaptureStream(). See bug 1302379. |
740 | | bool mSetInactiveOnFinish; |
741 | | |
742 | | private: |
743 | | void NotifyPrincipalChanged(); |
744 | | // Principal identifying who may access the collected contents of this stream. |
745 | | // If null, this stream can be used by anyone because it has no content yet. |
746 | | nsCOMPtr<nsIPrincipal> mPrincipal; |
747 | | // Video principal is used by video element as access is requested to its |
748 | | // image data. |
749 | | nsCOMPtr<nsIPrincipal> mVideoPrincipal; |
750 | | nsTArray<dom::PrincipalChangeObserver<DOMMediaStream>*> mPrincipalChangeObservers; |
751 | | CORSMode mCORSMode; |
752 | | }; |
753 | | |
754 | | NS_DEFINE_STATIC_IID_ACCESSOR(DOMMediaStream, |
755 | | NS_DOMMEDIASTREAM_IID) |
756 | | |
757 | | #define NS_DOMLOCALMEDIASTREAM_IID \ |
758 | | { 0xb1437260, 0xec61, 0x4dfa, \ |
759 | | { 0x92, 0x54, 0x04, 0x44, 0xe2, 0xb5, 0x94, 0x9c } } |
760 | | |
761 | | class DOMLocalMediaStream : public DOMMediaStream |
762 | | { |
763 | | public: |
764 | | explicit DOMLocalMediaStream(nsPIDOMWindowInner* aWindow, |
765 | | MediaStreamTrackSourceGetter* aTrackSourceGetter) |
766 | | : DOMMediaStream(aWindow, aTrackSourceGetter) {} |
767 | | |
768 | | NS_DECL_ISUPPORTS_INHERITED |
769 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMLOCALMEDIASTREAM_IID) |
770 | | |
771 | | virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; |
772 | | |
773 | | void Stop(); |
774 | | |
775 | | /** |
776 | | * Create an nsDOMLocalMediaStream whose underlying stream is a SourceMediaStream. |
777 | | */ |
778 | | static already_AddRefed<DOMLocalMediaStream> |
779 | | CreateSourceStreamAsInput(nsPIDOMWindowInner* aWindow, |
780 | | MediaStreamGraph* aGraph, |
781 | | MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); |
782 | | |
783 | | /** |
784 | | * Create an nsDOMLocalMediaStream whose underlying stream is a TrackUnionStream. |
785 | | */ |
786 | | static already_AddRefed<DOMLocalMediaStream> |
787 | | CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow, |
788 | | MediaStreamGraph* aGraph, |
789 | | MediaStreamTrackSourceGetter* aTrackSourceGetter = nullptr); |
790 | | |
791 | | protected: |
792 | | virtual ~DOMLocalMediaStream(); |
793 | | |
794 | | void StopImpl(); |
795 | | }; |
796 | | |
797 | | NS_DEFINE_STATIC_IID_ACCESSOR(DOMLocalMediaStream, |
798 | | NS_DOMLOCALMEDIASTREAM_IID) |
799 | | |
800 | | class DOMAudioNodeMediaStream : public DOMMediaStream |
801 | | { |
802 | | typedef dom::AudioNode AudioNode; |
803 | | public: |
804 | | DOMAudioNodeMediaStream(nsPIDOMWindowInner* aWindow, AudioNode* aNode); |
805 | | |
806 | | NS_DECL_ISUPPORTS_INHERITED |
807 | | NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMAudioNodeMediaStream, DOMMediaStream) |
808 | | |
809 | | /** |
810 | | * Create a DOMAudioNodeMediaStream whose underlying stream is a TrackUnionStream. |
811 | | */ |
812 | | static already_AddRefed<DOMAudioNodeMediaStream> |
813 | | CreateTrackUnionStreamAsInput(nsPIDOMWindowInner* aWindow, |
814 | | AudioNode* aNode, |
815 | | MediaStreamGraph* aGraph); |
816 | | |
817 | | protected: |
818 | | ~DOMAudioNodeMediaStream(); |
819 | | |
820 | | private: |
821 | | // If this object wraps a stream owned by an AudioNode, we need to ensure that |
822 | | // the node isn't cycle-collected too early. |
823 | | RefPtr<AudioNode> mStreamNode; |
824 | | }; |
825 | | |
826 | | } // namespace mozilla |
827 | | |
828 | | #endif /* NSDOMMEDIASTREAM_H_ */ |