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

Commit 47f98663 authored by Phil Burk's avatar Phil Burk Committed by Android (Google) Code Review
Browse files

Merge "AudioFlinger: reset frame position on standby" into mnc-dev

parents 065f6572 90eea763
Loading
Loading
Loading
Loading
+75 −10
Original line number Diff line number Diff line
@@ -27,11 +27,16 @@
namespace android {

// ----------------------------------------------------------------------------

AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags)
        : audioHwDev(dev)
        , stream(NULL)
        , flags(flags)
        , mFramesWritten(0)
        , mFramesWrittenAtStandby(0)
        , mRenderPosition(0)
        , mRateMultiplier(1)
        , mHalFormatIsLinearPcm(false)
        , mHalFrameSize(0)
{
}

@@ -40,12 +45,41 @@ audio_hw_device_t* AudioStreamOut::hwDev() const
    return audioHwDev->hwDevice();
}

status_t AudioStreamOut::getRenderPosition(uint32_t *frames)
status_t AudioStreamOut::getRenderPosition(uint64_t *frames)
{
    if (stream == NULL) {
        return NO_INIT;
    }
    return stream->get_render_position(stream, frames);

    uint32_t halPosition = 0;
    status_t status = stream->get_render_position(stream, &halPosition);
    if (status != NO_ERROR) {
        return status;
    }

    // Maintain a 64-bit render position using the 32-bit result from the HAL.
    // This delta calculation relies on the arithmetic overflow behavior
    // of integers. For example (100 - 0xFFFFFFF0) = 116.
    uint32_t truncatedPosition = (uint32_t)mRenderPosition;
    int32_t deltaHalPosition = (int32_t)(halPosition - truncatedPosition);
    if (deltaHalPosition > 0) {
        mRenderPosition += deltaHalPosition;
    }
    // Scale from HAL sample rate to application rate.
    *frames = mRenderPosition / mRateMultiplier;

    return status;
}

// return bottom 32-bits of the render position
status_t AudioStreamOut::getRenderPosition(uint32_t *frames)
{
    uint64_t position64 = 0;
    status_t status = getRenderPosition(&position64);
    if (status == NO_ERROR) {
        *frames = (uint32_t)position64;
    }
    return status;
}

status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timespec *timestamp)
@@ -53,7 +87,26 @@ status_t AudioStreamOut::getPresentationPosition(uint64_t *frames, struct timesp
    if (stream == NULL) {
        return NO_INIT;
    }
    return stream->get_presentation_position(stream, frames, timestamp);

    uint64_t halPosition = 0;
    status_t status = stream->get_presentation_position(stream, &halPosition, timestamp);
    if (status != NO_ERROR) {
        return status;
    }

    // Adjust for standby using HAL rate frames.
    // Only apply this correction if the HAL is getting PCM frames.
    if (mHalFormatIsLinearPcm) {
        uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
                0 : (halPosition - mFramesWrittenAtStandby);
        // Scale from HAL sample rate to application rate.
        *frames = adjustedPosition / mRateMultiplier;
    } else {
        // For offloaded MP3 and other compressed formats.
        *frames = halPosition;
    }

    return status;
}

status_t AudioStreamOut::open(
@@ -82,6 +135,9 @@ status_t AudioStreamOut::open(

    if (status == NO_ERROR) {
        stream = outStream;
        mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format);
        ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm);
        mHalFrameSize = audio_stream_out_frame_size(stream);
    }

    return status;
@@ -89,13 +145,15 @@ status_t AudioStreamOut::open(

size_t AudioStreamOut::getFrameSize()
{
    ALOG_ASSERT(stream != NULL);
    return audio_stream_out_frame_size(stream);
    return mHalFrameSize;
}

int AudioStreamOut::flush()
{
    ALOG_ASSERT(stream != NULL);
    mRenderPosition = 0;
    mFramesWritten = 0;
    mFramesWrittenAtStandby = 0;
    if (stream->flush != NULL) {
        return stream->flush(stream);
    }
@@ -105,13 +163,20 @@ int AudioStreamOut::flush()
int AudioStreamOut::standby()
{
    ALOG_ASSERT(stream != NULL);
    mRenderPosition = 0;
    mFramesWrittenAtStandby = mFramesWritten;
    ALOGI("AudioStreamOut::standby(), mFramesWrittenAtStandby = %llu", mFramesWrittenAtStandby);
    return stream->common.standby(&stream->common);
}

ssize_t AudioStreamOut::write(const void* buffer, size_t bytes)
ssize_t AudioStreamOut::write(const void *buffer, size_t numBytes)
{
    ALOG_ASSERT(stream != NULL);
    return stream->write(stream, buffer, bytes);
    ssize_t bytesWritten = stream->write(stream, buffer, numBytes);
    if (bytesWritten > 0 && mHalFrameSize > 0) {
        mFramesWritten += bytesWritten / mHalFrameSize;
    }
    return bytesWritten;
}

} // namespace android
+12 −1
Original line number Diff line number Diff line
@@ -53,7 +53,10 @@ public:

    virtual ~AudioStreamOut() { }

    virtual status_t getRenderPosition(uint32_t *frames);
    // Get the bottom 32-bits of the 64-bit render position.
    status_t getRenderPosition(uint32_t *frames);

    virtual status_t getRenderPosition(uint64_t *frames);

    virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);

@@ -76,6 +79,14 @@ public:

    virtual status_t flush();
    virtual status_t standby();

protected:
    uint64_t             mFramesWritten; // reset by flush
    uint64_t             mFramesWrittenAtStandby;
    uint64_t             mRenderPosition; // reset by flush or standby
    int                  mRateMultiplier;
    bool                 mHalFormatIsLinearPcm;
    size_t               mHalFrameSize;
};

} // namespace android
+0 −47
Original line number Diff line number Diff line
@@ -36,10 +36,7 @@ SpdifStreamOut::SpdifStreamOut(AudioHwDevice *dev,
            audio_output_flags_t flags,
            audio_format_t format)
        : AudioStreamOut(dev,flags)
        , mRateMultiplier(1)
        , mSpdifEncoder(this, format)
        , mRenderPositionHal(0)
        , mPreviousHalPosition32(0)
{
}

@@ -97,62 +94,18 @@ status_t SpdifStreamOut::open(
    return status;
}

// Account for possibly higher sample rate.
status_t SpdifStreamOut::getRenderPosition(uint32_t *frames)
{
    uint32_t halPosition = 0;
    status_t status = AudioStreamOut::getRenderPosition(&halPosition);
    if (status != NO_ERROR) {
        return status;
    }

    // Accumulate a 64-bit position so that we wrap at the right place.
    if (mRateMultiplier != 1) {
        // Maintain a 64-bit render position.
        int32_t deltaHalPosition = (int32_t)(halPosition - mPreviousHalPosition32);
        mPreviousHalPosition32 = halPosition;
        mRenderPositionHal += deltaHalPosition;

        // Scale from device sample rate to application rate.
        uint64_t renderPositionApp = mRenderPositionHal / mRateMultiplier;
        ALOGV("SpdifStreamOut::getRenderPosition() "
            "renderPositionAppRate = %llu = %llu / %u\n",
            renderPositionApp, mRenderPositionHal, mRateMultiplier);

        *frames = (uint32_t)renderPositionApp;
    } else {
        *frames = halPosition;
    }
    return status;
}

int SpdifStreamOut::flush()
{
    mSpdifEncoder.reset();
    mRenderPositionHal = 0;
    mPreviousHalPosition32 = 0;
    return AudioStreamOut::flush();
}

int SpdifStreamOut::standby()
{
    mSpdifEncoder.reset();
    mRenderPositionHal = 0;
    mPreviousHalPosition32 = 0;
    return AudioStreamOut::standby();
}

// Account for possibly higher sample rate.
// This is much easier when all the values are 64-bit.
status_t SpdifStreamOut::getPresentationPosition(uint64_t *frames,
        struct timespec *timestamp)
{
    uint64_t halFrames = 0;
    status_t status = AudioStreamOut::getPresentationPosition(&halFrames, timestamp);
    *frames = halFrames / mRateMultiplier;
    return status;
}

size_t SpdifStreamOut::getFrameSize()
{
    return sizeof(int8_t);
+0 −9
Original line number Diff line number Diff line
@@ -49,10 +49,6 @@ public:
            struct audio_config *config,
            const char *address);

    virtual status_t getRenderPosition(uint32_t *frames);

    virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);

    /**
    * Write audio buffer to driver. Returns number of bytes written, or a
    * negative status_t. If at least one frame was written successfully prior to the error,
@@ -92,13 +88,8 @@ private:
        SpdifStreamOut * const mSpdifStreamOut;
    };

    int                  mRateMultiplier;
    MySPDIFEncoder       mSpdifEncoder;

    // Used to implement getRenderPosition()
    int64_t              mRenderPositionHal;
    uint32_t             mPreviousHalPosition32;

    ssize_t  writeDataBurst(const void* data, size_t bytes);
    ssize_t  writeInternal(const void* buffer, size_t bytes);