Bug 1283724 - throttle notifications from stochastic network activity to save computation of buffer ranges.
MozReview-Commit-ID: BRBv2Flqu3u
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -140,23 +140,26 @@ NS_IMPL_ISUPPORTS(MediaMemoryTracker, ns
NS_IMPL_ISUPPORTS0(MediaDecoder)
void
MediaDecoder::ResourceCallback::Connect(MediaDecoder* aDecoder)
{
MOZ_ASSERT(NS_IsMainThread());
mDecoder = aDecoder;
+ mTimer = do_CreateInstance("@mozilla.org/timer;1");
}
void
MediaDecoder::ResourceCallback::Disconnect()
{
MOZ_ASSERT(NS_IsMainThread());
mDecoder = nullptr;
+ mTimer->Cancel();
+ mTimer = nullptr;
}
MediaDecoderOwner*
MediaDecoder::ResourceCallback::GetMediaOwner() const
{
MOZ_ASSERT(NS_IsMainThread());
return mDecoder ? mDecoder->GetOwner() : nullptr;
}
@@ -211,23 +214,40 @@ MediaDecoder::ResourceCallback::NotifyDe
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
if (self->mDecoder) {
self->mDecoder->DecodeError();
}
});
AbstractThread::MainThread()->Dispatch(r.forget());
}
+/* static */ void
+MediaDecoder::ResourceCallback::TimerCallback(nsITimer* aTimer, void* aClosure)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ ResourceCallback* thiz = static_cast<ResourceCallback*>(aClosure);
+ MOZ_ASSERT(thiz->mDecoder);
+ thiz->mDecoder->NotifyDataArrived();
+ thiz->mTimerArmed = false;
+}
+
void
MediaDecoder::ResourceCallback::NotifyDataArrived()
{
MOZ_ASSERT(NS_IsMainThread());
- if (mDecoder) {
- mDecoder->NotifyDataArrived();
+ if (!mDecoder || mTimerArmed) {
+ return;
}
+ // In situations where these notifications come from stochastic network
+ // activity, we can save significant computation by throttling the
+ // calls to MediaDecoder::NotifyDataArrived() which will update the buffer
+ // ranges of the reader.
+ mTimerArmed = true;
+ mTimer->InitWithFuncCallback(
+ TimerCallback, this, sDelay, nsITimer::TYPE_ONE_SHOT);
}
void
MediaDecoder::ResourceCallback::NotifyBytesDownloaded()
{
MOZ_ASSERT(NS_IsMainThread());
if (mDecoder) {
mDecoder->NotifyBytesDownloaded();
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -65,16 +65,20 @@ public:
: mAtEnd(aAtEnd), mEventVisibility(aEventVisibility) {}
bool mAtEnd;
MediaDecoderEventVisibility mEventVisibility;
};
// Used to register with MediaResource to receive notifications which will
// be forwarded to MediaDecoder.
class ResourceCallback : public MediaResourceCallback {
+ // Throttle calls to MediaDecoder::NotifyDataArrived()
+ // to be at most once per 500ms.
+ static const uint32_t sDelay = 500;
+
public:
// Start to receive notifications from ResourceCallback.
void Connect(MediaDecoder* aDecoder);
// Called upon shutdown to stop receiving notifications.
void Disconnect();
private:
/* MediaResourceCallback functions */
@@ -87,18 +91,22 @@ public:
void NotifyDecodeError() override;
void NotifyDataArrived() override;
void NotifyBytesDownloaded() override;
void NotifyDataEnded(nsresult aStatus) override;
void NotifyPrincipalChanged() override;
void NotifySuspendedStatusChanged() override;
void NotifyBytesConsumed(int64_t aBytes, int64_t aOffset) override;
+ static void TimerCallback(nsITimer* aTimer, void* aClosure);
+
// The decoder to send notifications. Main-thread only.
MediaDecoder* mDecoder = nullptr;
+ nsCOMPtr<nsITimer> mTimer;
+ bool mTimerArmed = false;
};
typedef MozPromise<SeekResolveValue, bool /* aIgnored */, /* IsExclusive = */ true> SeekPromise;
NS_DECL_THREADSAFE_ISUPPORTS
// Enumeration for the valid play states (see mPlayState)
enum PlayState {