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

Commit 7328a80f authored by Phil Burk's avatar Phil Burk
Browse files

aaudio: prevent retrograde motion in Legacy timestamps

Use MonotonicCounter for timestamp position.

Bug: 63918065
Test: write_sine_callback.cpp and test_timestamps.cpp
Change-Id: Iea58384e2d96adcfad586e8c522024baaecccb8c
parent 187dcd4e
Loading
Loading
Loading
Loading
+36 −13
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <utils/String16.h>
#include <media/AudioTrack.h>
#include <media/AudioTimestamp.h>
#include <aaudio/AAudio.h>

#include "core/AudioStream.h"
@@ -46,16 +47,32 @@ aaudio_legacy_callback_t AudioStreamLegacy::getLegacyCallback() {
    return AudioStreamLegacy_callback;
}

// Implement FixedBlockProcessor
int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
    int32_t frameCount = numBytes / getBytesPerFrame();
int32_t AudioStreamLegacy::callDataCallbackFrames(uint8_t *buffer, int32_t numFrames) {
    if (getDirection() == AAUDIO_DIRECTION_INPUT) {
        // Increment before because we already got the data from the device.
        incrementFramesRead(numFrames);
    }

    // Call using the AAudio callback interface.
    AAudioStream_dataCallback appCallback = getDataCallbackProc();
    return (*appCallback)(
    aaudio_data_callback_result_t callbackResult = (*appCallback)(
            (AAudioStream *) this,
            getDataCallbackUserData(),
            buffer,
            frameCount);
            numFrames);

    if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE
            && getDirection() == AAUDIO_DIRECTION_OUTPUT) {
        // Increment after because we are going to write the data to the device.
        incrementFramesWritten(numFrames);
    }
    return callbackResult;
}

// Implement FixedBlockProcessor
int32_t AudioStreamLegacy::onProcessFixedBlock(uint8_t *buffer, int32_t numBytes) {
    int32_t numFrames = numBytes / getBytesPerFrame();
    return callDataCallbackFrames(buffer, numFrames);
}

void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode, void *info) {
@@ -81,16 +98,11 @@ void AudioStreamLegacy::processCallbackCommon(aaudio_callback_operation_t opcode
                            (uint8_t *) audioBuffer->raw, byteCount);
                } else {
                    // Call using the AAudio callback interface.
                    callbackResult = (*getDataCallbackProc())(
                            (AAudioStream *) this,
                            getDataCallbackUserData(),
                            audioBuffer->raw,
                            audioBuffer->frameCount
                            );
                    callbackResult = callDataCallbackFrames((uint8_t *)audioBuffer->raw,
                                                            audioBuffer->frameCount);
                }
                if (callbackResult == AAUDIO_CALLBACK_RESULT_CONTINUE) {
                    audioBuffer->size = audioBuffer->frameCount * getBytesPerFrame();
                    incrementClientFrameCounter(audioBuffer->frameCount);
                } else {
                    audioBuffer->size = 0;
                }
@@ -139,7 +151,18 @@ aaudio_result_t AudioStreamLegacy::getBestTimestamp(clockid_t clockId,
            return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
            break;
    }
    status_t status = extendedTimestamp->getBestTimestamp(framePosition, timeNanoseconds, timebase);
    ExtendedTimestamp::Location location = ExtendedTimestamp::Location::LOCATION_INVALID;
    int64_t localPosition;
    status_t status = extendedTimestamp->getBestTimestamp(&localPosition, timeNanoseconds,
                                                          timebase, &location);
    // use MonotonicCounter to prevent retrograde motion.
    mTimestampPosition.update32((int32_t)localPosition);
    *framePosition = mTimestampPosition.get();

//    ALOGD("getBestTimestamp() fposition: server = %6lld, kernel = %6lld, location = %d",
//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_SERVER],
//          (long long) extendedTimestamp->mPosition[ExtendedTimestamp::Location::LOCATION_KERNEL],
//          (int)location);
    return AAudioConvert_androidToAAudioResult(status);
}

+3 −0
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ public:

    aaudio_legacy_callback_t getLegacyCallback();

    int32_t callDataCallbackFrames(uint8_t *buffer, int32_t numFrames);

    // This is public so it can be called from the C callback function.
    // This is called from the AudioTrack/AudioRecord client.
    virtual void processCallback(int event, void *info) = 0;
@@ -122,6 +124,7 @@ protected:

    MonotonicCounter           mFramesWritten;
    MonotonicCounter           mFramesRead;
    MonotonicCounter           mTimestampPosition;

    FixedBlockAdapter         *mBlockAdapter = nullptr;
    aaudio_wrapping_frames_t   mPositionWhenStarting = 0;
+2 −0
Original line number Diff line number Diff line
@@ -233,8 +233,10 @@ aaudio_result_t AudioStreamRecord::requestStop() {
    onStop();
    setState(AAUDIO_STREAM_STATE_STOPPING);
    incrementFramesWritten(getFramesRead() - getFramesWritten()); // TODO review
    mTimestampPosition.set(getFramesRead());
    mAudioRecord->stop();
    mFramesRead.reset32();
    mTimestampPosition.reset32();
    return AAUDIO_OK;
}

+17 −1
Original line number Diff line number Diff line
@@ -285,6 +285,7 @@ aaudio_result_t AudioStreamTrack::requestFlush() {
    incrementFramesRead(getFramesWritten() - getFramesRead());
    mAudioTrack->flush();
    mFramesWritten.reset32();
    mTimestampPosition.reset32();
    return AAUDIO_OK;
}

@@ -298,8 +299,10 @@ aaudio_result_t AudioStreamTrack::requestStop() {
    onStop();
    setState(AAUDIO_STREAM_STATE_STOPPING);
    incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
    mTimestampPosition.set(getFramesWritten());
    stop();
    mFramesWritten.reset32();
    mTimestampPosition.reset32();
    return AAUDIO_OK;
}

@@ -447,5 +450,18 @@ aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
    if (status != NO_ERROR) {
        return AAudioConvert_androidToAAudioResult(status);
    }
    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
    int64_t position = 0;
    int64_t nanoseconds = 0;
    aaudio_result_t result = getBestTimestamp(clockId, &position,
                                              &nanoseconds, &extendedTimestamp);
    if (result == AAUDIO_OK) {
        if (position < getFramesWritten()) {
            *framePosition = position;
            *timeNanoseconds = nanoseconds;
            return result;
        } else {
            return AAUDIO_ERROR_INVALID_STATE; // TODO review, documented but not consistent
        }
    }
    return result;
}
+7 −0
Original line number Diff line number Diff line
@@ -40,6 +40,13 @@ public:
        return mCounter64;
    }

    /**
     * set the current value of the counter
     */
    void set(int64_t counter) {
        mCounter64 = counter;
    }

    /**
     * Advance the counter if delta is positive.
     * @return current value of the counter