Bug 1423465. P4 - run GetStatistics() off the main thread.
Note we cache the result of GetStatistics().CanPlayThrough() which is needed
by CanPlayThroughImpl().
MozReview-Commit-ID: QYNqk1pUN5
--- a/dom/media/ChannelMediaDecoder.cpp
+++ b/dom/media/ChannelMediaDecoder.cpp
@@ -293,18 +293,17 @@ ChannelMediaDecoder::NotifyDownloadEnded
NetworkError(MediaResult(aStatus, "Download aborted"));
}
}
bool
ChannelMediaDecoder::CanPlayThroughImpl()
{
MOZ_ASSERT(NS_IsMainThread());
- NS_ENSURE_TRUE(GetStateMachine(), false);
- return GetStatistics(ComputePlaybackRate()).CanPlayThrough();
+ return mCanPlayThrough;
}
bool
ChannelMediaDecoder::IsLiveStream()
{
MOZ_ASSERT(NS_IsMainThread());
return mResource->IsLiveStream();
}
@@ -356,28 +355,40 @@ ChannelMediaDecoder::DurationChanged()
void
ChannelMediaDecoder::DownloadProgressed()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
AbstractThread::AutoEnter context(AbstractMainThread());
GetOwner()->DownloadProgressed();
- auto rate = ComputePlaybackRate();
- nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
- "ChannelMediaDecoder::UpdatePlaybackRate",
- [ rate, res = RefPtr<BaseMediaResource>(mResource) ]() {
- UpdatePlaybackRate(rate, res);
- });
- nsresult rv = GetStateMachine()->OwnerThread()->Dispatch(r.forget());
- MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
-
- MediaStatistics stats = GetStatistics(rate);
- GetStateMachine()->DispatchCanPlayThrough(stats.CanPlayThrough());
- mResource->ThrottleReadahead(ShouldThrottleDownload(stats));
+ using StatsPromise = MozPromise<MediaStatistics, bool, true>;
+ InvokeAsync(GetStateMachine()->OwnerThread(),
+ __func__,
+ [
+ rate = ComputePlaybackRate(),
+ res = RefPtr<BaseMediaResource>(mResource),
+ pos = mPlaybackPosition
+ ]() {
+ UpdatePlaybackRate(rate, res);
+ MediaStatistics stats = GetStatistics(rate, res, pos);
+ return StatsPromise::CreateAndResolve(stats, __func__);
+ })
+ ->Then(
+ mAbstractMainThread,
+ __func__,
+ [ =, self = RefPtr<ChannelMediaDecoder>(this) ](MediaStatistics aStats) {
+ if (IsShutdown()) {
+ return;
+ }
+ mCanPlayThrough = aStats.CanPlayThrough();
+ GetStateMachine()->DispatchCanPlayThrough(mCanPlayThrough);
+ mResource->ThrottleReadahead(ShouldThrottleDownload(aStats));
+ },
+ []() { MOZ_ASSERT_UNREACHABLE("Promise not resolved"); });
}
ChannelMediaDecoder::PlaybackRateInfo
ChannelMediaDecoder::ComputePlaybackRate()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mResource);
@@ -406,30 +417,30 @@ ChannelMediaDecoder::UpdatePlaybackRate(
// Set a minimum rate of 10,000 bytes per second ... sometimes we just
// don't have good data
rate = std::max(rate, 10000u);
}
aResource->SetPlaybackRate(rate);
}
-MediaStatistics
-ChannelMediaDecoder::GetStatistics(const PlaybackRateInfo& aInfo)
+/* static */ MediaStatistics
+ChannelMediaDecoder::GetStatistics(const PlaybackRateInfo& aInfo,
+ BaseMediaResource* aRes,
+ int64_t aPlaybackPosition)
{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mResource);
+ MOZ_ASSERT(!NS_IsMainThread());
MediaStatistics result;
- result.mDownloadRate =
- mResource->GetDownloadRate(&result.mDownloadRateReliable);
- result.mDownloadPosition = mResource->GetCachedDataEnd(mPlaybackPosition);
- result.mTotalBytes = mResource->GetLength();
+ result.mDownloadRate = aRes->GetDownloadRate(&result.mDownloadRateReliable);
+ result.mDownloadPosition = aRes->GetCachedDataEnd(aPlaybackPosition);
+ result.mTotalBytes = aRes->GetLength();
result.mPlaybackRate = aInfo.mRate;
result.mPlaybackRateReliable = aInfo.mReliable;
- result.mPlaybackPosition = mPlaybackPosition;
+ result.mPlaybackPosition = aPlaybackPosition;
return result;
}
bool
ChannelMediaDecoder::ShouldThrottleDownload(const MediaStatistics& aStats)
{
// We throttle the download if either the throttle override pref is set
// (so that we can always throttle in Firefox on mobile) or if the download
--- a/dom/media/ChannelMediaDecoder.h
+++ b/dom/media/ChannelMediaDecoder.h
@@ -130,17 +130,19 @@ private:
// so recompute it.
static void UpdatePlaybackRate(const PlaybackRateInfo& aInfo,
BaseMediaResource* aResource);
// Return statistics. This is used for progress events and other things.
// This can be called from any thread. It's only a snapshot of the
// current state, since other threads might be changing the state
// at any time.
- MediaStatistics GetStatistics(const PlaybackRateInfo& aInfo);
+ static MediaStatistics GetStatistics(const PlaybackRateInfo& aInfo,
+ BaseMediaResource* aRes,
+ int64_t aPlaybackPosition);
bool ShouldThrottleDownload(const MediaStatistics& aStats);
// Data needed to estimate playback data rate. The timeline used for
// this estimate is "decode time" (where the "current time" is the
// time of the last decoded video frame).
MediaChannelStatistics mPlaybackStatistics;
@@ -148,13 +150,15 @@ private:
// while seeking.
bool mPinnedForSeek = false;
// Current playback position in the stream. This is (approximately)
// where we're up to playing back the stream. This is not adjusted
// during decoder seek operations, but it's updated at the end when we
// start playing back again.
int64_t mPlaybackPosition = 0;
+
+ bool mCanPlayThrough = false;
};
} // namespace mozilla
#endif // ChannelMediaDecoder_h_