Bug 1259788 - Break out AddTrackInternal() from DOMMediaStream::CreateDOMTrack. r=jesup
authorAndreas Pehrson <pehrsons@gmail.com>
Fri, 12 Aug 2016 13:50:41 +0200
changeset 311196 7b797b5a2da378842a322ffc81642e9e2174c88e
parent 311195 d63f814b204d4d5fca42df2ace73bd4f123a8845
child 311197 da81522029f7097524d134c3dcdcb3d8cd01f237
push id81074
push userkwierso@gmail.com
push dateFri, 26 Aug 2016 00:14:36 +0000
treeherdermozilla-inbound@a7be6d4320fa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1259788
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1259788 - Break out AddTrackInternal() from DOMMediaStream::CreateDOMTrack. r=jesup Sometimes a track is added to a stream synchronously (before the stream is exposed to script), and sometimes asynchronously (see the mediacapture-main spec on the "addtrack" event). In the latter case we might still need to create the MediaStreamTrack object synchronously for tracking purposes. CaptureStream of Media element playing a MediaStream wants this. MozReview-Commit-ID: 7me8xzN7rwj
dom/html/HTMLCanvasElement.cpp
dom/html/HTMLMediaElement.cpp
dom/media/DOMMediaStream.cpp
dom/media/DOMMediaStream.h
dom/media/MediaManager.cpp
dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/test/FakeMediaStreams.h
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -681,18 +681,20 @@ HTMLCanvasElement::CaptureStream(const O
   nsCOMPtr<nsIPrincipal> principal = NodePrincipal();
   nsresult rv =
     stream->Init(aFrameRate, videoTrackId, principal);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
+  RefPtr<MediaStreamTrack> track =
   stream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO,
                          new BasicUnstoppableTrackSource(principal));
+  stream->AddTrackInternal(track);
 
   rv = RegisterFrameCaptureListener(stream->FrameCaptureListener());
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
   return stream.forget();
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -2283,25 +2283,29 @@ HTMLMediaElement::CaptureStreamInternal(
     mDecoder->AddOutputStream(out->mStream->GetInputStream()->AsProcessedStream(),
                               aFinishWhenEnded);
     if (mReadyState >= HAVE_METADATA) {
       // Expose the tracks to JS directly.
       if (HasAudio()) {
         TrackID audioTrackId = mMediaInfo.mAudio.mTrackId;
         RefPtr<MediaStreamTrackSource> trackSource =
           getter->GetMediaStreamTrackSource(audioTrackId);
-        out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO,
-                                     trackSource);
+        RefPtr<MediaStreamTrack> track =
+          out->mStream->CreateDOMTrack(audioTrackId, MediaSegment::AUDIO,
+                                       trackSource);
+        out->mStream->AddTrackInternal(track);
       }
       if (HasVideo()) {
         TrackID videoTrackId = mMediaInfo.mVideo.mTrackId;
         RefPtr<MediaStreamTrackSource> trackSource =
           getter->GetMediaStreamTrackSource(videoTrackId);
-        out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO,
-                                     trackSource);
+        RefPtr<MediaStreamTrack> track =
+          out->mStream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO,
+                                       trackSource);
+        out->mStream->AddTrackInternal(track);
       }
     }
   }
   RefPtr<DOMMediaStream> result = out->mStream;
   return result.forget();
 }
 
 already_AddRefed<DOMMediaStream>
--- a/dom/media/DOMMediaStream.cpp
+++ b/dom/media/DOMMediaStream.cpp
@@ -157,17 +157,19 @@ public:
       }
       if (!source) {
         NS_ASSERTION(false, "Dynamic track created without an explicit TrackSource");
         nsPIDOMWindowInner* window = mStream->GetParentObject();
         nsIDocument* doc = window ? window->GetExtantDoc() : nullptr;
         nsIPrincipal* principal = doc ? doc->NodePrincipal() : nullptr;
         source = new BasicUnstoppableTrackSource(principal);
       }
-      track = mStream->CreateDOMTrack(aTrackID, aType, source);
+      RefPtr<MediaStreamTrack> newTrack =
+        mStream->CreateDOMTrack(aTrackID, aType, source);
+      mStream->AddTrackInternal(newTrack);
     }
   }
 
   void DoNotifyTrackEnded(MediaStream* aInputStream, TrackID aInputTrackID,
                           TrackID aTrackID)
   {
     MOZ_ASSERT(NS_IsMainThread());
 
@@ -804,17 +806,20 @@ DOMMediaStream::InitAudioCaptureStream(n
   RefPtr<BasicUnstoppableTrackSource> audioCaptureSource =
     new BasicUnstoppableTrackSource(aPrincipal, MediaSourceEnum::AudioCapture);
 
   AudioCaptureStream* audioCaptureStream =
     static_cast<AudioCaptureStream*>(aGraph->CreateAudioCaptureStream(AUDIO_TRACK));
   InitInputStreamCommon(audioCaptureStream, aGraph);
   InitOwnedStreamCommon(aGraph);
   InitPlaybackStreamCommon(aGraph);
-  CreateDOMTrack(AUDIO_TRACK, MediaSegment::AUDIO, audioCaptureSource);
+  RefPtr<MediaStreamTrack> track =
+    CreateDOMTrack(AUDIO_TRACK, MediaSegment::AUDIO, audioCaptureSource);
+  AddTrackInternal(track);
+
   audioCaptureStream->Start();
 }
 
 void
 DOMMediaStream::InitInputStreamCommon(MediaStream* aStream,
                                       MediaStreamGraph* aGraph)
 {
   MOZ_ASSERT(!mOwnedStream, "Input stream must be initialized before owned stream");
@@ -972,51 +977,65 @@ DOMMediaStream::AddPrincipalChangeObserv
 
 bool
 DOMMediaStream::RemovePrincipalChangeObserver(
   PrincipalChangeObserver<DOMMediaStream>* aObserver)
 {
   return mPrincipalChangeObservers.RemoveElement(aObserver);
 }
 
-MediaStreamTrack*
+void
+DOMMediaStream::AddTrackInternal(MediaStreamTrack* aTrack)
+{
+  MOZ_ASSERT(aTrack->mOwningStream == this);
+  MOZ_ASSERT(FindOwnedDOMTrack(aTrack->GetInputStream(),
+                               aTrack->mInputTrackID,
+                               aTrack->mTrackID));
+  MOZ_ASSERT(!FindPlaybackDOMTrack(aTrack->GetOwnedStream(),
+                                   aTrack->mTrackID));
+
+  LOG(LogLevel::Debug, ("DOMMediaStream %p Adding owned track %p", this, aTrack));
+
+  mTracks.AppendElement(
+    new TrackPort(mPlaybackPort, aTrack, TrackPort::InputPortOwnership::EXTERNAL));
+
+  NotifyTrackAdded(aTrack);
+
+  DispatchTrackEvent(NS_LITERAL_STRING("addtrack"), aTrack);
+}
+
+already_AddRefed<MediaStreamTrack>
 DOMMediaStream::CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType,
                                MediaStreamTrackSource* aSource,
                                const MediaTrackConstraints& aConstraints)
 {
   MOZ_RELEASE_ASSERT(mInputStream);
   MOZ_RELEASE_ASSERT(mOwnedStream);
 
   MOZ_ASSERT(FindOwnedDOMTrack(GetInputStream(), aTrackID) == nullptr);
 
-  MediaStreamTrack* track;
+  RefPtr<MediaStreamTrack> track;
   switch (aType) {
   case MediaSegment::AUDIO:
     track = new AudioStreamTrack(this, aTrackID, aTrackID, aSource, aConstraints);
     break;
   case MediaSegment::VIDEO:
     track = new VideoStreamTrack(this, aTrackID, aTrackID, aSource, aConstraints);
     break;
   default:
     MOZ_CRASH("Unhandled track type");
   }
 
-  LOG(LogLevel::Debug, ("DOMMediaStream %p Created new track %p with ID %u", this, track, aTrackID));
+  LOG(LogLevel::Debug, ("DOMMediaStream %p Created new track %p with ID %u",
+                        this, track.get(), aTrackID));
 
   mOwnedTracks.AppendElement(
     new TrackPort(mOwnedPort, track, TrackPort::InputPortOwnership::EXTERNAL));
 
-  mTracks.AppendElement(
-    new TrackPort(mPlaybackPort, track, TrackPort::InputPortOwnership::EXTERNAL));
-
-  NotifyTrackAdded(track);
-
-  DispatchTrackEvent(NS_LITERAL_STRING("addtrack"), track);
-
-  return track;
+  return track.forget();
 }
 
 already_AddRefed<MediaStreamTrack>
 DOMMediaStream::CloneDOMTrack(MediaStreamTrack& aTrack,
                               TrackID aCloneTrackID)
 {
   MOZ_RELEASE_ASSERT(mOwnedStream);
   MOZ_RELEASE_ASSERT(mPlaybackStream);
--- a/dom/media/DOMMediaStream.h
+++ b/dom/media/DOMMediaStream.h
@@ -506,29 +506,35 @@ public:
                                   MediaStreamGraph* aGraph);
 
   void SetLogicalStreamStartTime(StreamTime aTime)
   {
     mLogicalStreamStartTime = aTime;
   }
 
   /**
-   * Called for each track in our owned stream to indicate to JS that we
-   * are carrying that track.
-   *
-   * Creates a MediaStreamTrack, adds it to mTracks, raises "addtrack" and
-   * returns it.
+   * Adds a MediaStreamTrack to mTracks and raises "addtrack".
    *
    * Note that "addtrack" is raised synchronously and only has an effect if
    * this MediaStream is already exposed to script. For spec compliance this is
    * to be called from an async task.
    */
-  MediaStreamTrack* CreateDOMTrack(TrackID aTrackID, MediaSegment::Type aType,
-      MediaStreamTrackSource* aSource,
-      const MediaTrackConstraints& aConstraints = MediaTrackConstraints());
+  void AddTrackInternal(MediaStreamTrack* aTrack);
+
+  /**
+   * Called for each track in our owned stream to indicate to JS that we
+   * are carrying that track.
+   *
+   * Pre-creates a MediaStreamTrack and returns it.
+   * It is up to the caller to make sure it is added through AddTrackInternal.
+   */
+  already_AddRefed<MediaStreamTrack> CreateDOMTrack(TrackID aTrackID,
+                                                    MediaSegment::Type aType,
+                                                    MediaStreamTrackSource* aSource,
+                                                    const MediaTrackConstraints& aConstraints = MediaTrackConstraints());
 
   /**
    * Creates a MediaStreamTrack cloned from aTrack, adds it to mTracks and
    * returns it.
    * aCloneTrackID is the TrackID the new track will get in mOwnedStream.
    */
   already_AddRefed<MediaStreamTrack> CloneDOMTrack(MediaStreamTrack& aTrack,
                                                    TrackID aCloneTrackID);
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -1202,30 +1202,34 @@ public:
         nsString audioDeviceName;
         mAudioDevice->GetName(audioDeviceName);
         const MediaSourceEnum source =
           mAudioDevice->GetSource()->GetMediaSource();
         RefPtr<MediaStreamTrackSource> audioSource =
           new LocalTrackSource(principal, audioDeviceName, mListener, source,
                                kAudioTrack, mPeerIdentity);
         MOZ_ASSERT(IsOn(mConstraints.mAudio));
-        domStream->CreateDOMTrack(kAudioTrack, MediaSegment::AUDIO, audioSource,
-                                  GetInvariant(mConstraints.mAudio));
+        RefPtr<MediaStreamTrack> track =
+          domStream->CreateDOMTrack(kAudioTrack, MediaSegment::AUDIO, audioSource,
+                                    GetInvariant(mConstraints.mAudio));
+        domStream->AddTrackInternal(track);
       }
       if (mVideoDevice) {
         nsString videoDeviceName;
         mVideoDevice->GetName(videoDeviceName);
         const MediaSourceEnum source =
           mVideoDevice->GetSource()->GetMediaSource();
         RefPtr<MediaStreamTrackSource> videoSource =
           new LocalTrackSource(principal, videoDeviceName, mListener, source,
                                kVideoTrack, mPeerIdentity);
         MOZ_ASSERT(IsOn(mConstraints.mVideo));
-        domStream->CreateDOMTrack(kVideoTrack, MediaSegment::VIDEO, videoSource,
-                                  GetInvariant(mConstraints.mVideo));
+        RefPtr<MediaStreamTrack> track =
+          domStream->CreateDOMTrack(kVideoTrack, MediaSegment::VIDEO, videoSource,
+                                    GetInvariant(mConstraints.mVideo));
+        domStream->AddTrackInternal(track);
       }
       stream = domStream->GetInputStream()->AsSourceStream();
     }
 
     if (!domStream || sInShutdown) {
       nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
       LOG(("Returning error for getUserMedia() - no stream"));
 
--- a/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
+++ b/dom/media/webaudio/MediaStreamAudioDestinationNode.cpp
@@ -34,19 +34,21 @@ MediaStreamAudioDestinationNode::MediaSt
                                                              this,
                                                              aContext->Graph()))
 {
   // Ensure an audio track with the correct ID is exposed to JS
   nsIDocument* doc = aContext->GetParentObject()->GetExtantDoc();
   RefPtr<MediaStreamTrackSource> source =
     new BasicUnstoppableTrackSource(doc->NodePrincipal(),
                                     MediaSourceEnum::AudioCapture);
-  mDOMStream->CreateDOMTrack(AudioNodeStream::AUDIO_TRACK,
-                             MediaSegment::AUDIO, source,
-                             MediaTrackConstraints());
+  RefPtr<MediaStreamTrack> track =
+    mDOMStream->CreateDOMTrack(AudioNodeStream::AUDIO_TRACK,
+                               MediaSegment::AUDIO, source,
+                               MediaTrackConstraints());
+  mDOMStream->AddTrackInternal(track);
 
   ProcessedMediaStream* outputStream = mDOMStream->GetInputStream()->AsProcessedStream();
   MOZ_ASSERT(!!outputStream);
   AudioNodeEngine* engine = new AudioNodeEngine(this);
   mStream = AudioNodeStream::Create(aContext, engine,
                                     AudioNodeStream::EXTERNAL_OUTPUT);
   mPort = outputStream->AllocateInputPort(mStream, AudioNodeStream::AUDIO_TRACK);
 }
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -1988,22 +1988,24 @@ PeerConnectionImpl::CreateNewRemoteTrack
         TrackID trackID = ++maxTrackId;
         RefPtr<MediaStreamTrack> domTrack;
         nsAutoPtr<MediaSegment> segment;
         if (track->GetMediaType() == SdpMediaSection::kAudio) {
           domTrack =
             info->GetMediaStream()->CreateDOMTrack(trackID,
                                                    MediaSegment::AUDIO,
                                                    source);
+          info->GetMediaStream()->AddTrackInternal(domTrack);
           segment = new AudioSegment;
         } else {
           domTrack =
             info->GetMediaStream()->CreateDOMTrack(trackID,
                                                    MediaSegment::VIDEO,
                                                    source);
+          info->GetMediaStream()->AddTrackInternal(domTrack);
 #if !defined(MOZILLA_EXTERNAL_LINKAGE)
           segment = new VideoSegment;
 #endif
         }
 
         StartTrack(info->GetMediaStream()->GetInputStream()->AsSourceStream(),
                    trackID, Move(segment));
         info->AddTrack(webrtcTrackId, domTrack);
--- a/media/webrtc/signaling/test/FakeMediaStreams.h
+++ b/media/webrtc/signaling/test/FakeMediaStreams.h
@@ -560,26 +560,28 @@ public:
   bool
   OwnsTrack(const Fake_MediaStreamTrack& aTrack) const
   {
     return HasTrack(aTrack);
   }
 
   void SetTrackEnabled(mozilla::TrackID aTrackID, bool aEnabled) {}
 
-  Fake_MediaStreamTrack*
+  void AddTrackInternal(Fake_MediaStreamTrack* aTrack) {}
+
+  already_AddRefed<Fake_MediaStreamTrack>
   CreateDOMTrack(mozilla::TrackID aTrackID, mozilla::MediaSegment::Type aType,
                  Fake_MediaStreamTrackSource* aSource)
   {
     switch(aType) {
       case mozilla::MediaSegment::AUDIO: {
-        return mAudioTrack;
+        return do_AddRef(mAudioTrack);
       }
       case mozilla::MediaSegment::VIDEO: {
-        return mVideoTrack;
+        return do_AddRef(mVideoTrack);
       }
       default: {
         MOZ_CRASH("Unkown media type");
       }
     }
   }
 
 private: