LCOV - code coverage report
Current view: top level - dom/media - Benchmark.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 189 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 68 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "Benchmark.h"
       8             : 
       9             : #include "BufferMediaResource.h"
      10             : #include "MediaData.h"
      11             : #include "MediaPrefs.h"
      12             : #include "PDMFactory.h"
      13             : #include "VideoUtils.h"
      14             : #include "WebMDemuxer.h"
      15             : #include "gfxPrefs.h"
      16             : #include "mozilla/AbstractThread.h"
      17             : #include "mozilla/Preferences.h"
      18             : #include "mozilla/SharedThreadPool.h"
      19             : #include "mozilla/TaskQueue.h"
      20             : #include "mozilla/Telemetry.h"
      21             : #include "mozilla/dom/ContentChild.h"
      22             : #include "mozilla/gfx/gfxVars.h"
      23             : 
      24             : #ifndef MOZ_WIDGET_ANDROID
      25             : #include "WebMSample.h"
      26             : #endif
      27             : 
      28             : using namespace mozilla::gfx;
      29             : 
      30             : namespace mozilla {
      31             : 
      32             : // Update this version number to force re-running the benchmark. Such as when
      33             : // an improvement to FFVP9 or LIBVPX is deemed worthwhile.
      34             : const uint32_t VP9Benchmark::sBenchmarkVersionID = 2;
      35             : 
      36             : const char* VP9Benchmark::sBenchmarkFpsPref = "media.benchmark.vp9.fps";
      37             : const char* VP9Benchmark::sBenchmarkFpsVersionCheck = "media.benchmark.vp9.versioncheck";
      38             : bool VP9Benchmark::sHasRunTest = false;
      39             : 
      40             : // static
      41             : bool
      42           0 : VP9Benchmark::IsVP9DecodeFast()
      43             : {
      44           0 :   MOZ_ASSERT(NS_IsMainThread());
      45             : 
      46             : #ifdef MOZ_WIDGET_ANDROID
      47             :   return false;
      48             : #else
      49           0 :   bool hasPref = Preferences::HasUserValue(sBenchmarkFpsPref);
      50           0 :   uint32_t hadRecentUpdate = Preferences::GetUint(sBenchmarkFpsVersionCheck, 0U);
      51             : 
      52           0 :   if (!sHasRunTest && (!hasPref || hadRecentUpdate != sBenchmarkVersionID)) {
      53           0 :     sHasRunTest = true;
      54             : 
      55             :     RefPtr<WebMDemuxer> demuxer = new WebMDemuxer(
      56           0 :       new BufferMediaResource(sWebMSample, sizeof(sWebMSample), nullptr));
      57             :     RefPtr<Benchmark> estimiser =
      58             :       new Benchmark(demuxer,
      59             :                     {
      60             :                       Preferences::GetInt("media.benchmark.frames", 300), // frames to measure
      61             :                       1, // start benchmarking after decoding this frame.
      62             :                       8, // loop after decoding that many frames.
      63           0 :                       TimeDuration::FromMilliseconds(
      64           0 :                         Preferences::GetUint("media.benchmark.timeout", 1000))
      65           0 :                     });
      66           0 :     estimiser->Run()->Then(
      67           0 :       SystemGroup::AbstractMainThreadFor(TaskCategory::Other), __func__,
      68           0 :       [](uint32_t aDecodeFps) {
      69           0 :         if (XRE_IsContentProcess()) {
      70           0 :           dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
      71           0 :           if (contentChild) {
      72           0 :             contentChild->SendNotifyBenchmarkResult(NS_LITERAL_STRING("VP9"),
      73           0 :                                                     aDecodeFps);
      74             :           }
      75             :         } else {
      76           0 :           Preferences::SetUint(sBenchmarkFpsPref, aDecodeFps);
      77           0 :           Preferences::SetUint(sBenchmarkFpsVersionCheck, sBenchmarkVersionID);
      78             :         }
      79           0 :         Telemetry::Accumulate(Telemetry::HistogramID::VIDEO_VP9_BENCHMARK_FPS, aDecodeFps);
      80           0 :       },
      81           0 :       []() { });
      82             :   }
      83             : 
      84           0 :   if (!hasPref) {
      85           0 :     return false;
      86             :   }
      87             : 
      88           0 :   uint32_t decodeFps = Preferences::GetUint(sBenchmarkFpsPref);
      89             :   uint32_t threshold =
      90           0 :     Preferences::GetUint("media.benchmark.vp9.threshold", 150);
      91             : 
      92           0 :   return decodeFps >= threshold;
      93             : #endif
      94             : }
      95             : 
      96           0 : Benchmark::Benchmark(MediaDataDemuxer* aDemuxer, const Parameters& aParameters)
      97             :   : QueueObject(AbstractThread::MainThread())
      98             :   , mParameters(aParameters)
      99             :   , mKeepAliveUntilComplete(this)
     100           0 :   , mPlaybackState(this, aDemuxer)
     101             : {
     102           0 :   MOZ_COUNT_CTOR(Benchmark);
     103           0 :   MOZ_ASSERT(Thread(), "Must be run in task queue");
     104           0 : }
     105             : 
     106           0 : Benchmark::~Benchmark()
     107             : {
     108           0 :   MOZ_COUNT_DTOR(Benchmark);
     109           0 : }
     110             : 
     111             : RefPtr<Benchmark::BenchmarkPromise>
     112           0 : Benchmark::Run()
     113             : {
     114           0 :   MOZ_ASSERT(OnThread());
     115             : 
     116           0 :   RefPtr<BenchmarkPromise> p = mPromise.Ensure(__func__);
     117           0 :   RefPtr<Benchmark> self = this;
     118           0 :   mPlaybackState.Dispatch(NS_NewRunnableFunction(
     119           0 :     "Benchmark::Run", [self]() { self->mPlaybackState.DemuxSamples(); }));
     120           0 :   return p;
     121             : }
     122             : 
     123             : void
     124           0 : Benchmark::ReturnResult(uint32_t aDecodeFps)
     125             : {
     126           0 :   MOZ_ASSERT(OnThread());
     127             : 
     128           0 :   mPromise.ResolveIfExists(aDecodeFps, __func__);
     129           0 : }
     130             : 
     131             : void
     132           0 : Benchmark::Dispose()
     133             : {
     134           0 :   MOZ_ASSERT(OnThread());
     135             : 
     136           0 :   mKeepAliveUntilComplete = nullptr;
     137           0 :   mPromise.RejectIfExists(false, __func__);
     138           0 : }
     139             : 
     140             : void
     141           0 : Benchmark::Init()
     142             : {
     143           0 :   MOZ_ASSERT(NS_IsMainThread());
     144           0 :   gfxVars::Initialize();
     145           0 :   gfxPrefs::GetSingleton();
     146           0 :   MediaPrefs::GetSingleton();
     147           0 : }
     148             : 
     149           0 : BenchmarkPlayback::BenchmarkPlayback(Benchmark* aMainThreadState,
     150           0 :                                      MediaDataDemuxer* aDemuxer)
     151             :   : QueueObject(new TaskQueue(
     152           0 :       GetMediaThreadPool(MediaThreadType::PLAYBACK),
     153           0 :       "BenchmarkPlayback::QueueObject"))
     154             :   , mMainThreadState(aMainThreadState)
     155             :   , mDecoderTaskQueue(new TaskQueue(
     156           0 :       GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER),
     157           0 :       "BenchmarkPlayback::mDecoderTaskQueue"))
     158             :   , mDemuxer(aDemuxer)
     159             :   , mSampleIndex(0)
     160             :   , mFrameCount(0)
     161             :   , mFinished(false)
     162           0 :   , mDrained(false)
     163             : {
     164           0 :   MOZ_ASSERT(static_cast<Benchmark*>(mMainThreadState)->OnThread());
     165           0 : }
     166             : 
     167             : void
     168           0 : BenchmarkPlayback::DemuxSamples()
     169             : {
     170           0 :   MOZ_ASSERT(OnThread());
     171             : 
     172           0 :   RefPtr<Benchmark> ref(mMainThreadState);
     173           0 :   mDemuxer->Init()->Then(
     174           0 :     Thread(), __func__,
     175           0 :     [this, ref](nsresult aResult) {
     176           0 :       MOZ_ASSERT(OnThread());
     177             :       mTrackDemuxer =
     178           0 :         mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
     179           0 :       if (!mTrackDemuxer) {
     180           0 :         MainThreadShutdown();
     181           0 :         return;
     182             :       }
     183           0 :       DemuxNextSample();
     184             :     },
     185           0 :     [this, ref](const MediaResult& aError) { MainThreadShutdown(); });
     186           0 : }
     187             : 
     188             : void
     189           0 : BenchmarkPlayback::DemuxNextSample()
     190             : {
     191           0 :   MOZ_ASSERT(OnThread());
     192             : 
     193           0 :   RefPtr<Benchmark> ref(mMainThreadState);
     194           0 :   RefPtr<MediaTrackDemuxer::SamplesPromise> promise = mTrackDemuxer->GetSamples();
     195             :   promise->Then(
     196           0 :     Thread(), __func__,
     197           0 :     [this, ref](RefPtr<MediaTrackDemuxer::SamplesHolder> aHolder) {
     198           0 :       mSamples.AppendElements(Move(aHolder->mSamples));
     199           0 :       if (ref->mParameters.mStopAtFrame
     200           0 :           && mSamples.Length() == (size_t)ref->mParameters.mStopAtFrame.ref()) {
     201           0 :         InitDecoder(Move(*mTrackDemuxer->GetInfo()));
     202             :       } else {
     203           0 :         Dispatch(NS_NewRunnableFunction("BenchmarkPlayback::DemuxNextSample",
     204           0 :                                         [this, ref]() { DemuxNextSample(); }));
     205             :       }
     206           0 :     },
     207           0 :     [this, ref](const MediaResult& aError) {
     208           0 :       switch (aError.Code()) {
     209             :         case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
     210           0 :           InitDecoder(Move(*mTrackDemuxer->GetInfo()));
     211           0 :           break;
     212             :         default:
     213           0 :           MainThreadShutdown();
     214             :       }
     215           0 :     });
     216           0 : }
     217             : 
     218             : void
     219           0 : BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo)
     220             : {
     221           0 :   MOZ_ASSERT(OnThread());
     222             : 
     223           0 :   RefPtr<PDMFactory> platform = new PDMFactory();
     224           0 :   mDecoder = platform->CreateDecoder({ aInfo, mDecoderTaskQueue });
     225           0 :   if (!mDecoder) {
     226           0 :     MainThreadShutdown();
     227           0 :     return;
     228             :   }
     229           0 :   RefPtr<Benchmark> ref(mMainThreadState);
     230           0 :   mDecoder->Init()->Then(
     231           0 :     Thread(), __func__,
     232           0 :     [this, ref](TrackInfo::TrackType aTrackType) {
     233           0 :       InputExhausted();
     234           0 :     },
     235           0 :     [this, ref](const MediaResult& aError) {
     236           0 :       MainThreadShutdown();
     237           0 :     });
     238             : }
     239             : 
     240             : void
     241           0 : BenchmarkPlayback::MainThreadShutdown()
     242             : {
     243           0 :   MOZ_ASSERT(OnThread());
     244             : 
     245           0 :   if (mFinished) {
     246             :     // Nothing more to do.
     247           0 :     return;
     248             :   }
     249           0 :   mFinished = true;
     250             : 
     251           0 :   if (mDecoder) {
     252           0 :     RefPtr<Benchmark> ref(mMainThreadState);
     253           0 :     mDecoder->Flush()->Then(
     254           0 :       Thread(), __func__,
     255           0 :       [ref, this]() {
     256           0 :         mDecoder->Shutdown()->Then(
     257           0 :           Thread(), __func__,
     258           0 :           [ref, this]() {
     259           0 :             mDecoderTaskQueue->BeginShutdown();
     260           0 :             mDecoderTaskQueue->AwaitShutdownAndIdle();
     261           0 :             mDecoderTaskQueue = nullptr;
     262             : 
     263           0 :             if (mTrackDemuxer) {
     264           0 :               mTrackDemuxer->Reset();
     265           0 :               mTrackDemuxer->BreakCycles();
     266           0 :               mTrackDemuxer = nullptr;
     267             :             }
     268             : 
     269           0 :             Thread()->AsTaskQueue()->BeginShutdown()->Then(
     270           0 :               ref->Thread(), __func__,
     271           0 :               [ref]() { ref->Dispose(); },
     272           0 :               []() { MOZ_CRASH("not reached"); });
     273           0 :           },
     274           0 :           []() { MOZ_CRASH("not reached"); });
     275           0 :         mDecoder = nullptr;
     276           0 :       },
     277           0 :       []() { MOZ_CRASH("not reached"); });
     278             :   }
     279             : }
     280             : 
     281             : void
     282           0 : BenchmarkPlayback::Output(const MediaDataDecoder::DecodedData& aResults)
     283             : {
     284           0 :   MOZ_ASSERT(OnThread());
     285           0 :   RefPtr<Benchmark> ref(mMainThreadState);
     286           0 :   mFrameCount += aResults.Length();
     287           0 :   if (!mDecodeStartTime && mFrameCount >= ref->mParameters.mStartupFrame) {
     288           0 :     mDecodeStartTime = Some(TimeStamp::Now());
     289             :   }
     290           0 :   TimeStamp now = TimeStamp::Now();
     291           0 :   int32_t frames = mFrameCount - ref->mParameters.mStartupFrame;
     292           0 :   TimeDuration elapsedTime = now - mDecodeStartTime.refOr(now);
     293           0 :   if (!mFinished
     294           0 :       && (((frames == ref->mParameters.mFramesToMeasure) && frames > 0)
     295           0 :           || elapsedTime >= ref->mParameters.mTimeout
     296           0 :           || mDrained)) {
     297           0 :     uint32_t decodeFps = frames / elapsedTime.ToSeconds();
     298           0 :     MainThreadShutdown();
     299           0 :     ref->Dispatch(
     300           0 :       NS_NewRunnableFunction("BenchmarkPlayback::Output", [ref, decodeFps]() {
     301           0 :         ref->ReturnResult(decodeFps);
     302           0 :       }));
     303             :   }
     304           0 : }
     305             : 
     306             : void
     307           0 : BenchmarkPlayback::InputExhausted()
     308             : {
     309           0 :   MOZ_ASSERT(OnThread());
     310           0 :   if (mFinished || mSampleIndex >= mSamples.Length()) {
     311           0 :     return;
     312             :   }
     313           0 :   RefPtr<Benchmark> ref(mMainThreadState);
     314           0 :   mDecoder->Decode(mSamples[mSampleIndex])
     315           0 :     ->Then(Thread(), __func__,
     316           0 :            [ref, this](const MediaDataDecoder::DecodedData& aResults) {
     317           0 :              Output(aResults);
     318           0 :              InputExhausted();
     319           0 :            },
     320           0 :            [ref, this](const MediaResult& aError) { MainThreadShutdown(); });
     321           0 :   mSampleIndex++;
     322           0 :   if (mSampleIndex == mSamples.Length()) {
     323           0 :     if (ref->mParameters.mStopAtFrame) {
     324           0 :       mSampleIndex = 0;
     325             :     } else {
     326           0 :       mDecoder->Drain()->Then(
     327           0 :         Thread(), __func__,
     328           0 :         [ref, this](const MediaDataDecoder::DecodedData& aResults) {
     329           0 :           mDrained = true;
     330           0 :           Output(aResults);
     331           0 :         },
     332           0 :         [ref, this](const MediaResult& aError) { MainThreadShutdown(); });
     333             :     }
     334             :   }
     335             : }
     336             : 
     337             : } // namespace mozilla

Generated by: LCOV version 1.13