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

MozReview-Commit-ID: FZQIWYZcEDr

--HG--
extra : rebase_source : 33336f84b8ab4f4fe9cc5bf734a7e3b587ff8729
This commit is contained in:
Andreas Pehrson 2016-01-22 16:51:37 +08:00
parent 660d9407e0
commit d81423155b
3 changed files with 126 additions and 4 deletions

View File

@ -390,15 +390,15 @@ DOMMediaStream::Destroy()
mOwnedPort = nullptr;
}
if (mPlaybackStream) {
mPlaybackStream->Destroy();
mPlaybackStream->UnregisterUser();
mPlaybackStream = nullptr;
}
if (mOwnedStream) {
mOwnedStream->Destroy();
mOwnedStream->UnregisterUser();
mOwnedStream = nullptr;
}
if (mInputStream) {
mInputStream->Destroy();
mInputStream->UnregisterUser();
mInputStream = nullptr;
}
}
@ -596,6 +596,108 @@ DOMMediaStream::RemoveTrack(MediaStreamTrack& aTrack)
LOG(LogLevel::Debug, ("DOMMediaStream %p Removed track %p", this, &aTrack));
}
class ClonedStreamSourceGetter :
public MediaStreamTrackSourceGetter
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ClonedStreamSourceGetter,
MediaStreamTrackSourceGetter)
explicit ClonedStreamSourceGetter(DOMMediaStream* aStream)
: mStream(aStream) {}
already_AddRefed<MediaStreamTrackSource>
GetMediaStreamTrackSource(TrackID aInputTrackID) override
{
MediaStreamTrack* sourceTrack =
mStream->FindOwnedDOMTrack(mStream->GetOwnedStream(), aInputTrackID);
MOZ_RELEASE_ASSERT(sourceTrack);
return do_AddRef(&sourceTrack->GetSource());
}
protected:
virtual ~ClonedStreamSourceGetter() {}
RefPtr<DOMMediaStream> mStream;
};
NS_IMPL_ADDREF_INHERITED(ClonedStreamSourceGetter,
MediaStreamTrackSourceGetter)
NS_IMPL_RELEASE_INHERITED(ClonedStreamSourceGetter,
MediaStreamTrackSourceGetter)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ClonedStreamSourceGetter)
NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackSourceGetter)
NS_IMPL_CYCLE_COLLECTION_INHERITED(ClonedStreamSourceGetter,
MediaStreamTrackSourceGetter,
mStream)
already_AddRefed<DOMMediaStream>
DOMMediaStream::Clone()
{
return CloneInternal(TrackForwardingOption::CURRENT);
}
already_AddRefed<DOMMediaStream>
DOMMediaStream::CloneInternal(TrackForwardingOption aForwarding)
{
RefPtr<DOMMediaStream> newStream =
new DOMMediaStream(GetParentObject(), new ClonedStreamSourceGetter(this));
LOG(LogLevel::Info, ("DOMMediaStream %p created clone %p, forwarding %s tracks",
this, newStream.get(),
aForwarding == TrackForwardingOption::ALL
? "all" : "current"));
MOZ_RELEASE_ASSERT(mPlaybackStream);
MOZ_RELEASE_ASSERT(mPlaybackStream->Graph());
MediaStreamGraph* graph = mPlaybackStream->Graph();
// We initiate the owned and playback streams first, since we need to create
// all existing DOM tracks before we add the generic input port from
// mInputStream to mOwnedStream (see AllocateInputPort wrt. destination
// TrackID as to why).
newStream->InitOwnedStreamCommon(graph);
newStream->InitPlaybackStreamCommon(graph);
// Set up existing DOM tracks.
TrackID allocatedTrackID = 1;
for (const RefPtr<TrackPort>& info : mTracks) {
MediaStreamTrack& track = *info->GetTrack();
LOG(LogLevel::Debug, ("DOMMediaStream %p forwarding external track %p to clone %p",
this, &track, newStream.get()));
RefPtr<MediaStreamTrack> trackClone =
newStream->CreateClonedDOMTrack(track, allocatedTrackID++);
}
if (aForwarding == TrackForwardingOption::ALL) {
// Set up an input port from our input stream to the new DOM stream's owned
// stream, to allow for dynamically added tracks at the source to appear in
// the clone. The clone may treat mInputStream as its own mInputStream but
// ownership remains with us.
newStream->mInputStream = mInputStream;
if (mInputStream) {
// We have already set up track-locked input ports for all existing DOM
// tracks, so now we need to block those in the generic input port to
// avoid ending up with double instances of them.
nsTArray<TrackID> tracksToBlock;
for (const RefPtr<TrackPort>& info : mOwnedTracks) {
tracksToBlock.AppendElement(info->GetTrack()->mTrackID);
}
newStream->mInputStream->RegisterUser();
newStream->mOwnedPort =
newStream->mOwnedStream->AllocateInputPort(mInputStream,
TRACK_ANY, TRACK_ANY, 0, 0,
&tracksToBlock);
}
}
return newStream.forget();
}
MediaStreamTrack*
DOMMediaStream::GetTrackById(const nsString& aId)
{
@ -698,6 +800,7 @@ DOMMediaStream::InitInputStreamCommon(MediaStream* aStream,
MOZ_ASSERT(!mOwnedStream, "Input stream must be initialized before owned stream");
mInputStream = aStream;
mInputStream->RegisterUser();
}
void
@ -709,6 +812,7 @@ DOMMediaStream::InitOwnedStreamCommon(MediaStreamGraph* aGraph)
// streams. This is only needed for the playback stream.
mOwnedStream = aGraph->CreateTrackUnionStream(nullptr);
mOwnedStream->SetAutofinish(true);
mOwnedStream->RegisterUser();
if (mInputStream) {
mOwnedPort = mOwnedStream->AllocateInputPort(mInputStream);
}
@ -723,6 +827,7 @@ DOMMediaStream::InitPlaybackStreamCommon(MediaStreamGraph* aGraph)
{
mPlaybackStream = aGraph->CreateTrackUnionStream(this);
mPlaybackStream->SetAutofinish(true);
mPlaybackStream->RegisterUser();
if (mOwnedStream) {
mPlaybackPort = mPlaybackStream->AllocateInputPort(mOwnedStream);
}

View File

@ -362,8 +362,25 @@ public:
void AddTrack(MediaStreamTrack& aTrack);
void RemoveTrack(MediaStreamTrack& aTrack);
/** Identical to CloneInternal(TrackForwardingOption::EXPLICIT) */
already_AddRefed<DOMMediaStream> Clone();
// NON-WebIDL
/**
* Option to provide to CloneInternal() of which tracks should be forwarded
* from the source stream (`this`) to the returned stream clone.
*
* CURRENT forwards the tracks currently in the source stream's track set.
* ALL forwards like EXPLICIT plus any and all future tracks originating
* from the same input stream as the source DOMMediaStream (`this`).
*/
enum class TrackForwardingOption {
CURRENT,
ALL
};
already_AddRefed<DOMMediaStream> CloneInternal(TrackForwardingOption aForwarding);
MediaStreamTrack* GetTrackById(const nsString& aId);
MediaStreamTrack* GetOwnedTrackById(const nsString& aId);

View File

@ -39,7 +39,7 @@ interface MediaStream : EventTarget {
// MediaStreamTrack? getTrackById (DOMString trackId);
void addTrack (MediaStreamTrack track);
void removeTrack (MediaStreamTrack track);
// MediaStream clone ();
MediaStream clone ();
// readonly attribute boolean active;
// attribute EventHandler onactive;
// attribute EventHandler oninactive;