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
--- 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
@@ -2282,25 +2282,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
@@ -1189,30 +1189,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
@@ -1987,22 +1987,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: