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