Offset direct/offload timestamps by downstream latency
Test: A/V sync of direct/offload DD+ non HW A/V sync playback thread
through MSD, and MSD -> Audio HAL patch in DD+ non HW A/V sync
mode.
Change-Id: I244e9fda9741fe9a9ea913f39901654ebefb973c
(cherry picked from commit 8729c2eb3eabda3f6b6985a113bd2022b5b379c9)
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 5555acf..f833cf7 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -3185,7 +3185,6 @@
if (mType == OFFLOAD || mType == DIRECT) {
mTimestampVerifier.setDiscontinuityMode(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
}
- audio_utils::Statistics<double> downstreamLatencyStatMs(0.999 /* alpha */);
audio_patch_handle_t lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
while (!exitPending())
@@ -3215,7 +3214,7 @@
downstreamPatchHandle = swPatches[0].getPatchHandle();
}
if (downstreamPatchHandle != lastDownstreamPatchHandle) {
- downstreamLatencyStatMs.reset();
+ mDownstreamLatencyStatMs.reset();
lastDownstreamPatchHandle = downstreamPatchHandle;
}
if (status == OK) {
@@ -3229,14 +3228,14 @@
if (latencyMs < minLatency) latencyMs = minLatency;
else if (latencyMs > maxLatency) latencyMs = maxLatency;
}
- downstreamLatencyStatMs.add(latencyMs);
+ mDownstreamLatencyStatMs.add(latencyMs);
}
mAudioFlinger->mLock.unlock();
}
} else {
if (lastDownstreamPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
// our device is no longer AUDIO_DEVICE_OUT_BUS, reset patch handle and stats.
- downstreamLatencyStatMs.reset();
+ mDownstreamLatencyStatMs.reset();
lastDownstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
}
}
@@ -3285,10 +3284,10 @@
(long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
// Note: Downstream latency only added if timestamp correction enabled.
- if (downstreamLatencyStatMs.getN() > 0) { // we have latency info.
+ if (mDownstreamLatencyStatMs.getN() > 0) { // we have latency info.
const int64_t newPosition =
timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
- - int64_t(downstreamLatencyStatMs.getMean() * mSampleRate * 1e-3);
+ - int64_t(mDownstreamLatencyStatMs.getMean() * mSampleRate * 1e-3);
// prevent retrograde
timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = max(
newPosition,
@@ -3747,6 +3746,15 @@
uint64_t position64;
if (mOutput->getPresentationPosition(&position64, ×tamp.mTime) == OK) {
timestamp.mPosition = (uint32_t)position64;
+ if (mDownstreamLatencyStatMs.getN() > 0) {
+ const uint32_t positionOffset =
+ (uint32_t)(mDownstreamLatencyStatMs.getMean() * mSampleRate * 1e-3);
+ if (positionOffset > timestamp.mPosition) {
+ timestamp.mPosition = 0;
+ } else {
+ timestamp.mPosition -= positionOffset;
+ }
+ }
return NO_ERROR;
}
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 61f7baf..49fc234 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1082,6 +1082,8 @@
static const size_t kFastMixerLogSize = 8 * 1024;
sp<NBLog::Writer> mFastMixerNBLogWriter;
+ // Downstream patch latency, available if mDownstreamLatencyStatMs.getN() > 0.
+ audio_utils::Statistics<double> mDownstreamLatencyStatMs{0.999};
public:
virtual bool hasFastMixer() const = 0;