author | Andreas Pehrson <apehrson@mozilla.com> |
Tue, 10 Dec 2019 17:22:18 +0000 | |
changeset 506297 | b7ef124e4519ff8433b01056a4db60601ddd7377 |
parent 506296 | e183cbb4983cfb3aecf97ab18fad916b91f89e7e |
child 506298 | 0ccc77928faaedb342b869322ace35254fc34e95 |
push id | 36902 |
push user | aciure@mozilla.com |
push date | Wed, 11 Dec 2019 03:34:51 +0000 |
treeherder | mozilla-central@7635669b8d72 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | padenot |
bugs | 1600063 |
milestone | 73.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/media/MediaTrackGraph.cpp +++ b/dom/media/MediaTrackGraph.cpp @@ -2559,16 +2559,28 @@ TrackTime SourceMediaTrack::AppendData(M NotifyDirectConsumers(aRawSegment ? aRawSegment : aSegment); appended = aSegment->GetDuration(); mUpdateTrack->mData->AppendFrom(aSegment); // note: aSegment is now dead graph->EnsureNextIteration(); return appended; } +TrackTime SourceMediaTrack::ClearFutureData() { + MutexAutoLock lock(mMutex); + auto graph = GraphImpl(); + if (!mUpdateTrack || !graph) { + return 0; + } + + TrackTime duration = mUpdateTrack->mData->GetDuration(); + mUpdateTrack->mData->Clear(); + return duration; +} + void SourceMediaTrack::NotifyDirectConsumers(MediaSegment* aSegment) { mMutex.AssertCurrentThreadOwns(); for (const auto& l : mDirectTrackListeners) { TrackTime offset = 0; // FIX! need a separate TrackTime.... or the end of // the internal buffer l->NotifyRealtimeTrackDataAndApplyTrackDisabling(Graph(), offset, *aSegment);
--- a/dom/media/MediaTrackGraph.h +++ b/dom/media/MediaTrackGraph.h @@ -648,18 +648,25 @@ class SourceMediaTrack : public MediaTra void SetAppendDataSourceRate(TrackRate aRate); /** * Append media data to this track. Ownership of aSegment remains with the * caller, but aSegment is emptied. Returns 0 if the data was not appended * because the stream has ended. Returns the duration of the appended data in * the graph's track rate otherwise. */ - virtual TrackTime AppendData(MediaSegment* aSegment, - MediaSegment* aRawSegment = nullptr); + TrackTime AppendData(MediaSegment* aSegment, + MediaSegment* aRawSegment = nullptr); + + /** + * Clear any data appended with AppendData() that hasn't entered the graph + * yet. Returns the duration of the cleared data in the graph's track rate. + */ + TrackTime ClearFutureData(); + /** * Indicate that this track has ended. Do not do any more API calls affecting * this track. */ void End(); // Overriding allows us to hold the mMutex lock while changing the track // enable status
--- a/dom/media/mediasink/DecodedStream.cpp +++ b/dom/media/mediasink/DecodedStream.cpp @@ -489,16 +489,17 @@ nsresult DecodedStream::Start(const Time } void DecodedStream::Stop() { AssertOwnerThread(); MOZ_ASSERT(mStartTime.isSome(), "playback not started."); DisconnectListener(); ResetVideo(mPrincipalHandle); + ResetAudio(); mStartTime.reset(); mAudioEndedPromise = nullptr; mVideoEndedPromise = nullptr; // Clear mData immediately when this playback session ends so we won't // send data to the wrong track in SendData() in next playback session. DestroyData(std::move(mData)); } @@ -674,27 +675,56 @@ static bool ZeroDurationAtLastChunk(Vide // Get the last video frame's start time in VideoSegment aInput. // If the start time is equal to the duration of aInput, means the last video // frame's duration is zero. TrackTime lastVideoStratTime; aInput.GetLastFrame(&lastVideoStratTime); return lastVideoStratTime == aInput.GetDuration(); } +void DecodedStream::ResetAudio() { + AssertOwnerThread(); + + if (!mData) { + return; + } + + if (!mInfo.HasAudio()) { + return; + } + + TrackTime cleared = mData->mAudioTrack->ClearFutureData(); + mData->mAudioTrackWritten -= cleared; + if (const RefPtr<AudioData>& v = mAudioQueue.PeekFront()) { + mData->mNextAudioTime = v->mTime; + } + if (mData->mHaveSentFinishAudio && cleared > 0) { + mData->mHaveSentFinishAudio = false; + mData->mListener->EndTrackAt(mData->mAudioTrack, TRACK_TIME_MAX); + } +} + void DecodedStream::ResetVideo(const PrincipalHandle& aPrincipalHandle) { AssertOwnerThread(); if (!mData) { return; } if (!mInfo.HasVideo()) { return; } + TrackTime cleared = mData->mVideoTrack->ClearFutureData(); + mData->mVideoTrackWritten -= cleared; + if (mData->mHaveSentFinishVideo && cleared > 0) { + mData->mHaveSentFinishVideo = false; + mData->mListener->EndTrackAt(mData->mVideoTrack, TRACK_TIME_MAX); + } + VideoSegment resetter; TimeStamp currentTime; TimeUnit currentPosition = GetPosition(¤tTime); // Giving direct consumers a frame (really *any* frame, so in this case: // nullptr) at an earlier time than the previous, will signal to that consumer // to discard any frames ahead in time of the new frame. To be honest, this is // an ugly hack because the direct listeners of the MediaTrackGraph do not @@ -887,28 +917,29 @@ void DecodedStream::NotifyOutput(int64_t return; } MOZ_ASSERT(mLastOutputTime < time); mLastOutputTime = time; auto currentTime = GetPosition(); // Remove audio samples that have been played by MTG from the queue. RefPtr<AudioData> a = mAudioQueue.PeekFront(); - for (; a && a->mTime < currentTime;) { + for (; a && a->GetEndTime() < currentTime;) { RefPtr<AudioData> releaseMe = mAudioQueue.PopFront(); a = mAudioQueue.PeekFront(); } } void DecodedStream::PlayingChanged() { AssertOwnerThread(); if (!mPlaying) { // On seek or pause we discard future frames. ResetVideo(mPrincipalHandle); + ResetAudio(); } } void DecodedStream::ConnectListener() { AssertOwnerThread(); mAudioPushListener = mAudioQueue.PushEvent().Connect( mOwnerThread, this, &DecodedStream::SendData);
--- a/dom/media/mediasink/DecodedStream.h +++ b/dom/media/mediasink/DecodedStream.h @@ -65,16 +65,17 @@ class DecodedStream : public MediaSink { protected: virtual ~DecodedStream(); private: void DestroyData(UniquePtr<DecodedStreamData>&& aData); void SendAudio(double aVolume, const PrincipalHandle& aPrincipalHandle); void SendVideo(const PrincipalHandle& aPrincipalHandle); + void ResetAudio(); void ResetVideo(const PrincipalHandle& aPrincipalHandle); void SendData(); void NotifyOutput(int64_t aTime); void AssertOwnerThread() const { MOZ_ASSERT(mOwnerThread->IsCurrentThreadIn()); }