Merge "audio: Adjust default impl for non-RT audio behavior of AVD" into main am: 8062a77307
am: 3bb96fe48b
am: ccbb3e1ad7
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2836447 Change-Id: Ic8ea353189b17d77be70906fce8ebc1e0553f1a7 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
b6c97c04a3
2 changed files with 48 additions and 18 deletions
|
@ -27,13 +27,18 @@ class StreamPrimary : public StreamAlsa {
|
|||
public:
|
||||
StreamPrimary(StreamContext* context, const Metadata& metadata);
|
||||
|
||||
::android::status_t start() override;
|
||||
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
|
||||
int32_t* latencyMs) override;
|
||||
::android::status_t refinePosition(StreamDescriptor::Position* position) override;
|
||||
|
||||
protected:
|
||||
std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
|
||||
|
||||
const bool mIsAsynchronous;
|
||||
long mStartTimeNs = 0;
|
||||
long mFramesSinceStart = 0;
|
||||
bool mSkipNextTransfer = false;
|
||||
};
|
||||
|
||||
class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
|
||||
|
|
|
@ -14,12 +14,11 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#define LOG_TAG "AHAL_StreamPrimary"
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <audio_utils/clock.h>
|
||||
#include <error/Result.h>
|
||||
#include <error/expected_utils.h>
|
||||
|
||||
#include "PrimaryMixer.h"
|
||||
|
@ -43,26 +42,52 @@ StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
|
|||
context->startStreamDataProcessor();
|
||||
}
|
||||
|
||||
::android::status_t StreamPrimary::start() {
|
||||
RETURN_STATUS_IF_ERROR(StreamAlsa::start());
|
||||
mStartTimeNs = ::android::uptimeNanos();
|
||||
mFramesSinceStart = 0;
|
||||
mSkipNextTransfer = false;
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamPrimary::transfer(void* buffer, size_t frameCount,
|
||||
size_t* actualFrameCount, int32_t* latencyMs) {
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
if (auto status = StreamAlsa::transfer(buffer, frameCount, actualFrameCount, latencyMs);
|
||||
status != ::android::OK) {
|
||||
return status;
|
||||
}
|
||||
// This is a workaround for the emulator implementation which has a host-side buffer
|
||||
// and this can result in reading faster than real time.
|
||||
if (mIsInput && !mIsAsynchronous) {
|
||||
auto recordDurationUs = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::steady_clock::now() - start);
|
||||
const long projectedVsObservedOffsetUs =
|
||||
*actualFrameCount * MICROS_PER_SECOND / mContext.getSampleRate() -
|
||||
recordDurationUs.count();
|
||||
if (projectedVsObservedOffsetUs > 0) {
|
||||
LOG(VERBOSE) << __func__ << ": sleeping for " << projectedVsObservedOffsetUs << " us";
|
||||
usleep(projectedVsObservedOffsetUs);
|
||||
// and is not being able to achieve real-time behavior similar to ADSPs (b/302587331).
|
||||
if (!mSkipNextTransfer) {
|
||||
RETURN_STATUS_IF_ERROR(
|
||||
StreamAlsa::transfer(buffer, frameCount, actualFrameCount, latencyMs));
|
||||
} else {
|
||||
LOG(DEBUG) << __func__ << ": skipping transfer (" << frameCount << " frames)";
|
||||
*actualFrameCount = frameCount;
|
||||
if (mIsInput) memset(buffer, 0, frameCount);
|
||||
mSkipNextTransfer = false;
|
||||
}
|
||||
if (!mIsAsynchronous) {
|
||||
const long bufferDurationUs =
|
||||
(*actualFrameCount) * MICROS_PER_SECOND / mContext.getSampleRate();
|
||||
const auto totalDurationUs =
|
||||
(::android::uptimeNanos() - mStartTimeNs) / NANOS_PER_MICROSECOND;
|
||||
mFramesSinceStart += *actualFrameCount;
|
||||
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);
|
||||
} else {
|
||||
mSkipNextTransfer = true;
|
||||
}
|
||||
} else {
|
||||
LOG(VERBOSE) << __func__ << ": asynchronous transfer";
|
||||
}
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
::android::status_t StreamPrimary::refinePosition(StreamDescriptor::Position*) {
|
||||
// Since not all data is actually sent to the HAL, use the position maintained by Stream class
|
||||
// which accounts for all frames passed from / to the client.
|
||||
return ::android::OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue