AudioFlinger: Add timestamp correction to MSD BUS Threads
Test: MSD YouTube playback
Bug: 112431914
Change-Id: Ic15ace24d6ab3613be08978b925fd7b9dc7aef38
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index d07f4ba..2a37dd8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -863,6 +863,7 @@
|| mType == DIRECT
|| mType == OFFLOAD) {
dprintf(fd, " Timestamp stats: %s\n", mTimestampVerifier.toString().c_str());
+ dprintf(fd, " Timestamp corrected: %s\n", isTimestampCorrectionEnabled() ? "yes" : "no");
}
if (locked) {
@@ -1732,10 +1733,21 @@
if (mOutput->audioHwDev->canSetMasterMute()) {
mMasterMute = false;
}
+ mIsMsdDevice = strcmp(
+ mOutput->audioHwDev->moduleName(), AUDIO_HARDWARE_MODULE_ID_MSD) == 0;
}
readOutputParameters_l();
+ // TODO: We may also match on address as well as device type for
+ // AUDIO_DEVICE_OUT_BUS, AUDIO_DEVICE_OUT_ALL_A2DP, AUDIO_DEVICE_OUT_REMOTE_SUBMIX
+ if (type == MIXER || type == DIRECT) {
+ mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
+ "audio.timestamp.corrected_output_devices",
+ (int64_t)(mIsMsdDevice ? AUDIO_DEVICE_OUT_BUS // turn on by default for MSD
+ : AUDIO_DEVICE_NONE));
+ }
+
// ++ operator does not compile
for (audio_stream_type_t stream = AUDIO_STREAM_MIN; stream < AUDIO_STREAM_FOR_POLICY_CNT;
stream = (audio_stream_type_t) (stream + 1)) {
@@ -3248,6 +3260,21 @@
mTimestampVerifier.add(timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
mSampleRate);
+
+ if (isTimestampCorrectionEnabled()) {
+ ALOGV("TS_BEFORE: %d %lld %lld", id(),
+ (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
+ (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
+ auto correctedTimestamp = mTimestampVerifier.getLastCorrectedTimestamp();
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
+ = correctedTimestamp.mFrames;
+ timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]
+ = correctedTimestamp.mTimeNs;
+ ALOGV("TS_AFTER: %d %lld %lld", id(),
+ (long long)timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
+ (long long)timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]);
+ }
+
// We always fetch the timestamp here because often the downstream
// sink will block while writing.
@@ -6368,8 +6395,20 @@
snprintf(mThreadName, kThreadNameLength, "AudioIn_%X", id);
mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
+ if (mInput != nullptr && mInput->audioHwDev != nullptr) {
+ mIsMsdDevice = strcmp(
+ mInput->audioHwDev->moduleName(), AUDIO_HARDWARE_MODULE_ID_MSD) == 0;
+ }
+
readInputParameters_l();
+ // TODO: We may also match on address as well as device type for
+ // AUDIO_DEVICE_IN_BUS, AUDIO_DEVICE_IN_BLUETOOTH_A2DP, AUDIO_DEVICE_IN_REMOTE_SUBMIX
+ mTimestampCorrectedDevices = (audio_devices_t)property_get_int64(
+ "audio.timestamp.corrected_input_devices",
+ (int64_t)(mIsMsdDevice ? AUDIO_DEVICE_IN_BUS // turn on by default for MSD
+ : AUDIO_DEVICE_NONE));
+
// create an NBAIO source for the HAL input stream, and negotiate
mInputSource = new AudioStreamInSource(input->stream);
size_t numCounterOffers = 0;
@@ -6804,7 +6843,22 @@
int64_t position, time;
if (mStandby) {
mTimestampVerifier.discontinuity();
- } else if (mInput->stream->getCapturePosition(&position, &time) == NO_ERROR) {
+ } else if (mInput->stream->getCapturePosition(&position, &time) == NO_ERROR
+ && time > mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL]) {
+
+ mTimestampVerifier.add(position, time, mSampleRate);
+
+ // Correct timestamps
+ if (isTimestampCorrectionEnabled()) {
+ ALOGV("TS_BEFORE: %d %lld %lld",
+ id(), (long long)time, (long long)position);
+ auto correctedTimestamp = mTimestampVerifier.getLastCorrectedTimestamp();
+ position = correctedTimestamp.mFrames;
+ time = correctedTimestamp.mTimeNs;
+ ALOGV("TS_AFTER: %d %lld %lld",
+ id(), (long long)time, (long long)position);
+ }
+
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = position;
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] = time;
// Note: In general record buffers should tend to be empty in
@@ -6812,10 +6866,6 @@
//
// Also, it is not advantageous to call get_presentation_position during the read
// as the read obtains a lock, preventing the timestamp call from executing.
-
- mTimestampVerifier.add(mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL],
- mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL],
- mSampleRate);
} else {
mTimestampVerifier.error();
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 705efbc..37b3870 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -393,6 +393,10 @@
void broadcast_l();
+ virtual bool isTimestampCorrectionEnabled() const { return false; }
+
+ bool isMsdDevice() const { return mIsMsdDevice; }
+
mutable Mutex mLock;
protected:
@@ -501,7 +505,8 @@
ExtendedTimestamp mTimestamp;
TimestampVerifier< // For timestamp statistics.
int64_t /* frame count */, int64_t /* time ns */> mTimestampVerifier;
-
+ audio_devices_t mTimestampCorrectedDevices = AUDIO_DEVICE_NONE;
+ bool mIsMsdDevice = false;
// A condition that must be evaluated by the thread loop has changed and
// we must not wait for async write callback in the thread loop before evaluating it
bool mSignalPending;
@@ -816,6 +821,11 @@
&& mTracks.size() < PlaybackThread::kMaxTracks;
}
+ bool isTimestampCorrectionEnabled() const override {
+ const audio_devices_t device =
+ mOutDevice & mTimestampCorrectedDevices;
+ return audio_is_output_devices(device) && popcount(device) > 0;
+ }
protected:
// updated by readOutputParameters_l()
size_t mNormalFrameCount; // normal mixer and effects
@@ -1532,6 +1542,11 @@
bool fastTrackAvailable() const { return mFastTrackAvail; }
+ bool isTimestampCorrectionEnabled() const override {
+ // checks popcount for exactly one device.
+ return audio_is_input_device(
+ mInDevice & mTimestampCorrectedDevices);
+ }
private:
// Enter standby if not already in standby, and set mStandby flag
void standbyIfNotAlreadyInStandby();