diff options
Diffstat (limited to 'services/audioflinger/AudioStreamOut.cpp')
| -rw-r--r-- | services/audioflinger/AudioStreamOut.cpp | 85 | 
1 files changed, 75 insertions, 10 deletions
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp index e6d8f09..f953cc8 100644 --- a/services/audioflinger/AudioStreamOut.cpp +++ b/services/audioflinger/AudioStreamOut.cpp @@ -27,25 +27,59 @@  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)  {  } -audio_hw_device_t* AudioStreamOut::hwDev() const +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( @@ -62,7 +115,7 @@ status_t AudioStreamOut::open(          struct audio_config *config,          const char *address)  { -    audio_stream_out_t* outStream; +    audio_stream_out_t *outStream;      int status = hwDev()->open_output_stream(              hwDev(),              handle, @@ -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  | 
