зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1628779 - Update the latency periodically on main thread. r=achronop
We're doing it async, triggered during the stable state runnable, and then the values are cached in atomic variables, so that the rendering thread can have the info as well, for using during processing. Differential Revision: https://phabricator.services.mozilla.com/D75331
This commit is contained in:
Родитель
25413bb019
Коммит
3eb71b17bf
|
@ -1232,6 +1232,17 @@ TimeDuration AudioCallbackDriver::AudioOutputLatency() {
|
|||
mSampleRate);
|
||||
}
|
||||
|
||||
TimeDuration AudioCallbackDriver::AudioInputLatency() {
|
||||
uint32_t latencyFrames;
|
||||
int rv = cubeb_stream_get_input_latency(mAudioStream, &latencyFrames);
|
||||
if (rv || mSampleRate == 0) {
|
||||
return TimeDuration::FromSeconds(0.0);
|
||||
}
|
||||
|
||||
return TimeDuration::FromSeconds(static_cast<double>(latencyFrames) /
|
||||
mSampleRate);
|
||||
}
|
||||
|
||||
void AudioCallbackDriver::FallbackToSystemClockDriver() {
|
||||
MOZ_ASSERT(!ThreadRunning());
|
||||
MOZ_ASSERT(mAudioStreamState == AudioStreamState::None ||
|
||||
|
|
|
@ -646,6 +646,8 @@ class AudioCallbackDriver : public GraphDriver,
|
|||
|
||||
// Returns the output latency for the current audio output stream.
|
||||
TimeDuration AudioOutputLatency();
|
||||
// Returns the input latency for the current audio output stream.
|
||||
TimeDuration AudioInputLatency();
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
|
@ -910,9 +910,9 @@ void MediaTrackGraphImpl::DeviceChanged() {
|
|||
return;
|
||||
}
|
||||
|
||||
// Reset the latency, it will get fetched again next time it's queried.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mAudioOutputLatency = 0.0;
|
||||
// Have the latency re-queried next stable state.
|
||||
mLatencyQueryCounter = LATENCY_QUERYING_INTERVAL;
|
||||
|
||||
// Dispatch to the bg thread to do the (potentially expensive) query of the
|
||||
// maximum channel count, and then dispatch back to the main thread, then to
|
||||
|
@ -1687,6 +1687,11 @@ void MediaTrackGraphImpl::RunInStableState(bool aSourceIsMTG) {
|
|||
LOG(LogLevel::Debug,
|
||||
("%p: Running stable state callback. Current state: %s", this,
|
||||
LifecycleState_str[LifecycleStateRef()]));
|
||||
} else {
|
||||
if (mLatencyQueryCounter++ == LATENCY_QUERYING_INTERVAL) {
|
||||
UpdateAudioLatencies();
|
||||
mLatencyQueryCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
runnables.SwapElements(mUpdateRunnables);
|
||||
|
@ -2987,6 +2992,7 @@ MediaTrackGraphImpl::MediaTrackGraphImpl(
|
|||
,
|
||||
mMainThreadGraphTime(0, "MediaTrackGraphImpl::mMainThreadGraphTime"),
|
||||
mAudioOutputLatency(0.0),
|
||||
mAudioInputLatency(0.0),
|
||||
mMaxOutputChannelCount(std::min(8u, CubebUtils::MaxNumberOfChannels())) {
|
||||
if (aRunTypeRequested == SINGLE_THREAD && !mGraphRunner) {
|
||||
// Failed to create thread. Jump to the last phase of the lifecycle.
|
||||
|
@ -3624,28 +3630,44 @@ uint32_t MediaTrackGraphImpl::AudioOutputChannelCount() const {
|
|||
}
|
||||
|
||||
double MediaTrackGraph::AudioOutputLatency() {
|
||||
return static_cast<MediaTrackGraphImpl*>(this)->AudioOutputLatency();
|
||||
return static_cast<MediaTrackGraphImpl*>(this)->CachedAudioOutputLatency();
|
||||
}
|
||||
|
||||
double MediaTrackGraphImpl::AudioOutputLatency() {
|
||||
double MediaTrackGraphImpl::CachedAudioOutputLatency() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mAudioOutputLatency != 0.0) {
|
||||
return mAudioOutputLatency;
|
||||
}
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
if (CurrentDriver()->AsAudioCallbackDriver()) {
|
||||
mAudioOutputLatency = CurrentDriver()
|
||||
->AsAudioCallbackDriver()
|
||||
->AudioOutputLatency()
|
||||
.ToSeconds();
|
||||
} else {
|
||||
// Failure mode: return 0.0 if running on a normal thread.
|
||||
mAudioOutputLatency = 0.0;
|
||||
}
|
||||
|
||||
return mAudioOutputLatency;
|
||||
}
|
||||
|
||||
double MediaTrackGraphImpl::CachedAudioInputLatency() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return mAudioInputLatency;
|
||||
}
|
||||
|
||||
void MediaTrackGraphImpl::UpdateAudioLatencies() {
|
||||
RefPtr<MediaTrackGraphImpl> self = this;
|
||||
NS_DispatchBackgroundTask(
|
||||
NS_NewRunnableFunction("UpdateLatency", [self{std::move(self)}]() {
|
||||
MonitorAutoLock lock(self->mMonitor);
|
||||
if (self->CurrentDriver()->AsAudioCallbackDriver()) {
|
||||
AudioCallbackDriver* driver =
|
||||
self->CurrentDriver()->AsAudioCallbackDriver();
|
||||
if (driver->InputChannelCount()) {
|
||||
self->mAudioInputLatency = driver->AudioInputLatency().ToSeconds();
|
||||
}
|
||||
self->mAudioOutputLatency = driver->AudioOutputLatency().ToSeconds();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
double MediaTrackGraphImpl::AudioOutputLatencyGraphThread() {
|
||||
AssertOnGraphThreadOrNotRunning();
|
||||
return mAudioOutputLatency;
|
||||
}
|
||||
double MediaTrackGraphImpl::AudioInputLatencyGraphThread() {
|
||||
AssertOnGraphThreadOrNotRunning();
|
||||
return mAudioInputLatency;
|
||||
}
|
||||
|
||||
bool MediaTrackGraph::IsNonRealtime() const {
|
||||
return !static_cast<const MediaTrackGraphImpl*>(this)->mRealtime;
|
||||
}
|
||||
|
|
|
@ -496,7 +496,14 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
|
|||
// Set a new maximum channel count. Graph thread only.
|
||||
void SetMaxOutputChannelCount(uint32_t aMaxChannelCount);
|
||||
|
||||
double AudioOutputLatency();
|
||||
// Main thread only, query and update the cached latency figure.
|
||||
double CachedAudioOutputLatency();
|
||||
double CachedAudioInputLatency();
|
||||
void UpdateAudioLatencies();
|
||||
|
||||
// Graph thread only, get the cached latency figure.
|
||||
double AudioOutputLatencyGraphThread();
|
||||
double AudioInputLatencyGraphThread();
|
||||
|
||||
/**
|
||||
* The audio input channel count for a MediaTrackGraph is the max of all the
|
||||
|
@ -1024,10 +1031,26 @@ class MediaTrackGraphImpl : public MediaTrackGraph,
|
|||
GraphTime mNextMainThreadGraphTime = 0;
|
||||
|
||||
/**
|
||||
* Cached audio output latency, in seconds. Main thread only. This is reset
|
||||
* Cached audio output latency, in seconds. This is reset
|
||||
* whenever the audio device running this MediaTrackGraph changes.
|
||||
*/
|
||||
double mAudioOutputLatency;
|
||||
std::atomic<double> mAudioOutputLatency;
|
||||
/**
|
||||
* Cached audio input latency, in seconds. This is reset
|
||||
* whenever the audio device running this MediaTrackGraph changes.
|
||||
*/
|
||||
std::atomic<double> mAudioInputLatency;
|
||||
|
||||
/**
|
||||
* Only query the latency once every LATENCY_QUERYING_INTERVAL stable state.
|
||||
*/
|
||||
const uint32_t LATENCY_QUERYING_INTERVAL = 100;
|
||||
|
||||
/**
|
||||
* Counter to only query the audio latencies every N iterations. Main thread
|
||||
* only.
|
||||
*/
|
||||
uint32_t mLatencyQueryCounter = 0;
|
||||
|
||||
/**
|
||||
* The max audio output channel count the default audio output device
|
||||
|
|
Загрузка…
Ссылка в новой задаче