Bug 1423465. P5 - run ComputePlaybackRate() off the main thread.
MozReview-Commit-ID: DhaZUVcHhiy
--- a/dom/media/ChannelMediaDecoder.cpp
+++ b/dom/media/ChannelMediaDecoder.cpp
@@ -271,19 +271,23 @@ ChannelMediaDecoder::NotifyDownloadEnded
AbstractThread::AutoEnter context(AbstractMainThread());
LOG("NotifyDownloadEnded, status=%" PRIx32, static_cast<uint32_t>(aStatus));
MediaDecoderOwner* owner = GetOwner();
if (NS_SUCCEEDED(aStatus) || aStatus == NS_BASE_STREAM_CLOSED) {
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
- rate = ComputePlaybackRate(),
- res = RefPtr<BaseMediaResource>(mResource)
- ]() { UpdatePlaybackRate(rate, res); });
+ stats = mPlaybackStatistics,
+ res = RefPtr<BaseMediaResource>(mResource),
+ duration = mDuration
+ ]() {
+ auto rate = ComputePlaybackRate(stats, res, duration);
+ UpdatePlaybackRate(rate, res);
+ });
nsresult rv = GetStateMachine()->OwnerThread()->Dispatch(r.forget());
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
owner->DownloadSuspended();
// NotifySuspendedStatusChanged will tell the element that download
// has been suspended "by the cache", which is true since we never
// download anything. The element can then transition to HAVE_ENOUGH_DATA.
owner->NotifySuspendedByCache(true);
} else if (aStatus == NS_BINDING_ABORTED) {
@@ -340,39 +344,45 @@ void
ChannelMediaDecoder::DurationChanged()
{
MOZ_ASSERT(NS_IsMainThread());
AbstractThread::AutoEnter context(AbstractMainThread());
MediaDecoder::DurationChanged();
// Duration has changed so we should recompute playback rate
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
- rate = ComputePlaybackRate(),
- res = RefPtr<BaseMediaResource>(mResource)
- ]() { UpdatePlaybackRate(rate, res); });
+ stats = mPlaybackStatistics,
+ res = RefPtr<BaseMediaResource>(mResource),
+ duration = mDuration
+ ]() {
+ auto rate = ComputePlaybackRate(stats, res, duration);
+ UpdatePlaybackRate(rate, res);
+ });
nsresult rv = GetStateMachine()->OwnerThread()->Dispatch(r.forget());
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
}
void
ChannelMediaDecoder::DownloadProgressed()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
AbstractThread::AutoEnter context(AbstractMainThread());
GetOwner()->DownloadProgressed();
using StatsPromise = MozPromise<MediaStatistics, bool, true>;
InvokeAsync(GetStateMachine()->OwnerThread(),
__func__,
[
- rate = ComputePlaybackRate(),
+ playbackStats = mPlaybackStatistics,
res = RefPtr<BaseMediaResource>(mResource),
+ duration = mDuration,
pos = mPlaybackPosition
]() {
+ auto rate = ComputePlaybackRate(playbackStats, res, duration);
UpdatePlaybackRate(rate, res);
MediaStatistics stats = GetStatistics(rate, res, pos);
return StatsPromise::CreateAndResolve(stats, __func__);
})
->Then(
mAbstractMainThread,
__func__,
[ =, self = RefPtr<ChannelMediaDecoder>(this) ](MediaStatistics aStats) {
@@ -381,29 +391,30 @@ ChannelMediaDecoder::DownloadProgressed(
}
mCanPlayThrough = aStats.CanPlayThrough();
GetStateMachine()->DispatchCanPlayThrough(mCanPlayThrough);
mResource->ThrottleReadahead(ShouldThrottleDownload(aStats));
},
[]() { MOZ_ASSERT_UNREACHABLE("Promise not resolved"); });
}
-ChannelMediaDecoder::PlaybackRateInfo
-ChannelMediaDecoder::ComputePlaybackRate()
+/* static */ ChannelMediaDecoder::PlaybackRateInfo
+ChannelMediaDecoder::ComputePlaybackRate(const MediaChannelStatistics& aStats,
+ BaseMediaResource* aResource,
+ double aDuration)
{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mResource);
+ MOZ_ASSERT(!NS_IsMainThread());
- int64_t length = mResource->GetLength();
- if (mozilla::IsFinite<double>(mDuration) && mDuration > 0 && length >= 0) {
- return { uint32_t(length / mDuration), true };
+ int64_t length = aResource->GetLength();
+ if (mozilla::IsFinite<double>(aDuration) && aDuration > 0 && length >= 0) {
+ return { uint32_t(length / aDuration), true };
}
bool reliable = false;
- uint32_t rate = mPlaybackStatistics.GetRate(&reliable);
+ uint32_t rate = aStats.GetRate(&reliable);
return { rate, reliable };
}
/* static */ void
ChannelMediaDecoder::UpdatePlaybackRate(const PlaybackRateInfo& aInfo,
BaseMediaResource* aResource)
{
MOZ_ASSERT(!NS_IsMainThread());
--- a/dom/media/ChannelMediaDecoder.h
+++ b/dom/media/ChannelMediaDecoder.h
@@ -119,17 +119,20 @@ private:
bool IsLiveStream() override final;
struct PlaybackRateInfo
{
uint32_t mRate; // Estimate of the current playback rate (bytes/second).
bool mReliable; // True if mRate is a reliable estimate.
};
// The actual playback rate computation.
- PlaybackRateInfo ComputePlaybackRate();
+ static PlaybackRateInfo ComputePlaybackRate(
+ const MediaChannelStatistics& aStats,
+ BaseMediaResource* aResource,
+ double aDuration);
// Something has changed that could affect the computed playback rate,
// 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
--- a/dom/media/MediaChannelStatistics.h
+++ b/dom/media/MediaChannelStatistics.h
@@ -53,25 +53,27 @@ public:
void AddBytes(int64_t aBytes) {
if (!mIsStarted) {
// ignore this data, it may be related to seeking or some other
// operation we don't care about
return;
}
mAccumulatedBytes += aBytes;
}
- double GetRateAtLastStop(bool* aReliable) {
+ double GetRateAtLastStop(bool* aReliable) const
+ {
double seconds = mAccumulatedTime.ToSeconds();
*aReliable = (seconds >= 1.0) ||
(mAccumulatedBytes >= RELIABLE_DATA_THRESHOLD);
if (seconds <= 0.0)
return 0.0;
return static_cast<double>(mAccumulatedBytes)/seconds;
}
- double GetRate(bool* aReliable) {
+ double GetRate(bool* aReliable) const
+ {
TimeDuration time = mAccumulatedTime;
if (mIsStarted) {
time += TimeStamp::Now() - mLastStartTime;
}
double seconds = time.ToSeconds();
*aReliable = (seconds >= 3.0) ||
(mAccumulatedBytes >= RELIABLE_DATA_THRESHOLD);
if (seconds <= 0.0)