From 9b07ac1beaa414b36cadbdf760a14d7551a3c373 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Mon, 7 Sep 2015 11:58:11 +0800 Subject: [PATCH] Bug 1199121. Part 2 - handle the case where audio ends before video and switch to system clock for calculating playback position. r=kinetik. --- dom/media/mediasink/AudioSinkWrapper.cpp | 28 +++++++++++++++++++++--- dom/media/mediasink/AudioSinkWrapper.h | 6 +++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/dom/media/mediasink/AudioSinkWrapper.cpp b/dom/media/mediasink/AudioSinkWrapper.cpp index 9c728ce846a..a70bb411a82 100644 --- a/dom/media/mediasink/AudioSinkWrapper.cpp +++ b/dom/media/mediasink/AudioSinkWrapper.cpp @@ -83,8 +83,8 @@ AudioSinkWrapper::GetPosition(TimeStamp* aTimeStamp) const int64_t pos = -1; TimeStamp t = TimeStamp::Now(); - if (mAudioSink) { - // Rely on the audio sink to report playback position when we have one. + if (!mAudioEnded) { + // Rely on the audio sink to report playback position when it is not ended. pos = mAudioSink->GetPosition(); } else if (!mPlayStartTime.IsNull()) { // Calculate playback position using system clock if we are still playing. @@ -123,7 +123,7 @@ AudioSinkWrapper::SetPlaybackRate(double aPlaybackRate) { AssertOwnerThread(); mParams.playbackRate = aPlaybackRate; - if (mAudioSink) { + if (!mAudioEnded) { // Pass the playback rate to the audio sink. The underlying AudioStream // will handle playback rate changes and report correct audio position. mAudioSink->SetPlaybackRate(aPlaybackRate); @@ -183,10 +183,18 @@ AudioSinkWrapper::Start(int64_t aStartTime, const MediaInfo& aInfo) mPlayDuration = aStartTime; mPlayStartTime = TimeStamp::Now(); + // no audio is equivalent to audio ended before video starts. + mAudioEnded = !aInfo.HasAudio(); + if (aInfo.HasAudio()) { mAudioSink = mCreator->Create(); mEndPromise = mAudioSink->Init(); SetPlaybackParams(mParams); + + mAudioSinkPromise.Begin(mEndPromise->Then( + mOwnerThread.get(), __func__, this, + &AudioSinkWrapper::OnAudioEnded, + &AudioSinkWrapper::OnAudioEnded)); } } @@ -197,8 +205,10 @@ AudioSinkWrapper::Stop() MOZ_ASSERT(mIsStarted, "playback not started."); mIsStarted = false; + mAudioEnded = true; if (mAudioSink) { + mAudioSinkPromise.DisconnectIfExists(); mAudioSink->Shutdown(); mAudioSink = nullptr; mEndPromise = nullptr; @@ -212,6 +222,18 @@ AudioSinkWrapper::IsStarted() const return mIsStarted; } +void +AudioSinkWrapper::OnAudioEnded() +{ + AssertOwnerThread(); + mAudioSinkPromise.Complete(); + mPlayDuration = GetPosition(); + if (!mPlayStartTime.IsNull()) { + mPlayStartTime = TimeStamp::Now(); + } + mAudioEnded = true; +} + } // namespace media } // namespace mozilla diff --git a/dom/media/mediasink/AudioSinkWrapper.h b/dom/media/mediasink/AudioSinkWrapper.h index 75eb3964421..4049c898bdb 100644 --- a/dom/media/mediasink/AudioSinkWrapper.h +++ b/dom/media/mediasink/AudioSinkWrapper.h @@ -53,6 +53,7 @@ public: , mIsStarted(false) // Give an insane value to facilitate debug if used before playback starts. , mPlayDuration(INT64_MAX) + , mAudioEnded(true) {} const PlaybackParams& GetPlaybackParams() const override; @@ -83,6 +84,8 @@ private: int64_t GetVideoPosition(TimeStamp aNow) const; + void OnAudioEnded(); + const nsRefPtr mOwnerThread; UniquePtr mCreator; nsRefPtr mAudioSink; @@ -93,6 +96,9 @@ private: TimeStamp mPlayStartTime; int64_t mPlayDuration; + + bool mAudioEnded; + MozPromiseRequestHolder mAudioSinkPromise; }; } // namespace media