mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 13:49:45 +00:00
audio: Implement blocking in remote submix when there is no sink am: a41ff5134d
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/3009658 Change-Id: Ie71efa7ec303bb311b546e28db3d71b428c46c76 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -55,8 +55,8 @@ class StreamRemoteSubmix : public StreamCommonImpl {
|
|||||||
r_submix::AudioConfig mStreamConfig;
|
r_submix::AudioConfig mStreamConfig;
|
||||||
std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
|
std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
|
||||||
|
|
||||||
// limit for number of read error log entries to avoid spamming the logs
|
// Limit for the number of error log entries to avoid spamming the logs.
|
||||||
static constexpr int kMaxReadErrorLogs = 5;
|
static constexpr int kMaxErrorLogs = 5;
|
||||||
// The duration of kMaxReadFailureAttempts * READ_ATTEMPT_SLEEP_MS must be strictly inferior
|
// The duration of kMaxReadFailureAttempts * READ_ATTEMPT_SLEEP_MS must be strictly inferior
|
||||||
// to the duration of a record buffer at the current record sample rate (of the device, not of
|
// to the duration of a record buffer at the current record sample rate (of the device, not of
|
||||||
// the recording itself). Here we have: 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms
|
// the recording itself). Here we have: 3 * 5ms = 15ms < 1024 frames * 1000 / 48000 = 21.333ms
|
||||||
@@ -68,6 +68,7 @@ class StreamRemoteSubmix : public StreamCommonImpl {
|
|||||||
long mFramesSinceStart = 0;
|
long mFramesSinceStart = 0;
|
||||||
int mReadErrorCount = 0;
|
int mReadErrorCount = 0;
|
||||||
int mReadFailureCount = 0;
|
int mReadFailureCount = 0;
|
||||||
|
int mWriteShutdownCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StreamInRemoteSubmix final : public StreamIn, public StreamSwitcher {
|
class StreamInRemoteSubmix final : public StreamIn, public StreamSwitcher {
|
||||||
|
|||||||
@@ -134,11 +134,16 @@ void StreamRemoteSubmix::shutdown() {
|
|||||||
*latencyMs = getDelayInUsForFrameCount(getStreamPipeSizeInFrames()) / 1000;
|
*latencyMs = getDelayInUsForFrameCount(getStreamPipeSizeInFrames()) / 1000;
|
||||||
LOG(VERBOSE) << __func__ << ": Latency " << *latencyMs << "ms";
|
LOG(VERBOSE) << __func__ << ": Latency " << *latencyMs << "ms";
|
||||||
mCurrentRoute->exitStandby(mIsInput);
|
mCurrentRoute->exitStandby(mIsInput);
|
||||||
RETURN_STATUS_IF_ERROR(mIsInput ? inRead(buffer, frameCount, actualFrameCount)
|
::android::status_t status = mIsInput ? inRead(buffer, frameCount, actualFrameCount)
|
||||||
: outWrite(buffer, frameCount, actualFrameCount));
|
: outWrite(buffer, frameCount, actualFrameCount);
|
||||||
|
if ((status != ::android::OK && mIsInput) ||
|
||||||
|
((status != ::android::OK && status != ::android::DEAD_OBJECT) && !mIsInput)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
mFramesSinceStart += *actualFrameCount;
|
mFramesSinceStart += *actualFrameCount;
|
||||||
if (!mIsInput) return ::android::OK;
|
if (!mIsInput && status != ::android::DEAD_OBJECT) return ::android::OK;
|
||||||
// Only input streams need to block, for output this is implemented by MonoPipe.
|
// Input streams always need to block, output streams need to block when there is no sink.
|
||||||
|
// When the sink exists, more sophisticated blocking algorithm is implemented by MonoPipe.
|
||||||
const long bufferDurationUs =
|
const long bufferDurationUs =
|
||||||
(*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
|
(*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
|
||||||
const auto totalDurationUs = (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
|
const auto totalDurationUs = (::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
|
||||||
@@ -188,14 +193,17 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
|||||||
if (sink != nullptr) {
|
if (sink != nullptr) {
|
||||||
if (sink->isShutdown()) {
|
if (sink->isShutdown()) {
|
||||||
sink.clear();
|
sink.clear();
|
||||||
LOG(DEBUG) << __func__ << ": pipe shutdown, ignoring the write";
|
if (++mWriteShutdownCount < kMaxErrorLogs) {
|
||||||
|
LOG(DEBUG) << __func__ << ": pipe shutdown, ignoring the write. (limited logging)";
|
||||||
|
}
|
||||||
*actualFrameCount = frameCount;
|
*actualFrameCount = frameCount;
|
||||||
return ::android::OK;
|
return ::android::DEAD_OBJECT; // Induce wait in `transfer`.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG(FATAL) << __func__ << ": without a pipe!";
|
LOG(FATAL) << __func__ << ": without a pipe!";
|
||||||
return ::android::UNKNOWN_ERROR;
|
return ::android::UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
mWriteShutdownCount = 0;
|
||||||
|
|
||||||
LOG(VERBOSE) << __func__ << ": " << mDeviceAddress.toString() << ", " << frameCount
|
LOG(VERBOSE) << __func__ << ": " << mDeviceAddress.toString() << ", " << frameCount
|
||||||
<< " frames";
|
<< " frames";
|
||||||
@@ -262,7 +270,7 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
|||||||
// about to read from audio source
|
// about to read from audio source
|
||||||
sp<MonoPipeReader> source = mCurrentRoute->getSource();
|
sp<MonoPipeReader> source = mCurrentRoute->getSource();
|
||||||
if (source == nullptr) {
|
if (source == nullptr) {
|
||||||
if (++mReadErrorCount < kMaxReadErrorLogs) {
|
if (++mReadErrorCount < kMaxErrorLogs) {
|
||||||
LOG(ERROR) << __func__
|
LOG(ERROR) << __func__
|
||||||
<< ": no audio pipe yet we're trying to read! (not all errors will be "
|
<< ": no audio pipe yet we're trying to read! (not all errors will be "
|
||||||
"logged)";
|
"logged)";
|
||||||
|
|||||||
Reference in New Issue
Block a user