Bug 1230265 - Add codec agnostic benchmark ; r?kentuckyfriedtakahe draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 04 Mar 2016 01:46:10 +1100
changeset 337578 ccbf8bd399dc58837a8400046376ff03b2912fae
parent 337577 82d4ac602e70dae67aa6b92141d3c339bac6a101
child 338091 afab86bc6f54c0d4c494b5de9459c477cd5f4a0a
push id12403
push userbmo:jyavenard@mozilla.com
push dateTue, 08 Mar 2016 02:33:43 +0000
reviewerskentuckyfriedtakahe
bugs1230265
milestone47.0a1
Bug 1230265 - Add codec agnostic benchmark ; r?kentuckyfriedtakahe The Benchmark class is now taking a MediaDataDemuxer argument. Options allow to decode any videos and measure the decoding speed. MozReview-Commit-ID: C017I1cGqPL
dom/media/Benchmark.cpp
dom/media/Benchmark.h
dom/media/QueueObject.h
dom/media/mediasource/MediaSource.cpp
--- a/dom/media/Benchmark.cpp
+++ b/dom/media/Benchmark.cpp
@@ -7,246 +7,315 @@
 #include "Benchmark.h"
 #include "DecoderTraits.h"
 #include "PDMFactory.h"
 #include "WebMDemuxer.h"
 #include "BufferMediaResource.h"
 #include "WebMSample.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
+#include "MP4Demuxer.h"
+
+#include <iostream>
+#include <fstream>
+#include "MediaData.h"
 
 namespace mozilla {
 
-const char* Benchmark::sBenchmarkFpsPref = "media.benchmark.fps";
-bool Benchmark::sHasRunTest = false;
-
-const uint32_t BenchmarkDecoder::sStartupFrames = 1;
+const char* VP9Benchmark::sBenchmarkFpsPref = "media.benchmark.vp9.fps";
+bool VP9Benchmark::sHasRunTest = false;
 
 bool
-Benchmark::IsVP9DecodeFast()
+VP9Benchmark::IsVP9DecodeFast()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (true || !sHasRunTest) {
     sHasRunTest = true;
 
     if (true || !Preferences::HasUserValue(sBenchmarkFpsPref)) {
-      RefPtr<Benchmark> estimiser = new Benchmark();
+      RefPtr<WebMDemuxer> demuxer =
+        new WebMDemuxer(new BufferMediaResource(sWebMSample, sizeof(sWebMSample), nullptr,
+                                                NS_LITERAL_CSTRING("video/webm")));
+      RefPtr<Benchmark> estimiser =
+        new Benchmark(demuxer,
+                      {
+                        Preferences::GetInt("media.benchmark.frames", 300),
+                        1,
+                        8,
+                        TimeDuration::FromMilliseconds(
+                          Preferences::GetUint("media.benchmark.timeout", 1000))
+                      });
+      estimiser->Run()->Then(
+        AbstractThread::MainThread(), __func__,
+        [](uint32_t aDecodeFps) {
+          Preferences::SetUint(sBenchmarkFpsPref, aDecodeFps);
+          Telemetry::Accumulate(Telemetry::ID::VIDEO_VP9_BENCHMARK_FPS, aDecodeFps);
+
+          // H264 benchmark
+          // This is how it can be used, I will remove it from final commit
+          // of course.
+          std::ifstream infile;
+          infile.open("/Users/jyavenard/Downloads/g5dv.mp4", std::ios::binary);
+          infile.seekg(0, std::ios::end);
+          size_t fileSize = infile.tellg();
+          RefPtr<MediaByteBuffer> data = new MediaByteBuffer;
+          data->SetLength(fileSize);
+          infile.seekg(0, std::ios::beg);
+          infile.read((char*)data->Elements(), fileSize);
+
+          RefPtr<MP4Demuxer> mp4demuxer =
+            new MP4Demuxer(new BufferMediaResource(data->Elements(), data->Length(), nullptr,
+                                                   NS_LITERAL_CSTRING("video/mp4")));
+          RefPtr<Benchmark> mp4estimiser = new Benchmark(mp4demuxer);
+          mp4estimiser->Run()->Then(
+            AbstractThread::MainThread(), __func__,
+            [](uint32_t aDecodeFps) {
+              Preferences::SetUint("media.benchmark.h264.fps", aDecodeFps);
+            },
+            []() { });
+
+        },
+        []() { });
     }
   }
 
   if (!Preferences::HasUserValue(sBenchmarkFpsPref)) {
     return false;
   }
 
   uint32_t decodeFps = Preferences::GetUint(sBenchmarkFpsPref);
   uint32_t threshold =
     Preferences::GetUint("media.benchmark.vp9.threshold", 150);
 
   return decodeFps >= threshold;
 }
 
-Benchmark::Benchmark()
+Benchmark::Benchmark(MediaDataDemuxer* aDemuxer, const Parameters& aParameters)
   : QueueObject(AbstractThread::MainThread())
+  , mParameters(aParameters)
   , mKeepAliveUntilComplete(this)
-  , mPlaybackState(this)
+  , mPlaybackState(this, aDemuxer)
+{
+  MOZ_COUNT_CTOR(Benchmark);
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+Benchmark::~Benchmark()
 {
-  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_COUNT_DTOR(Benchmark);
+}
 
+RefPtr<Benchmark::BenchmarkPromise>
+Benchmark::Run()
+{
+  RefPtr<BenchmarkPromise> p = mPromise.Ensure(__func__);
   RefPtr<Benchmark> self = this;
   mPlaybackState.Dispatch(
     NS_NewRunnableFunction([self]() { self->mPlaybackState.DemuxSamples(); }));
+  return p;
 }
 
 void
-Benchmark::SaveResult(uint32_t aDecodeFps)
+Benchmark::ReturnResult(uint32_t aDecodeFps)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  Preferences::SetUint(sBenchmarkFpsPref, aDecodeFps);
-  Telemetry::Accumulate(Telemetry::ID::VIDEO_VP9_BENCHMARK_FPS, aDecodeFps);
-}
-
-void
-Benchmark::Drain(RefPtr<MediaDataDecoder> aDecoder)
-{
-  RefPtr<Benchmark> self = this;
-  mPlaybackState.Dispatch(NS_NewRunnableFunction([self, aDecoder]() {
-    self->mPlaybackState.Drain(aDecoder);
-  }));
+  mPromise.ResolveIfExists(aDecodeFps, __func__);
 }
 
 void
 Benchmark::Dispose()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  mPlaybackState.Shutdown();
   mKeepAliveUntilComplete = nullptr;
+  mPromise.RejectIfExists(false, __func__);
 }
 
-bool
-Benchmark::IsOnPlaybackThread()
-{
-  return mPlaybackState.OnThread();
-}
-
-BenchmarkPlayback::BenchmarkPlayback(Benchmark* aMainThreadState)
+BenchmarkPlayback::BenchmarkPlayback(Benchmark* aMainThreadState,
+                                     MediaDataDemuxer* aDemuxer)
   : QueueObject(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
   , mMainThreadState(aMainThreadState)
-  , mDecoderState(aMainThreadState, new FlushableTaskQueue(GetMediaThreadPool(
-                                      MediaThreadType::PLATFORM_DECODER)))
+  , mDecoderTaskQueue(new FlushableTaskQueue(GetMediaThreadPool(
+                        MediaThreadType::PLATFORM_DECODER)))
+  , mDemuxer(aDemuxer)
+  , mSampleIndex(0)
+  , mFrameCount(0)
+  , mFinished(false)
 {
+  MOZ_ASSERT(NS_IsMainThread());
+  PDMFactory::Init();
 }
 
 void
 BenchmarkPlayback::DemuxSamples()
 {
   MOZ_ASSERT(OnThread());
 
-  RefPtr<MediaDataDemuxer> demuxer = new WebMDemuxer(
-    new BufferMediaResource(sWebMSample, sizeof(sWebMSample), nullptr,
-                            NS_LITERAL_CSTRING("video/webm")));
-  RefPtr<Benchmark> ref = mMainThreadState;
-  demuxer->Init()->Then(
+  RefPtr<Benchmark> ref(mMainThreadState);
+  mDemuxer->Init()->Then(
     Thread(), __func__,
-    [this, ref, demuxer](nsresult aResult) {
+    [this, ref](nsresult aResult) {
       MOZ_ASSERT(OnThread());
-      RefPtr<MediaTrackDemuxer> track =
-        demuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
-
-      RefPtr<MediaTrackDemuxer::SamplesPromise> promise = track->GetSamples(8);
-
-      promise->Then(
-        ref->Thread(), __func__,
-        [this, ref, track](RefPtr<MediaTrackDemuxer::SamplesHolder> aHolder) {
-          mDecoderState.Init(Move(*track->GetInfo()), aHolder->mSamples);
-        },
-        [ref](DemuxerFailureReason aReason) { ref->Dispose(); });
+      mTrackDemuxer =
+        mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
+      if (!mTrackDemuxer) {
+        MainThreadShutdown();
+      }
+      DemuxNextSample();
     },
-    [ref](DemuxerFailureReason aReason) { ref->Dispose(); });
-}
-
-void
-BenchmarkPlayback::Drain(RefPtr<MediaDataDecoder> aDecoder)
-{
-  MOZ_ASSERT(OnThread());
-
-  aDecoder->Drain();
+    [this, ref](DemuxerFailureReason aReason) { MainThreadShutdown(); });
 }
 
 void
-BenchmarkPlayback::Shutdown()
+BenchmarkPlayback::DemuxNextSample()
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  mDecoderState.Thread()->AsTaskQueue()->BeginShutdown();
-  Thread()->AsTaskQueue()->BeginShutdown();
-}
+  MOZ_ASSERT(OnThread());
 
-BenchmarkDecoder::BenchmarkDecoder(Benchmark* aMainThreadState,
-                                   RefPtr<FlushableTaskQueue> aTaskQueue)
-  : QueueObject(aTaskQueue)
-  , mTaskQueue(aTaskQueue)
-  , mMainThreadState(aMainThreadState)
-  , mSampleIndex(0)
-  , mFrameCount(0)
-  , mFramesToMeasure(Preferences::GetUint("media.benchmark.frames", 300))
-  , mTimeout(TimeDuration::FromMilliseconds(
-      Preferences::GetUint("media.benchmark.timeout", 1000)))
-  , mFinished(false)
-{
-  MOZ_ASSERT(NS_IsMainThread());
+  RefPtr<Benchmark> ref(mMainThreadState);
+  RefPtr<MediaTrackDemuxer::SamplesPromise> promise = mTrackDemuxer->GetSamples();
+  promise->Then(
+    Thread(), __func__,
+    [this, ref](RefPtr<MediaTrackDemuxer::SamplesHolder> aHolder) {
+      mSamples.AppendElements(Move(aHolder->mSamples));
+      if (ref->mParameters.mStopAtFrame > 0 &&
+          mSamples.Length() == (size_t)ref->mParameters.mStopAtFrame) {
+        InitDecoder(Move(*mTrackDemuxer->GetInfo()));
+      } else {
+        Dispatch(NS_NewRunnableFunction([this, ref]() { DemuxNextSample(); }));
+      }
+    },
+    [this, ref](DemuxerFailureReason aReason) {
+      switch (aReason) {
+        case DemuxerFailureReason::END_OF_STREAM:
+          InitDecoder(Move(*mTrackDemuxer->GetInfo()));
+          break;
+        default:
+          MainThreadShutdown();
+      }
+    });
 }
 
 void
-BenchmarkDecoder::Init(TrackInfo&& aInfo,
-                       nsTArray<RefPtr<MediaRawData> >& aSamples)
+BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo)
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  mSamples = aSamples;
+  MOZ_ASSERT(OnThread());
 
   RefPtr<PDMFactory> platform = new PDMFactory();
-  platform->Init();
-
-  mDecoder = platform->CreateDecoder(aInfo, mTaskQueue, this);
-  RefPtr<Benchmark> ref = mMainThreadState;
+  mDecoder = platform->CreateDecoder(aInfo, mDecoderTaskQueue, this);
+  if (!mDecoder) {
+    MainThreadShutdown();
+    return;
+  }
+  RefPtr<Benchmark> ref(mMainThreadState);
   mDecoder->Init()->Then(
     ref->Thread(), __func__,
-    [this, ref, aSamples](TrackInfo::TrackType aTrackType) {
+    [this, ref](TrackInfo::TrackType aTrackType) {
       Dispatch(NS_NewRunnableFunction([this, ref]() { InputExhausted(); }));
     },
     [this, ref](MediaDataDecoder::DecoderFailureReason aReason) {
-      ref->Dispose();
+      MainThreadShutdown();
     });
 }
 
 void
-BenchmarkDecoder::MainThreadShutdown()
-{
-  MOZ_ASSERT(OnThread());
-
-  RefPtr<Benchmark> ref = mMainThreadState;
-  ref->Dispatch(NS_NewRunnableFunction([ref]() { ref->Dispose(); }));
-}
-
-void
-BenchmarkDecoder::Output(MediaData* aData)
+BenchmarkPlayback::MainThreadShutdown()
 {
   MOZ_ASSERT(OnThread());
 
-  if (mFinished) {
-    return;
+  if (mDecoder) {
+    mDecoder->Flush();
+    mDecoder->Shutdown();
+    mDecoder = nullptr;
   }
-  mFrameCount++;
-  if (mFrameCount == sStartupFrames) {
-    mDecodeStartTime = TimeStamp::Now();
+
+  mDecoderTaskQueue->BeginShutdown();
+  mDecoderTaskQueue->AwaitShutdownAndIdle();
+  mDecoderTaskQueue = nullptr;
+
+  if (mTrackDemuxer) {
+    mTrackDemuxer->Reset();
+    mTrackDemuxer->BreakCycles();
+    mTrackDemuxer = nullptr;
   }
-  uint32_t frames = mFrameCount - sStartupFrames;
-  TimeDuration elapsedTime = TimeStamp::Now() - mDecodeStartTime;
-  if (frames == mFramesToMeasure || elapsedTime >= mTimeout) {
-    uint32_t decodeFps = frames / elapsedTime.ToSeconds();
-    mFinished = true;
+
+  RefPtr<Benchmark> ref(mMainThreadState);
+  Thread()->AsTaskQueue()->BeginShutdown()->Then(
+    ref->Thread(), __func__,
+    [ref]() {  ref->Dispose(); },
+    []() { MOZ_CRASH("not reached"); });
+}
 
-    RefPtr<Benchmark> ref = mMainThreadState;
-    RefPtr<MediaDataDecoder> decoder = mDecoder;
-    ref->Dispatch(NS_NewRunnableFunction([ref, decoder, decodeFps]() {
-      ref->Drain(decoder);
-      ref->SaveResult(decodeFps);
-    }));
-  }
+void
+BenchmarkPlayback::Output(MediaData* aData)
+{
+  RefPtr<Benchmark> ref(mMainThreadState);
+  Dispatch(NS_NewRunnableFunction([this, ref]() {
+    mFrameCount++;
+    if (mFrameCount == ref->mParameters.mStartupFrame) {
+      mDecodeStartTime = TimeStamp::Now();
+    }
+    int32_t frames = mFrameCount - ref->mParameters.mStartupFrame;
+    TimeDuration elapsedTime = TimeStamp::Now() - mDecodeStartTime;
+    if (!mFinished &&
+        (frames == ref->mParameters.mFramesToMeasure ||
+         elapsedTime >= ref->mParameters.mTimeout)) {
+      uint32_t decodeFps = frames / elapsedTime.ToSeconds();
+      mFinished = true;
+      MainThreadShutdown();
+      ref->Dispatch(NS_NewRunnableFunction([ref, decodeFps]() {
+        ref->ReturnResult(decodeFps);
+      }));
+    }
+  }));
 }
 
 void
-BenchmarkDecoder::Error()
+BenchmarkPlayback::Error()
 {
-  MOZ_ASSERT(OnThread());
-
-  MainThreadShutdown();
+  RefPtr<Benchmark> ref(mMainThreadState);
+  Dispatch(NS_NewRunnableFunction([this, ref]() {  MainThreadShutdown(); }));
 }
 
 void
-BenchmarkDecoder::InputExhausted()
+BenchmarkPlayback::InputExhausted()
 {
-  MOZ_ASSERT(OnThread());
-
-  mDecoder->Input(mSamples[mSampleIndex]);
-  mSampleIndex++;
-  if (mSampleIndex == mSamples.Length()) {
-    mSampleIndex = 0;
-  }
+  RefPtr<Benchmark> ref(mMainThreadState);
+  Dispatch(NS_NewRunnableFunction([this, ref]() {
+    MOZ_ASSERT(OnThread());
+    if (mFinished || mSampleIndex >= mSamples.Length()) {
+      return;
+    }
+    mDecoder->Input(mSamples[mSampleIndex]);
+    mSampleIndex++;
+    if (ref->mParameters.mStopAtFrame > 0 &&
+        mSampleIndex == (size_t)ref->mParameters.mStopAtFrame) {
+      mSampleIndex = 0;
+    } else if (mSampleIndex == mSamples.Length()) {
+      mDecoder->Drain();
+    }
+  }));
 }
 
 void
-BenchmarkDecoder::DrainComplete()
+BenchmarkPlayback::DrainComplete()
 {
-  MOZ_ASSERT(OnThread());
-
-  MainThreadShutdown();
+  RefPtr<Benchmark> ref(mMainThreadState);
+  Dispatch(NS_NewRunnableFunction([this, ref]() {
+    int32_t frames = mFrameCount - ref->mParameters.mStartupFrame;
+    TimeDuration elapsedTime = TimeStamp::Now() - mDecodeStartTime;
+    uint32_t decodeFps = frames / elapsedTime.ToSeconds();
+    mFinished = true;
+    MainThreadShutdown();
+    ref->Dispatch(NS_NewRunnableFunction([ref, decodeFps]() {
+      ref->ReturnResult(decodeFps);
+    }));
+  }));
 }
 
 bool
-BenchmarkDecoder::OnReaderTaskQueue()
+BenchmarkPlayback::OnReaderTaskQueue()
 {
-  return mMainThreadState->IsOnPlaybackThread();
+  return OnThread();
 }
+
 }
--- a/dom/media/Benchmark.h
+++ b/dom/media/Benchmark.h
@@ -2,83 +2,109 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_BENCHMARK_H
 #define MOZILLA_BENCHMARK_H
 
+#include "MediaDataDemuxer.h"
+#include "QueueObject.h"
+#include "PlatformDecoderModule.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/TaskQueue.h"
 #include "mozilla/TimeStamp.h"
-#include "QueueObject.h"
+#include "nsCOMPtr.h"
 
 namespace mozilla {
 
 class FlushableTaskQueue;
 class Benchmark;
-class BenchmarkPlayback;
 
-class BenchmarkDecoder : public QueueObject, private MediaDataDecoderCallback
+class BenchmarkPlayback : public QueueObject, private MediaDataDecoderCallback
 {
 public:
-  BenchmarkDecoder(Benchmark* aMainThreadState,
-                   RefPtr<FlushableTaskQueue> aTaskQueue);
-  void Init(TrackInfo&& aInfo, nsTArray<RefPtr<MediaRawData>>& aSamples);
+  explicit BenchmarkPlayback(Benchmark* aMainThreadState, MediaDataDemuxer* aDemuxer);
+  void DemuxSamples();
+  void DemuxNextSample();
+  void MainThreadShutdown();
+  void InitDecoder(TrackInfo&& aInfo);
 
-  void MainThreadShutdown();
-  MediaRawData* PopNextSample();
-
+  // MediaDataDecoderCallback
+  // Those methods are called on the MediaDataDecoder's task queue.
   void Output(MediaData* aData) override;
   void Error() override;
   void InputExhausted() override;
   void DrainComplete() override;
   bool OnReaderTaskQueue() override;
 
-  RefPtr<FlushableTaskQueue> mTaskQueue;
-  Benchmark* mMainThreadState;
+private:
+  Atomic<Benchmark*> mMainThreadState;
+
+  RefPtr<FlushableTaskQueue> mDecoderTaskQueue;
   RefPtr<MediaDataDecoder> mDecoder;
+
+  RefPtr<TaskQueue> mTaskQueue;
+  // Object only accessed on mTaskQueue
+  RefPtr<MediaDataDemuxer> mDemuxer;
+  RefPtr<MediaTrackDemuxer> mTrackDemuxer;
   nsTArray<RefPtr<MediaRawData>> mSamples;
   size_t mSampleIndex;
   TimeStamp mDecodeStartTime;
   uint32_t mFrameCount;
-  const uint32_t mFramesToMeasure;
-  const TimeDuration mTimeout;
-  static const uint32_t sStartupFrames;
   bool mFinished;
 };
 
-class BenchmarkPlayback : public QueueObject
-{
-public:
-  explicit BenchmarkPlayback(Benchmark* aMainThreadState);
-  void DemuxSamples();
-  void Drain(RefPtr<MediaDataDecoder> aDecoder);
-  void Shutdown();
-
-private:
-  Benchmark* mMainThreadState;
-  BenchmarkDecoder mDecoderState;
-};
-
 class Benchmark : public QueueObject
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Benchmark)
 
-  static bool IsVP9DecodeFast();
+  struct Parameters
+  {
+    Parameters()
+      : mFramesToMeasure(-1)
+      , mStartupFrame(1)
+      , mStopAtFrame(-1)
+      , mTimeout(TimeDuration::Forever()) {}
 
-  void SaveResult(uint32_t aDecodeFps);
-  void Drain(RefPtr<MediaDataDecoder> aDecoder);
+    Parameters(int32_t aFramesToMeasure,
+               uint32_t aStartupFrame,
+               int32_t aStopAtFrame,
+               const TimeDuration& aTimeout)
+      : mFramesToMeasure(aFramesToMeasure)
+      , mStartupFrame(aStartupFrame)
+      , mStopAtFrame(aStopAtFrame)
+      , mTimeout(aTimeout) {}
+
+    const int32_t mFramesToMeasure;
+    const uint32_t mStartupFrame;
+    const int32_t mStopAtFrame;
+    const TimeDuration mTimeout;
+  };
+
+  typedef MozPromise<uint32_t, bool, /* IsExclusive = */ true> BenchmarkPromise;
+
+  Benchmark(MediaDataDemuxer* aDemuxer, const Parameters& aParameters = Parameters());
+  RefPtr<BenchmarkPromise> Run();
+  void ReturnResult(uint32_t aDecodeFps);
   void Dispose();
-  bool IsOnPlaybackThread();
+
+  const Parameters mParameters;
 
 private:
-  Benchmark();
-  virtual ~Benchmark() {}
+  virtual ~Benchmark();
   RefPtr<Benchmark> mKeepAliveUntilComplete;
   BenchmarkPlayback mPlaybackState;
+  MozPromiseHolder<BenchmarkPromise> mPromise;
+};
+
+class VP9Benchmark
+{
+public:
+  static bool IsVP9DecodeFast();
   static const char* sBenchmarkFpsPref;
   static bool sHasRunTest;
 };
 }
 
 #endif
--- a/dom/media/QueueObject.h
+++ b/dom/media/QueueObject.h
@@ -3,16 +3,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_QUEUE_OBJECT_H
 #define MOZILLA_QUEUE_OBJECT_H
 
 #include "mozilla/RefPtr.h"
+#include "nsIRunnable.h"
+#include "nsThreadUtils.h"
 
 namespace mozilla {
 
 class AbstractThread;
 
 class QueueObject
 {
 public:
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -74,17 +74,17 @@ static const char* const gMediaSourceTyp
 // 2. If H264 hardware acceleration is not available.
 // 3. The CPU is considered to be fast enough
 static bool
 IsWebMForced()
 {
   bool mp4supported =
     DecoderTraits::IsMP4TypeAndEnabled(NS_LITERAL_CSTRING("video/mp4"));
   bool hwsupported = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
-  return !mp4supported || !hwsupported || Benchmark::IsVP9DecodeFast();
+  return !mp4supported || !hwsupported || VP9Benchmark::IsVP9DecodeFast();
 }
 
 static nsresult
 IsTypeSupported(const nsAString& aType)
 {
   if (aType.IsEmpty()) {
     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }