Exemple #1
0
void BenchmarkPlayback::DemuxNextSample() {
  MOZ_ASSERT(OnThread());

  RefPtr<Benchmark> ref(mGlobalState);
  RefPtr<MediaTrackDemuxer::SamplesPromise> promise =
      mTrackDemuxer->GetSamples();
  promise->Then(
      Thread(), __func__,
      [this, ref](RefPtr<MediaTrackDemuxer::SamplesHolder> aHolder) {
        mSamples.AppendElements(std::move(aHolder->mSamples));
        if (ref->mParameters.mStopAtFrame &&
            mSamples.Length() == ref->mParameters.mStopAtFrame.ref()) {
          InitDecoder(std::move(*mTrackDemuxer->GetInfo()));
        } else {
          Dispatch(
              NS_NewRunnableFunction("BenchmarkPlayback::DemuxNextSample",
                                     [this, ref]() { DemuxNextSample(); }));
        }
      },
      [this, ref](const MediaResult& aError) {
        switch (aError.Code()) {
          case NS_ERROR_DOM_MEDIA_END_OF_STREAM:
            InitDecoder(std::move(*mTrackDemuxer->GetInfo()));
            break;
          default:
            Error(aError);
            break;
        }
      });
}
Exemple #2
0
void
BenchmarkPlayback::DemuxNextSample()
{
  MOZ_ASSERT(OnThread());

  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 &&
          mSamples.Length() == (size_t)ref->mParameters.mStopAtFrame.ref()) {
        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();
      }
    });
}
Exemple #3
0
void
BenchmarkPlayback::MainThreadShutdown()
{
  MOZ_ASSERT(OnThread());

  if (mDecoder) {
    mDecoder->Flush();
    mDecoder->Shutdown();
    mDecoder = nullptr;
  }

  mDecoderTaskQueue->BeginShutdown();
  mDecoderTaskQueue->AwaitShutdownAndIdle();
  mDecoderTaskQueue = nullptr;

  if (mTrackDemuxer) {
    mTrackDemuxer->Reset();
    mTrackDemuxer->BreakCycles();
    mTrackDemuxer = nullptr;
  }

  RefPtr<Benchmark> ref(mMainThreadState);
  Thread()->AsTaskQueue()->BeginShutdown()->Then(
    ref->Thread(), __func__,
    [ref]() {  ref->Dispose(); },
    []() { MOZ_CRASH("not reached"); });
}
Exemple #4
0
void
BenchmarkPlayback::InputExhausted()
{
  MOZ_ASSERT(OnThread());
  if (mFinished || mSampleIndex >= mSamples.Length()) {
    return;
  }
  RefPtr<Benchmark> ref(mMainThreadState);
  mDecoder->Decode(mSamples[mSampleIndex])
    ->Then(Thread(), __func__,
           [ref, this](const MediaDataDecoder::DecodedData& aResults) {
             Output(aResults);
             InputExhausted();
           },
           [ref, this](const MediaResult& aError) { MainThreadShutdown(); });
  mSampleIndex++;
  if (mSampleIndex == mSamples.Length()) {
    if (ref->mParameters.mStopAtFrame) {
      mSampleIndex = 0;
    } else {
      mDecoder->Drain()->Then(
        Thread(), __func__,
        [ref, this](const MediaDataDecoder::DecodedData& aResults) {
          mDrained = true;
          Output(aResults);
        },
        [ref, this](const MediaResult& aError) { MainThreadShutdown(); });
    }
  }
}
void
Benchmark::ReturnResult(uint32_t aDecodeFps)
{
  MOZ_ASSERT(OnThread());

  mPromise.ResolveIfExists(aDecodeFps, __func__);
}
void
Benchmark::Dispose()
{
  MOZ_ASSERT(OnThread());

  mKeepAliveUntilComplete = nullptr;
  mPromise.RejectIfExists(false, __func__);
}
Exemple #7
0
void BenchmarkPlayback::Error(const MediaResult& aError) {
  MOZ_ASSERT(OnThread());

  RefPtr<Benchmark> ref(mGlobalState);
  GlobalShutdown();
  ref->Dispatch(
      NS_NewRunnableFunction("BenchmarkPlayback::Error",
                             [ref, aError]() { ref->ReturnError(aError); }));
}
Exemple #8
0
void
BenchmarkPlayback::DemuxSamples()
{
  MOZ_ASSERT(OnThread());

  RefPtr<Benchmark> ref(mMainThreadState);
  mDemuxer->Init()->Then(
    Thread(), __func__,
    [this, ref](nsresult aResult) {
      MOZ_ASSERT(OnThread());
      mTrackDemuxer =
        mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
      if (!mTrackDemuxer) {
        MainThreadShutdown();
      }
      DemuxNextSample();
    },
    [this, ref](DemuxerFailureReason aReason) { MainThreadShutdown(); });
}
RefPtr<Benchmark::BenchmarkPromise>
Benchmark::Run()
{
  MOZ_ASSERT(OnThread());

  RefPtr<BenchmarkPromise> p = mPromise.Ensure(__func__);
  RefPtr<Benchmark> self = this;
  mPlaybackState.Dispatch(
    NS_NewRunnableFunction([self]() { self->mPlaybackState.DemuxSamples(); }));
  return p;
}
Exemple #10
0
void BenchmarkPlayback::DemuxSamples() {
  MOZ_ASSERT(OnThread());

  RefPtr<Benchmark> ref(mGlobalState);
  mDemuxer->Init()->Then(
      Thread(), __func__,
      [this, ref](nsresult aResult) {
        MOZ_ASSERT(OnThread());
        if (mDemuxer->GetNumberTracks(TrackInfo::kVideoTrack)) {
          mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
        } else if (mDemuxer->GetNumberTracks(TrackInfo::kAudioTrack)) {
          mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
        }
        if (!mTrackDemuxer) {
          Error(MediaResult(NS_ERROR_FAILURE, "Can't create track demuxer"));
          return;
        }
        DemuxNextSample();
      },
      [this, ref](const MediaResult& aError) { Error(aError); });
}
Exemple #11
0
void BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo) {
  MOZ_ASSERT(OnThread());

  RefPtr<PDMFactory> platform = new PDMFactory();
  mDecoder = platform->CreateDecoder({aInfo, mDecoderTaskQueue});
  if (!mDecoder) {
    Error(MediaResult(NS_ERROR_FAILURE, "Failed to create decoder"));
    return;
  }
  RefPtr<Benchmark> ref(mGlobalState);
  mDecoder->Init()->Then(
      Thread(), __func__,
      [this, ref](TrackInfo::TrackType aTrackType) { InputExhausted(); },
      [this, ref](const MediaResult& aError) { Error(aError); });
}
Exemple #12
0
bool GraphRunner::RunByGraphDriver(GraphDriver* aDriver) {
  if (!OnThread()) {
    return false;
  }

  if (auto audioDriver = aDriver->AsAudioCallbackDriver()) {
    return audioDriver->ThreadId() == mAudioDriverThreadId;
  }

  if (auto clockDriver = aDriver->AsSystemClockDriver()) {
    return clockDriver->Thread() == mClockDriverThread;
  }

  MOZ_CRASH("Unknown driver");
}
Exemple #13
0
void BenchmarkPlayback::InputExhausted() {
  MOZ_ASSERT(OnThread());
  MOZ_ASSERT(!mFinished);

  if (mSampleIndex >= mSamples.Length()) {
    Error(MediaResult(NS_ERROR_FAILURE, "Nothing left to decode"));
    return;
  }

  RefPtr<MediaRawData> sample = mSamples[mSampleIndex];
  RefPtr<Benchmark> ref(mGlobalState);
  RefPtr<MediaDataDecoder::DecodePromise> p = mDecoder->Decode(sample);

  mSampleIndex++;
  if (mSampleIndex == mSamples.Length() && !ref->mParameters.mStopAtFrame) {
    // Complete current frame decode then drain if still necessary.
    p->Then(Thread(), __func__,
            [ref, this](MediaDataDecoder::DecodedData&& aResults) {
              Output(std::move(aResults));
              if (!mFinished) {
                mDecoder->Drain()->Then(
                    Thread(), __func__,
                    [ref, this](MediaDataDecoder::DecodedData&& aResults) {
                      mDrained = true;
                      Output(std::move(aResults));
                      MOZ_ASSERT(mFinished, "We must be done now");
                    },
                    [ref, this](const MediaResult& aError) { Error(aError); });
              }
            },
            [ref, this](const MediaResult& aError) { Error(aError); });
  } else {
    if (mSampleIndex == mSamples.Length() && ref->mParameters.mStopAtFrame) {
      mSampleIndex = 0;
    }
    // Continue decoding
    p->Then(Thread(), __func__,
            [ref, this](MediaDataDecoder::DecodedData&& aResults) {
              Output(std::move(aResults));
              if (!mFinished) {
                InputExhausted();
              }
            },
            [ref, this](const MediaResult& aError) { Error(aError); });
  }
}
Exemple #14
0
void BenchmarkPlayback::FinalizeShutdown() {
  MOZ_ASSERT(OnThread());

  MOZ_ASSERT(!mDecoder, "mDecoder must have been shutdown already");
  MOZ_DIAGNOSTIC_ASSERT(mDecoderTaskQueue->IsEmpty());
  mDecoderTaskQueue = nullptr;

  if (mTrackDemuxer) {
    mTrackDemuxer->Reset();
    mTrackDemuxer->BreakCycles();
    mTrackDemuxer = nullptr;
  }
  mDemuxer = nullptr;

  RefPtr<Benchmark> ref(mGlobalState);
  ref->Thread()->Dispatch(NS_NewRunnableFunction(
      "BenchmarkPlayback::FinalizeShutdown", [ref]() { ref->Dispose(); }));
}
Exemple #15
0
void
BenchmarkPlayback::InputExhausted()
{
  RefPtr<Benchmark> ref(mMainThreadState);
  Dispatch(NS_NewRunnableFunction([this, ref]() {
    MOZ_ASSERT(OnThread());
    if (mFinished || mSampleIndex >= mSamples.Length()) {
      return;
    }
    mDecoder->Input(mSamples[mSampleIndex]);
    mSampleIndex++;
    if (mSampleIndex == mSamples.Length()) {
      if (ref->mParameters.mStopAtFrame) {
        mSampleIndex = 0;
      } else {
        mDecoder->Drain();
      }
    }
  }));
}
Exemple #16
0
void
BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo)
{
    MOZ_ASSERT(OnThread());

    RefPtr<PDMFactory> platform = new PDMFactory();
    mDecoder = platform->CreateDecoder({ aInfo, mDecoderTaskQueue, reinterpret_cast<MediaDataDecoderCallback*>(this) });
    if (!mDecoder) {
        MainThreadShutdown();
        return;
    }
    RefPtr<Benchmark> ref(mMainThreadState);
    mDecoder->Init()->Then(
        Thread(), __func__,
    [this, ref](TrackInfo::TrackType aTrackType) {
        InputExhausted();
    },
    [this, ref](MediaDataDecoder::DecoderFailureReason aReason) {
        MainThreadShutdown();
    });
}
Exemple #17
0
void
BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo)
{
  MOZ_ASSERT(OnThread());

  RefPtr<PDMFactory> platform = new PDMFactory();
  mDecoder = platform->CreateDecoder(aInfo, mDecoderTaskQueue, this);
  if (!mDecoder) {
    MainThreadShutdown();
    return;
  }
  RefPtr<Benchmark> ref(mMainThreadState);
  mDecoder->Init()->Then(
    ref->Thread(), __func__,
    [this, ref](TrackInfo::TrackType aTrackType) {
      Dispatch(NS_NewRunnableFunction([this, ref]() { InputExhausted(); }));
    },
    [this, ref](MediaDataDecoder::DecoderFailureReason aReason) {
      MainThreadShutdown();
    });
}
Exemple #18
0
void
BenchmarkPlayback::InitDecoder(TrackInfo&& aInfo)
{
  MOZ_ASSERT(OnThread());

  RefPtr<PDMFactory> platform = new PDMFactory();
  mDecoder = platform->CreateDecoder({ aInfo, mDecoderTaskQueue });
  if (!mDecoder) {
    MainThreadShutdown();
    return;
  }
  RefPtr<Benchmark> ref(mMainThreadState);
  mDecoder->Init()->Then(
    Thread(), __func__,
    [this, ref](TrackInfo::TrackType aTrackType) {
      InputExhausted();
    },
    [this, ref](const MediaResult& aError) {
      MainThreadShutdown();
    });
}
Exemple #19
0
void BenchmarkPlayback::GlobalShutdown() {
  MOZ_ASSERT(OnThread());

  MOZ_ASSERT(!mFinished, "We've already shutdown");

  mFinished = true;

  if (mDecoder) {
    RefPtr<Benchmark> ref(mGlobalState);
    mDecoder->Flush()->Then(Thread(), __func__,
                            [ref, this]() {
                              mDecoder->Shutdown()->Then(
                                  Thread(), __func__,
                                  [ref, this]() { FinalizeShutdown(); },
                                  []() { MOZ_CRASH("not reached"); });
                              mDecoder = nullptr;
                            },
                            []() { MOZ_CRASH("not reached"); });
  } else {
    FinalizeShutdown();
  }
}
Exemple #20
0
void BenchmarkPlayback::Output(MediaDataDecoder::DecodedData&& aResults) {
  MOZ_ASSERT(OnThread());
  MOZ_ASSERT(!mFinished);

  RefPtr<Benchmark> ref(mGlobalState);
  mFrameCount += aResults.Length();
  if (!mDecodeStartTime && mFrameCount >= ref->mParameters.mStartupFrame) {
    mDecodeStartTime = Some(TimeStamp::Now());
  }
  TimeStamp now = TimeStamp::Now();
  uint32_t frames = mFrameCount - ref->mParameters.mStartupFrame;
  TimeDuration elapsedTime = now - mDecodeStartTime.refOr(now);
  if (((frames == ref->mParameters.mFramesToMeasure) &&
       mFrameCount > ref->mParameters.mStartupFrame && frames > 0) ||
      elapsedTime >= ref->mParameters.mTimeout || mDrained) {
    uint32_t decodeFps = frames / elapsedTime.ToSeconds();
    GlobalShutdown();
    ref->Dispatch(NS_NewRunnableFunction(
        "BenchmarkPlayback::Output",
        [ref, decodeFps]() { ref->ReturnResult(decodeFps); }));
  }
}
Exemple #21
0
bool
BenchmarkPlayback::OnReaderTaskQueue()
{
  return OnThread();
}
Exemple #22
0
void Benchmark::ReturnError(const MediaResult& aError) {
  MOZ_ASSERT(OnThread());

  mPromise.RejectIfExists(aError, __func__);
}
Exemple #23
0
void Benchmark::Dispose() {
  MOZ_ASSERT(OnThread());

  mKeepAliveUntilComplete = nullptr;
}
void ParseThread(DWORD TID) 
{
   WAITCHAIN_NODE_INFO chain[WCT_MAX_NODE_COUNT];

   DWORD dwNodesInChain;
   BOOL bDeadlock;
   dwNodesInChain = WCT_MAX_NODE_COUNT;
   DWORD dwNodeCount;

   /* Open thread wait chain session */
   HWCT hWCTSession = OpenThreadWaitChainSession(0, NULL);

   /* Get the chain for the current thread
    * Retrieves the wait chain for the specified thread.
	*
	* WctHandle [in]
    *  A handle to the WCT session created by 
	*  the OpenThreadWaitChainSession function.
	*
	* Context [in, optional]
    *  A pointer to an application-defined context structure 
	*  to be passed to the callback function for an asynchronous session.
	* 
	* Flags [in]
    *  The wait chain retrieval options.
	*  This parameter can be one of more of the following values.
	*           Value	                               Meaning
    *  WCT_OUT_OF_PROC_COM_FLAG	         Enumerates all threads of an out-of-proc MTA 
	*                                    COM server to find the correct thread identifier.
	*  
	*  WCT_OUT_OF_PROC_CS_FLAG	         Retrieves critical-section information from other processes.
	*
	*  WCT_OUT_OF_PROC_FLAG	             Follows the wait chain into other processes. 
	*                                    Otherwise, the function reports the first thread 
	*                                    in a different process but does not retrieve additional information.
	* ThreadId [in]
    *  The identifier of the thread. 
	* 
	* NodeCount [in, out]
    *  On input, a number from 1 to WCT_MAX_NODE_COUNT that specifies 
	*  the number of nodes in the wait chain. 
	*  On return, the number of nodes retrieved. 
	*  If the array cannot contain all the nodes of the wait chain, 
	*  the function fails, GetLastError returns ERROR_MORE_DATA, 
	*  and this parameter receives the number of array elements 
	*  required to contain all the nodes.
    *  For asynchronous sessions, check the value that is passed to the callback function. 
	*  Do not free the variable until the callback function has returned.
    * 
	* NodeInfoArray [out]
    *  An array of WAITCHAIN_NODE_INFO structures that receives the wait chain.
    *  For asynchronous sessions, check the value that is passed 
	*  to the callback function. Do not free the array until the callback function has returned.
	* 
	* IsCycle [out]
    *  If the function detects a deadlock, this variable is set to TRUE; 
	*  otherwise, it is set to FALSE.
    *  For asynchronous sessions, check the value 
	*  that is passed to the callback function. 
	*  Do not free the variable until the callback function has returned.
    */
   if (!GetThreadWaitChain(
	      hWCTSession, 
		  NULL, 
		  WCTP_GETINFO_ALL_FLAGS,
          TID, 
		  &dwNodesInChain, 
		  chain, 
		  &bDeadlock)) 
   {
       dwNodeCount = 0;
	   /* Call onThread callback */
       OnThread(TID, FALSE, 0);
       return;
   }

   // Start the chain processing for the current thread
   dwNodeCount = min(dwNodesInChain, WCT_MAX_NODE_COUNT);
   OnThread(TID, bDeadlock, dwNodesInChain);

   // For each node in the chain, call the virtual method with details
   for 
   (
       DWORD current = 0;
       current < min(dwNodesInChain, WCT_MAX_NODE_COUNT);
       current++
   ) 
   {
        OnChainNodeInfo(TID, current, chain[current]);
   }
}