Bug 1423465. P2 - run UpdatePlaybackRate() off the main thread.
MozReview-Commit-ID: Ktw4IxzHT2f
--- a/dom/media/ChannelMediaDecoder.cpp
+++ b/dom/media/ChannelMediaDecoder.cpp
@@ -269,17 +269,23 @@ ChannelMediaDecoder::NotifyDownloadEnded
MOZ_ASSERT(NS_IsMainThread());
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
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) {
- UpdatePlaybackRate(ComputePlaybackRate());
+ nsCOMPtr<nsIRunnable> r =
+ NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
+ rate = ComputePlaybackRate(),
+ res = RefPtr<BaseMediaResource>(mResource)
+ ]() { 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) {
// Download has been cancelled by user.
owner->LoadAborted();
@@ -333,28 +339,42 @@ ChannelMediaDecoder::OnPlaybackEvent(Med
void
ChannelMediaDecoder::DurationChanged()
{
MOZ_ASSERT(NS_IsMainThread());
AbstractThread::AutoEnter context(AbstractMainThread());
MediaDecoder::DurationChanged();
// Duration has changed so we should recompute playback rate
- UpdatePlaybackRate(ComputePlaybackRate());
+ nsCOMPtr<nsIRunnable> r =
+ NS_NewRunnableFunction("ChannelMediaDecoder::UpdatePlaybackRate", [
+ rate = ComputePlaybackRate(),
+ res = RefPtr<BaseMediaResource>(mResource)
+ ]() { 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();
+
auto rate = ComputePlaybackRate();
- UpdatePlaybackRate(rate);
+ 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));
}
ChannelMediaDecoder::PlaybackRateInfo
ChannelMediaDecoder::ComputePlaybackRate()
{
@@ -366,34 +386,34 @@ ChannelMediaDecoder::ComputePlaybackRate
return { uint32_t(length / mDuration), true };
}
bool reliable = false;
uint32_t rate = mPlaybackStatistics.GetRate(&reliable);
return { rate, reliable };
}
-void
-ChannelMediaDecoder::UpdatePlaybackRate(const PlaybackRateInfo& aInfo)
+/* static */ void
+ChannelMediaDecoder::UpdatePlaybackRate(const PlaybackRateInfo& aInfo,
+ BaseMediaResource* aResource)
{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(mResource);
+ MOZ_ASSERT(!NS_IsMainThread());
uint32_t rate = aInfo.mRate;
if (aInfo.mReliable) {
// Avoid passing a zero rate
rate = std::max(rate, 1u);
} else {
// Set a minimum rate of 10,000 bytes per second ... sometimes we just
// don't have good data
rate = std::max(rate, 10000u);
}
- mResource->SetPlaybackRate(rate);
+ aResource->SetPlaybackRate(rate);
}
MediaStatistics
ChannelMediaDecoder::GetStatistics(const PlaybackRateInfo& aInfo)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mResource);
--- a/dom/media/ChannelMediaDecoder.h
+++ b/dom/media/ChannelMediaDecoder.h
@@ -123,17 +123,18 @@ private:
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();
// Something has changed that could affect the computed playback rate,
// so recompute it.
- void UpdatePlaybackRate(const PlaybackRateInfo& aInfo);
+ 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);
bool ShouldThrottleDownload(const MediaStatistics& aStats);