Bug 1586370 - Pass IterationEnd up to the graph rather than back-querying the driver. r=padenot

This makes it simpler to maintain state in the GraphDriver in more complex
cases, such as when an AudioCallbackDriver is backed by a fallback driver.

Differential Revision: https://phabricator.services.mozilla.com/D57553

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Andreas Pehrson 2019-12-18 22:52:24 +00:00
Родитель 712efff333
Коммит a4fbb9b878
7 изменённых файлов: 41 добавлений и 27 удалений

Просмотреть файл

@ -167,7 +167,7 @@ bool SystemClockDriver::IsFallback() { return mIsFallback; }
void ThreadedDriver::RunThread() {
mThreadRunning = true;
while (true) {
mIterationStart = IterationEnd();
mIterationStart = mIterationEnd;
mIterationEnd += GetIntervalForIteration();
if (mStateComputedTime < mIterationEnd) {
@ -202,7 +202,8 @@ void ThreadedDriver::RunThread() {
(long)nextStateComputedTime));
mStateComputedTime = nextStateComputedTime;
IterationResult result = Graph()->OneIteration(mStateComputedTime, nullptr);
IterationResult result =
Graph()->OneIteration(mStateComputedTime, mIterationEnd, nullptr);
if (result.IsStop()) {
// Signal that we're done stopping.
@ -231,7 +232,7 @@ MediaTime SystemClockDriver::GetIntervalForIteration() {
MOZ_LOG(gMediaTrackGraphLog, LogLevel::Verbose,
("%p: Updating current time to %f (real %f, StateComputedTime() %f)",
Graph(), MediaTimeToSeconds(IterationEnd() + interval),
Graph(), MediaTimeToSeconds(mIterationEnd + interval),
(now - mInitialTimeStamp).ToSeconds(),
MediaTimeToSeconds(mStateComputedTime)));
@ -726,8 +727,9 @@ long AudioCallbackDriver::DataCallback(const AudioDataValue* aInputBuffer,
bool iterate = mBuffer.Available();
IterationResult result =
iterate ? Graph()->OneIteration(nextStateComputedTime, &mMixer)
: IterationResult::CreateStillProcessing();
iterate
? Graph()->OneIteration(nextStateComputedTime, mIterationEnd, &mMixer)
: IterationResult::CreateStillProcessing();
if (iterate) {
// We totally filled the buffer (and mScratchBuffer isn't empty).
// We don't need to run an iteration and if we do so we may overflow.

Просмотреть файл

@ -178,7 +178,8 @@ struct GraphInterface {
virtual void DeviceChanged() = 0;
/* Called by GraphDriver to iterate the graph. Output from the graph gets
* mixed into aMixer, if it is non-null. */
virtual IterationResult OneIteration(GraphTime aStateEnd,
virtual IterationResult OneIteration(GraphTime aStateComputedEnd,
GraphTime aIterationEnd,
AudioMixer* aMixer) = 0;
#ifdef DEBUG
/* True if we're on aDriver's thread, or if we're on mGraphRunner's thread
@ -271,8 +272,6 @@ class GraphDriver {
GraphDriver* PreviousDriver();
void SetPreviousDriver(GraphDriver* aPreviousDriver);
GraphTime IterationEnd() { return mIterationEnd; }
virtual AudioCallbackDriver* AsAudioCallbackDriver() { return nullptr; }
virtual OfflineClockDriver* AsOfflineClockDriver() { return nullptr; }
@ -314,11 +313,9 @@ class GraphDriver {
}
protected:
// Time of the start of this graph iteration. This must be accessed while
// having the monitor.
// Time of the start of this graph iteration.
GraphTime mIterationStart = 0;
// Time of the end of this graph iteration. This must be accessed while having
// the monitor.
// Time of the end of this graph iteration.
GraphTime mIterationEnd = 0;
// Time until which the graph has processed data.
GraphTime mStateComputedTime = 0;

Просмотреть файл

@ -56,13 +56,13 @@ void GraphRunner::Shutdown() {
mThread->Shutdown();
}
auto GraphRunner::OneIteration(GraphTime aStateEnd, AudioMixer* aMixer)
-> IterationResult {
auto GraphRunner::OneIteration(GraphTime aStateEnd, GraphTime aIterationEnd,
AudioMixer* aMixer) -> IterationResult {
TRACE_AUDIO_CALLBACK();
MonitorAutoLock lock(mMonitor);
MOZ_ASSERT(mThreadState == ThreadState::Wait);
mIterationState = Some(IterationState(aStateEnd, aMixer));
mIterationState = Some(IterationState(aStateEnd, aIterationEnd, aMixer));
#ifdef DEBUG
if (auto audioDriver = mGraph->CurrentDriver()->AsAudioCallbackDriver()) {
@ -109,6 +109,7 @@ NS_IMETHODIMP GraphRunner::Run() {
MOZ_DIAGNOSTIC_ASSERT(mIterationState.isSome());
TRACE();
mIterationResult = mGraph->OneIterationImpl(mIterationState->StateEnd(),
mIterationState->IterationEnd(),
mIterationState->Mixer());
// Signal that mIterationResult was updated
mThreadState = ThreadState::Wait;

Просмотреть файл

@ -32,10 +32,11 @@ class GraphRunner final : public Runnable {
MOZ_CAN_RUN_SCRIPT void Shutdown();
/**
* Signals one iteration of mGraph. Hands aStateEnd over to mThread and runs
* Signals one iteration of mGraph. Hands state over to mThread and runs
* the iteration there.
*/
IterationResult OneIteration(GraphTime aStateEnd, AudioMixer* aMixer);
IterationResult OneIteration(GraphTime aStateEnd, GraphTime aIterationEnd,
AudioMixer* aMixer);
/**
* Runs mGraph until it shuts down.
@ -62,17 +63,21 @@ class GraphRunner final : public Runnable {
class IterationState {
GraphTime mStateEnd;
GraphTime mIterationEnd;
AudioMixer* MOZ_NON_OWNING_REF mMixer;
public:
IterationState(GraphTime aStateEnd, AudioMixer* aMixer)
: mStateEnd(aStateEnd), mMixer(aMixer) {}
IterationState(GraphTime aStateEnd, GraphTime aIterationEnd,
AudioMixer* aMixer)
: mStateEnd(aStateEnd), mIterationEnd(aIterationEnd), mMixer(aMixer) {}
IterationState& operator=(const IterationState& aOther) {
mStateEnd = aOther.mStateEnd;
mIterationEnd = aOther.mIterationEnd;
mMixer = aOther.mMixer;
return *this;
}
GraphTime StateEnd() const { return mStateEnd; }
GraphTime IterationEnd() const { return mIterationEnd; }
AudioMixer* Mixer() const { return mMixer; }
};

Просмотреть файл

@ -126,7 +126,7 @@ TrackTime MediaTrackGraphImpl::GraphTimeToTrackTimeWithBlocking(
GraphTime MediaTrackGraphImpl::IterationEnd() const {
MOZ_ASSERT(OnGraphThread());
return CurrentDriver()->IterationEnd();
return mIterationEndTime;
}
void MediaTrackGraphImpl::UpdateCurrentTimeForTracks(
@ -1302,20 +1302,24 @@ bool MediaTrackGraphImpl::UpdateMainThreadState() {
return true;
}
auto MediaTrackGraphImpl::OneIteration(GraphTime aStateEnd, AudioMixer* aMixer)
-> IterationResult {
auto MediaTrackGraphImpl::OneIteration(GraphTime aStateEnd,
GraphTime aIterationEnd,
AudioMixer* aMixer) -> IterationResult {
if (mGraphRunner) {
return mGraphRunner->OneIteration(aStateEnd, aMixer);
return mGraphRunner->OneIteration(aStateEnd, aIterationEnd, aMixer);
}
return OneIterationImpl(aStateEnd, aMixer);
return OneIterationImpl(aStateEnd, aIterationEnd, aMixer);
}
auto MediaTrackGraphImpl::OneIterationImpl(GraphTime aStateEnd,
GraphTime aIterationEnd,
AudioMixer* aMixer)
-> IterationResult {
TRACE_AUDIO_CALLBACK();
mIterationEndTime = aIterationEnd;
if (SoftRealTimeLimitReached()) {
DemoteThreadFromRealTime();
}

Просмотреть файл

@ -216,13 +216,14 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
* OneIterationImpl is called directly. Output from the graph gets mixed into
* aMixer, if it is non-null.
*/
IterationResult OneIteration(GraphTime aStateEnd,
IterationResult OneIteration(GraphTime aStateEnd, GraphTime aIterationEnd,
AudioMixer* aMixer) override;
/**
* Returns true if this MediaTrackGraph should keep running
*/
IterationResult OneIterationImpl(GraphTime aStateEnd, AudioMixer* aMixer);
IterationResult OneIterationImpl(GraphTime aStateEnd, GraphTime aIterationEnd,
AudioMixer* aMixer);
/**
* Called from the driver, when the graph thread is about to stop, to tell
@ -725,6 +726,10 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
* at this time. This is behind mStateComputedTime during processing.
*/
GraphTime mProcessedTime = 0;
/**
* The end of the current iteration. Only access on the graph thread.
*/
GraphTime mIterationEndTime = 0;
/**
* The graph should stop processing at this time.
*/

Просмотреть файл

@ -30,7 +30,7 @@ class MockGraphInterface : public GraphInterface {
MOCK_METHOD0(DeviceChanged, void());
/* OneIteration cannot be mocked because IterationResult is non-memmovable and
* cannot be passed as a parameter, which GMock does internally. */
IterationResult OneIteration(GraphTime, AudioMixer*) {
IterationResult OneIteration(GraphTime, GraphTime, AudioMixer*) {
return mKeepProcessing ? IterationResult::CreateStillProcessing()
: IterationResult::CreateStop(
NS_NewRunnableFunction(__func__, [] {}));