Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/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
0
  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
0
  {
87
0
  }
88
89
  virtual already_AddRefed<dom::MediaStreamTrackSource>
90
  GetMediaStreamTrackSource(TrackID aInputTrackID) = 0;
91
92
protected:
93
  virtual ~MediaStreamTrackSourceGetter()
94
0
  {
95
0
  }
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
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
    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
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
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMMediaStream,
337
                                           DOMEventTargetHelper)
338
  NS_DECLARE_STATIC_IID_ACCESSOR(NS_DOMMEDIASTREAM_IID)
339
340
  nsPIDOMWindowInner* GetParentObject() const
341
  {
342
    return mWindow;
343
  }
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
  MediaStream* GetInputStream() const { return mInputStream; }
445
0
  ProcessedMediaStream* GetOwnedStream() const { return mOwnedStream; }
446
0
  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
0
  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
0
  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
0
  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
  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
0
  {
527
0
    mLogicalStreamStartTime = aTime;
528
0
  }
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
0
  {
575
0
    mConsumersToKeepAlive.AppendElement(aConsumer);
576
0
  }
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
0
    : 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_ */