diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp index c6eb3331b015..5e124360ccf5 100644 --- a/dom/media/VideoUtils.cpp +++ b/dom/media/VideoUtils.cpp @@ -369,4 +369,78 @@ CreateFlushableMediaDecodeTaskQueue() return queue.forget(); } +void +SimpleTimer::Cancel() { + if (mTimer) { +#ifdef DEBUG + nsCOMPtr target; + mTimer->GetTarget(getter_AddRefs(target)); + nsCOMPtr thread(do_QueryInterface(target)); + MOZ_ASSERT(NS_GetCurrentThread() == thread); +#endif + mTimer->Cancel(); + mTimer = nullptr; + } + mTask = nullptr; +} + +NS_IMETHODIMP +SimpleTimer::Notify(nsITimer *timer) { + nsRefPtr deathGrip(this); + if (mTask) { + mTask->Run(); + mTask = nullptr; + } + return NS_OK; +} + +nsresult +SimpleTimer::Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget) +{ + nsresult rv; + + // Get target thread first, so we don't have to cancel the timer if it fails. + nsCOMPtr target; + if (aTarget) { + target = aTarget; + } else { + rv = NS_GetMainThread(getter_AddRefs(target)); + if (NS_FAILED(rv)) { + return rv; + } + } + + nsCOMPtr timer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + return rv; + } + // Note: set target before InitWithCallback in case the timer fires before + // we change the event target. + rv = timer->SetTarget(aTarget); + if (NS_FAILED(rv)) { + timer->Cancel(); + return rv; + } + rv = timer->InitWithCallback(this, aTimeoutMs, nsITimer::TYPE_ONE_SHOT); + if (NS_FAILED(rv)) { + return rv; + } + + mTimer = timer.forget(); + mTask = aTask; + return NS_OK; +} + +NS_IMPL_ISUPPORTS(SimpleTimer, nsITimerCallback) + +already_AddRefed +SimpleTimer::Create(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget) +{ + nsRefPtr t(new SimpleTimer()); + if (NS_FAILED(t->Init(aTask, aTimeoutMs, aTarget))) { + return nullptr; + } + return t.forget(); +} + } // end namespace mozilla diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h index 1371f6b1328f..b94942e19e79 100644 --- a/dom/media/VideoUtils.h +++ b/dom/media/VideoUtils.h @@ -22,6 +22,8 @@ #include "prtime.h" #include "AudioSampleFormat.h" #include "TimeUnits.h" +#include "nsITimer.h" +#include "nsCOMPtr.h" using mozilla::CheckedInt64; using mozilla::CheckedUint64; @@ -301,6 +303,29 @@ nsRefPtr InvokeUntil(Work aWork, Condition aCondition) { return p.forget(); } +// Simple timer to run a runnable after a timeout. +class SimpleTimer : public nsITimerCallback +{ +public: + NS_DECL_ISUPPORTS + + // Create a new timer to run aTask after aTimeoutMs milliseconds + // on thread aTarget. If aTarget is null, task is run on the main thread. + static already_AddRefed Create(nsIRunnable* aTask, + uint32_t aTimeoutMs, + nsIThread* aTarget = nullptr); + void Cancel(); + + NS_IMETHOD Notify(nsITimer *timer) override; + +private: + virtual ~SimpleTimer() {} + nsresult Init(nsIRunnable* aTask, uint32_t aTimeoutMs, nsIThread* aTarget); + + nsRefPtr mTask; + nsCOMPtr mTimer; +}; + } // end namespace mozilla #endif