Bug 1208371 - Implement MediaStreamTrack::Clone(). r=smaug,jib,roc

MozReview-Commit-ID: HrL0RFMcG4B

--HG--
extra : rebase_source : 2b07983ebec0c0a7016b8a0e0e64ad38486d035b
This commit is contained in:
Andreas Pehrson 2016-01-22 16:27:51 +08:00
parent d8ed56d953
commit 660d9407e0
7 changed files with 100 additions and 8 deletions

View File

@ -27,6 +27,17 @@ public:
// WebIDL
void GetKind(nsAString& aKind) override { aKind.AssignLiteral("audio"); }
protected:
already_AddRefed<MediaStreamTrack> CloneInternal(DOMMediaStream* aOwningStream,
TrackID aTrackID) override
{
return do_AddRef(new AudioStreamTrack(aOwningStream,
aTrackID,
mInputTrackID,
mLabel,
mSource));
}
};
} // namespace dom

View File

@ -863,18 +863,51 @@ DOMMediaStream::CreateOwnDOMTrack(TrackID aTrackID, MediaSegment::Type aType,
LOG(LogLevel::Debug, ("DOMMediaStream %p Created new track %p with ID %u", this, track, aTrackID));
RefPtr<TrackPort> ownedTrackPort =
new TrackPort(mOwnedPort, track, TrackPort::InputPortOwnership::EXTERNAL);
mOwnedTracks.AppendElement(ownedTrackPort.forget());
mOwnedTracks.AppendElement(
new TrackPort(mOwnedPort, track, TrackPort::InputPortOwnership::EXTERNAL));
RefPtr<TrackPort> playbackTrackPort =
new TrackPort(mPlaybackPort, track, TrackPort::InputPortOwnership::EXTERNAL);
mTracks.AppendElement(playbackTrackPort.forget());
mTracks.AppendElement(
new TrackPort(mPlaybackPort, track, TrackPort::InputPortOwnership::EXTERNAL));
NotifyTrackAdded(track);
return track;
}
already_AddRefed<MediaStreamTrack>
DOMMediaStream::CreateClonedDOMTrack(MediaStreamTrack& aTrack,
TrackID aCloneTrackID)
{
MOZ_RELEASE_ASSERT(mOwnedStream);
MOZ_RELEASE_ASSERT(mPlaybackStream);
MOZ_RELEASE_ASSERT(IsTrackIDExplicit(aCloneTrackID));
TrackID inputTrackID = aTrack.mInputTrackID;
MediaStream* inputStream = aTrack.GetInputStream();
RefPtr<MediaStreamTrack> newTrack = aTrack.CloneInternal(this, aCloneTrackID);
newTrack->mOriginalTrack =
aTrack.mOriginalTrack ? aTrack.mOriginalTrack.get() : &aTrack;
LOG(LogLevel::Debug, ("DOMMediaStream %p Created new track %p cloned from stream %p track %d",
this, newTrack.get(), inputStream, inputTrackID));
RefPtr<MediaInputPort> inputPort =
mOwnedStream->AllocateInputPort(inputStream, inputTrackID, aCloneTrackID);
mOwnedTracks.AppendElement(
new TrackPort(inputPort, newTrack, TrackPort::InputPortOwnership::OWNED));
mTracks.AppendElement(
new TrackPort(mPlaybackPort, newTrack, TrackPort::InputPortOwnership::EXTERNAL));
NotifyTrackAdded(newTrack);
newTrack->SetEnabled(aTrack.Enabled());
return newTrack.forget();
}
MediaStreamTrack*
DOMMediaStream::FindOwnedDOMTrack(MediaStream* aInputStream,
TrackID aInputTrackID) const
@ -907,7 +940,11 @@ DOMMediaStream::FindOwnedTrackPort(const MediaStreamTrack& aTrack) const
MediaStreamTrack*
DOMMediaStream::FindPlaybackDOMTrack(MediaStream* aInputStream, TrackID aInputTrackID) const
{
MOZ_RELEASE_ASSERT(mPlaybackStream);
if (!mPlaybackStream) {
// One would think we can assert mPlaybackStream here, but track clones have
// a dummy DOMMediaStream that doesn't have a playback stream, so we can't.
return nullptr;
}
for (const RefPtr<TrackPort>& info : mTracks) {
if (info->GetInputPort() == mPlaybackPort &&

View File

@ -518,6 +518,14 @@ public:
const nsString& aLabel,
MediaStreamTrackSource* aSource);
/**
* 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> CreateClonedDOMTrack(MediaStreamTrack& aTrack,
TrackID aCloneTrackID);
// When the initial set of tracks has been added, run
// aCallback->NotifyTracksAvailable.
// It is allowed to do anything, including run script.

View File

@ -200,6 +200,22 @@ MediaStreamTrack::RemovePrincipalChangeObserver(
return mPrincipalChangeObservers.RemoveElement(aObserver);
}
already_AddRefed<MediaStreamTrack>
MediaStreamTrack::Clone()
{
// MediaStreamTracks are currently governed by streams, so we need a dummy
// DOMMediaStream to own our track clone. The dummy will never see any
// dynamically created tracks (no input stream) so no need for a SourceGetter.
RefPtr<DOMMediaStream> newStream =
new DOMMediaStream(mOwningStream->GetParentObject(), nullptr);
MediaStreamGraph* graph = Graph();
newStream->InitOwnedStreamCommon(graph);
newStream->InitPlaybackStreamCommon(graph);
return newStream->CreateClonedDOMTrack(*this, mTrackID);
}
DOMMediaStream*
MediaStreamTrack::GetInputDOMStream()
{

View File

@ -215,6 +215,7 @@ public:
void Stop();
already_AddRefed<Promise>
ApplyConstraints(const dom::MediaTrackConstraints& aConstraints, ErrorResult &aRv);
already_AddRefed<MediaStreamTrack> Clone();
bool Ended() const { return mEnded; }
// Notifications from the MediaStreamGraph
@ -282,6 +283,14 @@ protected:
// the original track's owning DOMMediaStream is returned.
DOMMediaStream* GetInputDOMStream();
/**
* Creates a new MediaStreamTrack with the same type, input track ID and
* source as this MediaStreamTrack.
* aTrackID is the TrackID the new track will have in its owned stream.
*/
virtual already_AddRefed<MediaStreamTrack> CloneInternal(DOMMediaStream* aOwningStream,
TrackID aTrackID) = 0;
nsTArray<PrincipalChangeObserver<MediaStreamTrack>*> mPrincipalChangeObservers;
RefPtr<DOMMediaStream> mOwningStream;

View File

@ -27,6 +27,17 @@ public:
// WebIDL
void GetKind(nsAString& aKind) override { aKind.AssignLiteral("video"); }
protected:
already_AddRefed<MediaStreamTrack> CloneInternal(DOMMediaStream* aOwningStream,
TrackID aTrackID) override
{
return do_AddRef(new VideoStreamTrack(aOwningStream,
aTrackID,
mInputTrackID,
mLabel,
mSource));
}
};
} // namespace dom

View File

@ -76,7 +76,7 @@ interface MediaStreamTrack : EventTarget {
// readonly attribute boolean remote;
// readonly attribute MediaStreamTrackState readyState;
// attribute EventHandler onended;
// MediaStreamTrack clone ();
MediaStreamTrack clone ();
void stop ();
// MediaTrackCapabilities getCapabilities ();
// MediaTrackConstraints getConstraints ();