From 10fc96386edfa98fea9c5a2a35146f9a2d1efe31 Mon Sep 17 00:00:00 2001 From: Mikhail Naganov Date: Wed, 21 Aug 2024 11:30:21 -0700 Subject: [PATCH] audio: Implement more accurate timing for the stub stream Stub output stream is like a /dev/null audio device, however for synchronous transfers it must block for the duration of the audio chunk being transferred. Implement more accurate accounting for the blocking time using the same approach as employed by the remote submix stream implementation. Bug: 356719263 Test: atest CtsNativeMediaAAudioTestCases on aosp_cf_x86_64_auto target Change-Id: I137aed397246bcf2b5ef6789aa4d2d27ead64467 --- .../default/include/core-impl/StreamStub.h | 4 ++++ audio/aidl/default/stub/StreamStub.cpp | 24 ++++++++++++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/audio/aidl/default/include/core-impl/StreamStub.h b/audio/aidl/default/include/core-impl/StreamStub.h index f4ee566110..22b20202c5 100644 --- a/audio/aidl/default/include/core-impl/StreamStub.h +++ b/audio/aidl/default/include/core-impl/StreamStub.h @@ -44,6 +44,10 @@ class StreamStub : public StreamCommonImpl { const bool mIsInput; bool mIsInitialized = false; // Used for validating the state machine logic. bool mIsStandby = true; // Used for validating the state machine logic. + + // Used by the worker thread. + int64_t mStartTimeNs = 0; + long mFramesSinceStart = 0; }; class StreamInStub final : public StreamIn, public StreamStub { diff --git a/audio/aidl/default/stub/StreamStub.cpp b/audio/aidl/default/stub/StreamStub.cpp index 3b6a85aa68..a3d99a8873 100644 --- a/audio/aidl/default/stub/StreamStub.cpp +++ b/audio/aidl/default/stub/StreamStub.cpp @@ -83,7 +83,6 @@ StreamStub::~StreamStub() { if (!mIsInitialized) { LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; } - usleep(500); mIsStandby = true; return ::android::OK; } @@ -92,8 +91,9 @@ StreamStub::~StreamStub() { if (!mIsInitialized) { LOG(FATAL) << __func__ << ": must not happen for an uninitialized driver"; } - usleep(500); mIsStandby = false; + mStartTimeNs = ::android::uptimeNanos(); + mFramesSinceStart = 0; return ::android::OK; } @@ -105,14 +105,23 @@ StreamStub::~StreamStub() { if (mIsStandby) { LOG(FATAL) << __func__ << ": must not happen while in standby"; } - static constexpr float kMicrosPerSecond = MICROS_PER_SECOND; - static constexpr float kScaleFactor = .8f; + *actualFrameCount = frameCount; if (mIsAsynchronous) { usleep(500); } else { - const size_t delayUs = static_cast( - std::roundf(kScaleFactor * frameCount * kMicrosPerSecond / mSampleRate)); - usleep(delayUs); + mFramesSinceStart += *actualFrameCount; + const long bufferDurationUs = + (*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate(); + const auto totalDurationUs = + (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND; + const long totalOffsetUs = + mFramesSinceStart * MICROS_PER_SECOND / mContext.getSampleRate() - totalDurationUs; + LOG(VERBOSE) << __func__ << ": totalOffsetUs " << totalOffsetUs; + if (totalOffsetUs > 0) { + const long sleepTimeUs = std::min(totalOffsetUs, bufferDurationUs); + LOG(VERBOSE) << __func__ << ": sleeping for " << sleepTimeUs << " us"; + usleep(sleepTimeUs); + } } if (mIsInput) { uint8_t* byteBuffer = static_cast(buffer); @@ -120,7 +129,6 @@ StreamStub::~StreamStub() { byteBuffer[i] = std::rand() % 255; } } - *actualFrameCount = frameCount; return ::android::OK; }