Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c63a7f81 authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Automerger Merge Worker
Browse files

Merge "audio: Adjust default impl for non-RT audio behavior of AVD" into main am: 8062a773

parents e12f4b76 8062a773
Loading
Loading
Loading
Loading
+5 −0
Original line number Original line Diff line number Diff line
@@ -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 {
+42 −17
Original line number Original line Diff line number Diff line
@@ -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;
}
}