From d47c752c4b77dcffe7a40cb68f684cf4b7391ddc Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Thu, 19 Feb 2015 12:04:26 -0500 Subject: [PATCH] Bug 1116925: queue track adds for getUserMedia and cleanup r=roc --- dom/media/MediaManager.h | 7 ++++-- dom/media/MediaStreamGraph.cpp | 17 ++++++++++++-- dom/media/MediaStreamGraph.h | 22 ++++++++++++++----- dom/media/webrtc/MediaEngineDefault.cpp | 12 ++++------ .../webrtc/MediaEngineGonkVideoSource.cpp | 1 - .../webrtc/MediaEngineTabVideoSource.cpp | 1 - dom/media/webrtc/MediaEngineWebRTCAudio.cpp | 4 ++-- dom/media/webrtc/MediaEngineWebRTCVideo.cpp | 3 +-- 8 files changed, 44 insertions(+), 23 deletions(-) diff --git a/dom/media/MediaManager.h b/dom/media/MediaManager.h index 5802ba1a40d..61c8a87f2da 100644 --- a/dom/media/MediaManager.h +++ b/dom/media/MediaManager.h @@ -393,8 +393,6 @@ public: NS_ASSERTION(!NS_IsMainThread(), "Never call on main thread"); nsresult rv; - source->SetPullEnabled(true); - DOMMediaStream::TrackTypeHints expectedTracks = 0; if (mAudioSource) { rv = mAudioSource->Start(source, kAudioTrack); @@ -414,9 +412,14 @@ public: return; } } + // Start() queued the tracks to be added synchronously to avoid races + source->FinishAddTracks(); mOnTracksAvailableCallback->SetExpectedTracks(expectedTracks); + source->SetPullEnabled(true); + source->AdvanceKnownTracksTime(STREAM_TIME_MAX); + MM_LOG(("started all sources")); // Forward mOnTracksAvailableCallback to GetUserMediaNotificationEvent, // because mOnTracksAvailableCallback needs to be added to mStream diff --git a/dom/media/MediaStreamGraph.cpp b/dom/media/MediaStreamGraph.cpp index 4a50ea3185b..e03212d48a6 100644 --- a/dom/media/MediaStreamGraph.cpp +++ b/dom/media/MediaStreamGraph.cpp @@ -2275,10 +2275,12 @@ SourceMediaStream::SetPullEnabled(bool aEnabled) void SourceMediaStream::AddTrackInternal(TrackID aID, TrackRate aRate, StreamTime aStart, - MediaSegment* aSegment) + MediaSegment* aSegment, uint32_t aFlags) { MutexAutoLock lock(mMutex); - TrackData* data = mUpdateTracks.AppendElement(); + nsTArray *track_data = (aFlags & ADDTRACK_QUEUED) ? + &mPendingTracks : &mUpdateTracks; + TrackData* data = track_data->AppendElement(); data->mID = aID; data->mInputRate = aRate; data->mStart = aStart; @@ -2286,6 +2288,16 @@ SourceMediaStream::AddTrackInternal(TrackID aID, TrackRate aRate, StreamTime aSt data->mCommands = TRACK_CREATE; data->mData = aSegment; data->mHaveEnough = false; + if (!(aFlags & ADDTRACK_QUEUED) && GraphImpl()) { + GraphImpl()->EnsureNextIteration(); + } +} + +void +SourceMediaStream::FinishAddTracks() +{ + MutexAutoLock lock(mMutex); + mUpdateTracks.MoveElementsFrom(mPendingTracks); if (GraphImpl()) { GraphImpl()->EnsureNextIteration(); } @@ -2515,6 +2527,7 @@ SourceMediaStream::EndAllTrackAndFinish() SourceMediaStream::TrackData* data = &mUpdateTracks[i]; data->mCommands |= TRACK_END; } + mPendingTracks.Clear(); FinishWithLockHeld(); // we will call NotifyEvent() to let GetUserMedia know } diff --git a/dom/media/MediaStreamGraph.h b/dom/media/MediaStreamGraph.h index 7947342b52f..09f38808a08 100644 --- a/dom/media/MediaStreamGraph.h +++ b/dom/media/MediaStreamGraph.h @@ -720,26 +720,36 @@ public: void AddDirectListener(MediaStreamDirectListener* aListener); void RemoveDirectListener(MediaStreamDirectListener* aListener); + enum { + ADDTRACK_QUEUED = 0x01 // Queue track add until FinishAddTracks() + }; /** * Add a new track to the stream starting at the given base time (which * must be greater than or equal to the last time passed to * AdvanceKnownTracksTime). Takes ownership of aSegment. aSegment should * contain data starting after aStart. */ - void AddTrack(TrackID aID, StreamTime aStart, MediaSegment* aSegment) + void AddTrack(TrackID aID, StreamTime aStart, MediaSegment* aSegment, + uint32_t aFlags = 0) { - AddTrackInternal(aID, GraphRate(), aStart, aSegment); + AddTrackInternal(aID, GraphRate(), aStart, aSegment, aFlags); } /** * Like AddTrack, but resamples audio from aRate to the graph rate. */ void AddAudioTrack(TrackID aID, TrackRate aRate, StreamTime aStart, - AudioSegment* aSegment) + AudioSegment* aSegment, uint32_t aFlags = 0) { - AddTrackInternal(aID, aRate, aStart, aSegment); + AddTrackInternal(aID, aRate, aStart, aSegment, aFlags); } + /** + * Call after a series of AddTrack or AddAudioTrack calls to implement + * any pending track adds. + */ + void FinishAddTracks(); + /** * Append media data to a track. Ownership of aSegment remains with the caller, * but aSegment is emptied. @@ -874,7 +884,8 @@ protected: void ResampleAudioToGraphSampleRate(TrackData* aTrackData, MediaSegment* aSegment); void AddTrackInternal(TrackID aID, TrackRate aRate, - StreamTime aStart, MediaSegment* aSegment); + StreamTime aStart, MediaSegment* aSegment, + uint32_t aFlags); TrackData* FindDataForTrack(TrackID aID) { @@ -905,6 +916,7 @@ protected: // protected by mMutex StreamTime mUpdateKnownTracksTime; nsTArray mUpdateTracks; + nsTArray mPendingTracks; nsTArray > mDirectListeners; bool mPullEnabled; bool mUpdateFinished; diff --git a/dom/media/webrtc/MediaEngineDefault.cpp b/dom/media/webrtc/MediaEngineDefault.cpp index 6c3ab69ee3c..2339d1a4475 100644 --- a/dom/media/webrtc/MediaEngineDefault.cpp +++ b/dom/media/webrtc/MediaEngineDefault.cpp @@ -138,12 +138,11 @@ MediaEngineDefaultVideoSource::Start(SourceMediaStream* aStream, TrackID aID) return NS_ERROR_FAILURE; } - aStream->AddTrack(aID, 0, new VideoSegment()); - aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX); + aStream->AddTrack(aID, 0, new VideoSegment(), SourceMediaStream::ADDTRACK_QUEUED); if (mHasFakeTracks) { for (int i = 0; i < kFakeVideoTrackCount; ++i) { - aStream->AddTrack(kTrackCount + i, 0, new VideoSegment()); + aStream->AddTrack(kTrackCount + i, 0, new VideoSegment(), SourceMediaStream::ADDTRACK_QUEUED); } } @@ -389,18 +388,15 @@ MediaEngineDefaultAudioSource::Start(SourceMediaStream* aStream, TrackID aID) // AddTrack will take ownership of segment AudioSegment* segment = new AudioSegment(); - mSource->AddAudioTrack(aID, AUDIO_RATE, 0, segment); + mSource->AddAudioTrack(aID, AUDIO_RATE, 0, segment, SourceMediaStream::ADDTRACK_QUEUED); if (mHasFakeTracks) { for (int i = 0; i < kFakeAudioTrackCount; ++i) { mSource->AddAudioTrack(kTrackCount + kFakeVideoTrackCount+i, - AUDIO_RATE, 0, new AudioSegment()); + AUDIO_RATE, 0, new AudioSegment(), SourceMediaStream::ADDTRACK_QUEUED); } } - // We aren't going to add any more tracks - mSource->AdvanceKnownTracksTime(STREAM_TIME_MAX); - // Remember TrackID so we can finish later mTrackID = aID; diff --git a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp index bc1bdec2d36..46530168d00 100644 --- a/dom/media/webrtc/MediaEngineGonkVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineGonkVideoSource.cpp @@ -182,7 +182,6 @@ MediaEngineGonkVideoSource::Start(SourceMediaStream* aStream, TrackID aID) } aStream->AddTrack(aID, 0, new VideoSegment()); - aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX); ReentrantMonitorAutoEnter sync(mCallbackMonitor); diff --git a/dom/media/webrtc/MediaEngineTabVideoSource.cpp b/dom/media/webrtc/MediaEngineTabVideoSource.cpp index a9e5d9a2747..12cde002ea4 100644 --- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp +++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp @@ -174,7 +174,6 @@ MediaEngineTabVideoSource::Start(SourceMediaStream* aStream, TrackID aID) runnable = new StartRunnable(this); NS_DispatchToMainThread(runnable); aStream->AddTrack(aID, 0, new VideoSegment()); - aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX); return NS_OK; } diff --git a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp index 686af3495b1..90758ed5022 100644 --- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp +++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp @@ -328,8 +328,8 @@ MediaEngineWebRTCAudioSource::Start(SourceMediaStream* aStream, TrackID aID) } AudioSegment* segment = new AudioSegment(); - aStream->AddAudioTrack(aID, SAMPLE_FREQUENCY, 0, segment); - aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX); + aStream->AddAudioTrack(aID, SAMPLE_FREQUENCY, 0, segment, SourceMediaStream::ADDTRACK_QUEUED); + // XXX Make this based on the pref. aStream->RegisterForAudioMixing(); LOG(("Start audio for stream %p", aStream)); diff --git a/dom/media/webrtc/MediaEngineWebRTCVideo.cpp b/dom/media/webrtc/MediaEngineWebRTCVideo.cpp index 7067cfd3bf7..d46e360803f 100644 --- a/dom/media/webrtc/MediaEngineWebRTCVideo.cpp +++ b/dom/media/webrtc/MediaEngineWebRTCVideo.cpp @@ -408,8 +408,7 @@ MediaEngineWebRTCVideoSource::Start(SourceMediaStream* aStream, TrackID aID) mSources.AppendElement(aStream); } - aStream->AddTrack(aID, 0, new VideoSegment()); - aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX); + aStream->AddTrack(aID, 0, new VideoSegment(), SourceMediaStream::ADDTRACK_QUEUED); if (mState == kStarted) { return NS_OK;