зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1208316 - Route notifications of ending tracks through MediaStreamTrack instead of DOMMediaStream. r=jib
MozReview-Commit-ID: KMFE5HXEOtJ --HG-- extra : rebase_source : 279dffcdd325a5ac78f115803269a724887b6ac0
This commit is contained in:
Родитель
d88a8a02fa
Коммит
da3ba8634d
|
@ -236,40 +236,6 @@ public:
|
|||
mStream = nullptr;
|
||||
}
|
||||
|
||||
void DoNotifyTrackEnded(MediaStream* aInputStream,
|
||||
TrackID aInputTrackID)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mStream) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(LogLevel::Debug, ("DOMMediaStream %p Track %u of stream %p ended",
|
||||
mStream, aInputTrackID, aInputStream));
|
||||
|
||||
RefPtr<MediaStreamTrack> track =
|
||||
mStream->FindPlaybackDOMTrack(aInputStream, aInputTrackID);
|
||||
if (!track) {
|
||||
LOG(LogLevel::Debug, ("DOMMediaStream %p Not a playback track.", mStream));
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(LogLevel::Debug, ("DOMMediaStream %p Playback track; notifying stream listeners.",
|
||||
mStream));
|
||||
mStream->NotifyTrackRemoved(track);
|
||||
|
||||
RefPtr<TrackPort> endedPort = mStream->FindPlaybackTrackPort(*track);
|
||||
NS_ASSERTION(endedPort, "Playback track should have a TrackPort");
|
||||
if (endedPort && IsTrackIDExplicit(endedPort->GetSourceTrackId())) {
|
||||
// If a track connected to a locked-track input port ends, we destroy the
|
||||
// port to allow our playback stream to finish.
|
||||
// XXX (bug 1208316) This should not be necessary when MediaStreams don't
|
||||
// finish but instead become inactive.
|
||||
endedPort->DestroyInputPort();
|
||||
}
|
||||
}
|
||||
|
||||
void DoNotifyFinishedTrackCreation()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -285,22 +251,19 @@ public:
|
|||
NewRunnableMethod(mStream, &DOMMediaStream::NotifyTracksCreated));
|
||||
}
|
||||
|
||||
// The methods below are called on the MediaStreamGraph thread.
|
||||
|
||||
void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
|
||||
StreamTime aTrackOffset, TrackEventCommand aTrackEvents,
|
||||
const MediaSegment& aQueuedMedia,
|
||||
MediaStream* aInputStream,
|
||||
TrackID aInputTrackID) override
|
||||
void DoNotifyFinished()
|
||||
{
|
||||
if (aTrackEvents & TrackEventCommand::TRACK_EVENT_ENDED) {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NewRunnableMethod<RefPtr<MediaStream>, TrackID>(
|
||||
this, &PlaybackStreamListener::DoNotifyTrackEnded, aInputStream, aInputTrackID);
|
||||
aGraph->DispatchToMainThreadAfterStreamStateUpdate(runnable.forget());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mStream) {
|
||||
return;
|
||||
}
|
||||
|
||||
mStream->NotifyFinished();
|
||||
}
|
||||
|
||||
// The methods below are called on the MediaStreamGraph thread.
|
||||
|
||||
void NotifyFinishedTrackCreation(MediaStreamGraph* aGraph) override
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
|
@ -313,6 +276,48 @@ private:
|
|||
DOMMediaStream* mStream;
|
||||
};
|
||||
|
||||
class DOMMediaStream::PlaybackTrackListener : public MediaStreamTrackConsumer
|
||||
{
|
||||
public:
|
||||
explicit PlaybackTrackListener(DOMMediaStream* aStream) :
|
||||
mStream(aStream) {}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PlaybackTrackListener,
|
||||
MediaStreamTrackConsumer)
|
||||
|
||||
void NotifyEnded(MediaStreamTrack* aTrack) override
|
||||
{
|
||||
if (!mStream) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aTrack) {
|
||||
MOZ_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mStream->HasTrack(*aTrack));
|
||||
mStream->NotifyTrackRemoved(aTrack);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~PlaybackTrackListener() {}
|
||||
|
||||
RefPtr<DOMMediaStream> mStream;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(DOMMediaStream::PlaybackTrackListener,
|
||||
MediaStreamTrackConsumer)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMMediaStream::PlaybackTrackListener,
|
||||
MediaStreamTrackConsumer)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DOMMediaStream::PlaybackTrackListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackConsumer)
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(DOMMediaStream::PlaybackTrackListener,
|
||||
MediaStreamTrackConsumer,
|
||||
mStream)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(DOMMediaStream)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMediaStream,
|
||||
|
@ -323,6 +328,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMMediaStream,
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTracks)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsumersToKeepAlive)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTrackSourceGetter)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPlaybackTrackListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVideoPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
@ -334,6 +340,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMMediaStream,
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTracks)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsumersToKeepAlive)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTrackSourceGetter)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlaybackTrackListener)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVideoPrincipal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
@ -366,6 +373,7 @@ DOMMediaStream::DOMMediaStream(nsPIDOMWindowInner* aWindow,
|
|||
: mLogicalStreamStartTime(0), mWindow(aWindow),
|
||||
mInputStream(nullptr), mOwnedStream(nullptr), mPlaybackStream(nullptr),
|
||||
mTracksPendingRemoval(0), mTrackSourceGetter(aTrackSourceGetter),
|
||||
mPlaybackTrackListener(MakeAndAddRef<PlaybackTrackListener>(this)),
|
||||
mTracksCreated(false), mNotifiedOfMediaStreamGraphShutdown(false),
|
||||
mActive(false)
|
||||
{
|
||||
|
@ -405,8 +413,12 @@ DOMMediaStream::Destroy()
|
|||
for (const RefPtr<TrackPort>& info : mTracks) {
|
||||
// We must remove ourselves from each track's principal change observer list
|
||||
// before we die. CC may have cleared info->mTrack so guard against it.
|
||||
if (info->GetTrack()) {
|
||||
info->GetTrack()->RemovePrincipalChangeObserver(this);
|
||||
MediaStreamTrack* track = info->GetTrack();
|
||||
if (track) {
|
||||
track->RemovePrincipalChangeObserver(this);
|
||||
if (!track->Ended()) {
|
||||
track->RemoveConsumer(mPlaybackTrackListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mPlaybackPort) {
|
||||
|
@ -1268,6 +1280,7 @@ DOMMediaStream::NotifyTrackAdded(const RefPtr<MediaStreamTrack>& aTrack)
|
|||
}
|
||||
|
||||
aTrack->AddPrincipalChangeObserver(this);
|
||||
aTrack->AddConsumer(mPlaybackTrackListener);
|
||||
|
||||
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
||||
mTrackListeners[i]->NotifyTrackAdded(aTrack);
|
||||
|
@ -1297,6 +1310,7 @@ DOMMediaStream::NotifyTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack)
|
|||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
aTrack->RemoveConsumer(mPlaybackTrackListener);
|
||||
aTrack->RemovePrincipalChangeObserver(this);
|
||||
|
||||
for (int32_t i = mTrackListeners.Length() - 1; i >= 0; --i) {
|
||||
|
|
|
@ -635,6 +635,9 @@ protected:
|
|||
class PlaybackStreamListener;
|
||||
friend class PlaybackStreamListener;
|
||||
|
||||
class PlaybackTrackListener;
|
||||
friend class PlaybackTrackListener;
|
||||
|
||||
/**
|
||||
* Block a track in our playback stream. Calls NotifyPlaybackTrackBlocked()
|
||||
* after the MediaStreamGraph has applied the block and the track is no longer
|
||||
|
@ -704,6 +707,9 @@ protected:
|
|||
// in this DOMMediaStream and notifications to mTrackListeners.
|
||||
RefPtr<PlaybackStreamListener> mPlaybackListener;
|
||||
|
||||
// Listener tracking when live MediaStreamTracks in mTracks end.
|
||||
RefPtr<PlaybackTrackListener> mPlaybackTrackListener;
|
||||
|
||||
nsTArray<nsAutoPtr<OnTracksAvailableCallback> > mRunOnTracksAvailable;
|
||||
|
||||
// Set to true after MediaStreamGraph has created tracks for mPlaybackStream.
|
||||
|
|
|
@ -53,6 +53,14 @@ MediaStreamTrackSource::ApplyConstraints(
|
|||
return p.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaStreamTrackConsumer)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaStreamTrackConsumer)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaStreamTrackConsumer)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_0(MediaStreamTrackConsumer)
|
||||
|
||||
/**
|
||||
* PrincipalHandleListener monitors changes in PrincipalHandle of the media flowing
|
||||
* through the MediaStreamGraph.
|
||||
|
@ -171,6 +179,7 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(MediaStreamTrack)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaStreamTrack,
|
||||
DOMEventTargetHelper)
|
||||
tmp->Destroy();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mConsumers)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwningStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginalTrack)
|
||||
|
@ -180,6 +189,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaStreamTrack,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConsumers)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwningStream)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOriginalTrack)
|
||||
|
@ -245,6 +255,8 @@ MediaStreamTrack::Stop()
|
|||
Unused << p;
|
||||
|
||||
mReadyState = MediaStreamTrackState::Ended;
|
||||
|
||||
NotifyEnded();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -357,6 +369,18 @@ MediaStreamTrack::NotifyPrincipalHandleChanged(const PrincipalHandle& aNewPrinci
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamTrack::NotifyEnded()
|
||||
{
|
||||
MOZ_ASSERT(mReadyState == MediaStreamTrackState::Ended);
|
||||
|
||||
for (int32_t i = mConsumers.Length() - 1; i >= 0; --i) {
|
||||
// Loop backwards by index in case the consumer removes itself in the
|
||||
// callback.
|
||||
mConsumers[i]->NotifyEnded(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MediaStreamTrack::AddPrincipalChangeObserver(
|
||||
PrincipalChangeObserver<MediaStreamTrack>* aObserver)
|
||||
|
@ -371,6 +395,19 @@ MediaStreamTrack::RemovePrincipalChangeObserver(
|
|||
return mPrincipalChangeObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamTrack::AddConsumer(MediaStreamTrackConsumer* aConsumer)
|
||||
{
|
||||
MOZ_ASSERT(!mConsumers.Contains(aConsumer));
|
||||
mConsumers.AppendElement(aConsumer);
|
||||
}
|
||||
|
||||
void
|
||||
MediaStreamTrack::RemoveConsumer(MediaStreamTrackConsumer* aConsumer)
|
||||
{
|
||||
mConsumers.RemoveElement(aConsumer);
|
||||
}
|
||||
|
||||
already_AddRefed<MediaStreamTrack>
|
||||
MediaStreamTrack::Clone()
|
||||
{
|
||||
|
@ -423,6 +460,8 @@ MediaStreamTrack::OverrideEnded()
|
|||
|
||||
mReadyState = MediaStreamTrackState::Ended;
|
||||
|
||||
NotifyEnded();
|
||||
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("ended"));
|
||||
}
|
||||
|
||||
|
|
|
@ -230,6 +230,27 @@ protected:
|
|||
const MediaSourceEnum mMediaSource;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class that consumers of a MediaStreamTrack can use to get notifications
|
||||
* about state changes in the track.
|
||||
*/
|
||||
class MediaStreamTrackConsumer : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(MediaStreamTrackConsumer)
|
||||
|
||||
/**
|
||||
* Called when the track's readyState transitions to "ended".
|
||||
* Unlike the "ended" event exposed to script this is called for any reason,
|
||||
* including MediaStreamTrack::Stop().
|
||||
*/
|
||||
virtual void NotifyEnded(MediaStreamTrack* aTrack) {};
|
||||
|
||||
protected:
|
||||
virtual ~MediaStreamTrackConsumer() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing a track in a DOMMediaStream.
|
||||
*/
|
||||
|
@ -320,6 +341,12 @@ public:
|
|||
*/
|
||||
void NotifyPrincipalHandleChanged(const PrincipalHandle& aPrincipalHandle);
|
||||
|
||||
/**
|
||||
* Called when this track's readyState transitions to "ended".
|
||||
* Notifies all MediaStreamTrackConsumers that this track ended.
|
||||
*/
|
||||
void NotifyEnded();
|
||||
|
||||
/**
|
||||
* Get this track's CORS mode.
|
||||
*/
|
||||
|
@ -363,6 +390,18 @@ public:
|
|||
*/
|
||||
bool RemovePrincipalChangeObserver(PrincipalChangeObserver<MediaStreamTrack>* aObserver);
|
||||
|
||||
/**
|
||||
* Add a MediaStreamTrackConsumer to this track.
|
||||
*
|
||||
* Adding the same consumer multiple times is prohibited.
|
||||
*/
|
||||
void AddConsumer(MediaStreamTrackConsumer* aConsumer);
|
||||
|
||||
/**
|
||||
* Remove an added MediaStreamTrackConsumer from this track.
|
||||
*/
|
||||
void RemoveConsumer(MediaStreamTrackConsumer* aConsumer);
|
||||
|
||||
/**
|
||||
* Adds a MediaStreamTrackListener to the MediaStreamGraph representation of
|
||||
* this track.
|
||||
|
@ -429,6 +468,8 @@ protected:
|
|||
|
||||
nsTArray<PrincipalChangeObserver<MediaStreamTrack>*> mPrincipalChangeObservers;
|
||||
|
||||
nsTArray<RefPtr<MediaStreamTrackConsumer>> mConsumers;
|
||||
|
||||
RefPtr<DOMMediaStream> mOwningStream;
|
||||
TrackID mTrackID;
|
||||
TrackID mInputTrackID;
|
||||
|
|
Загрузка…
Ссылка в новой задаче