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:
|
public:
|
||||||
StreamPrimary(StreamContext* context, const Metadata& metadata);
|
StreamPrimary(StreamContext* context, const Metadata& metadata);
|
||||||
|
|
||||||
|
::android::status_t start() override;
|
||||||
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
|
::android::status_t transfer(void* buffer, size_t frameCount, size_t* actualFrameCount,
|
||||||
int32_t* latencyMs) override;
|
int32_t* latencyMs) override;
|
||||||
|
::android::status_t refinePosition(StreamDescriptor::Position* position) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
|
std::vector<alsa::DeviceProfile> getDeviceProfiles() override;
|
||||||
|
|
||||||
const bool mIsAsynchronous;
|
const bool mIsAsynchronous;
|
||||||
|
long mStartTimeNs = 0;
|
||||||
|
long mFramesSinceStart = 0;
|
||||||
|
bool mSkipNextTransfer = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
|
class StreamInPrimary final : public StreamIn, public StreamSwitcher, public StreamInHwGainHelper {
|
||||||
|
|
|
@ -14,12 +14,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#define LOG_TAG "AHAL_StreamPrimary"
|
#define LOG_TAG "AHAL_StreamPrimary"
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
#include <android-base/properties.h>
|
#include <android-base/properties.h>
|
||||||
#include <audio_utils/clock.h>
|
#include <audio_utils/clock.h>
|
||||||
|
#include <error/Result.h>
|
||||||
#include <error/expected_utils.h>
|
#include <error/expected_utils.h>
|
||||||
|
|
||||||
#include "PrimaryMixer.h"
|
#include "PrimaryMixer.h"
|
||||||
|
@ -43,26 +42,52 @@ StreamPrimary::StreamPrimary(StreamContext* context, const Metadata& metadata)
|
||||||
context->startStreamDataProcessor();
|
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,
|
::android::status_t StreamPrimary::transfer(void* buffer, size_t frameCount,
|
||||||
size_t* actualFrameCount, int32_t* latencyMs) {
|
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
|
// This is a workaround for the emulator implementation which has a host-side buffer
|
||||||
// and this can result in reading faster than real time.
|
// and is not being able to achieve real-time behavior similar to ADSPs (b/302587331).
|
||||||
if (mIsInput && !mIsAsynchronous) {
|
if (!mSkipNextTransfer) {
|
||||||
auto recordDurationUs = std::chrono::duration_cast<std::chrono::microseconds>(
|
RETURN_STATUS_IF_ERROR(
|
||||||
std::chrono::steady_clock::now() - start);
|
StreamAlsa::transfer(buffer, frameCount, actualFrameCount, latencyMs));
|
||||||
const long projectedVsObservedOffsetUs =
|
} else {
|
||||||
*actualFrameCount * MICROS_PER_SECOND / mContext.getSampleRate() -
|
LOG(DEBUG) << __func__ << ": skipping transfer (" << frameCount << " frames)";
|
||||||
recordDurationUs.count();
|
*actualFrameCount = frameCount;
|
||||||
if (projectedVsObservedOffsetUs > 0) {
|
if (mIsInput) memset(buffer, 0, frameCount);
|
||||||
LOG(VERBOSE) << __func__ << ": sleeping for " << projectedVsObservedOffsetUs << " us";
|
mSkipNextTransfer = false;
|
||||||
usleep(projectedVsObservedOffsetUs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
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;
|
return ::android::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue