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
This commit is contained in:
Mikhail Naganov
2024-08-21 11:30:21 -07:00
parent c818adc8d4
commit 10fc96386e
2 changed files with 20 additions and 8 deletions

View File

@@ -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 {

View File

@@ -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<size_t>(
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<uint8_t*>(buffer);
@@ -120,7 +129,6 @@ StreamStub::~StreamStub() {
byteBuffer[i] = std::rand() % 255;
}
}
*actualFrameCount = frameCount;
return ::android::OK;
}