diff options
| -rw-r--r-- | services/audioflinger/AudioStreamOut.cpp | 85 | ||||
| -rw-r--r-- | services/audioflinger/AudioStreamOut.h | 13 | ||||
| -rw-r--r-- | services/audioflinger/SpdifStreamOut.cpp | 47 | ||||
| -rw-r--r-- | services/audioflinger/SpdifStreamOut.h | 9 | 
4 files changed, 87 insertions, 67 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 diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h index e91ca9c..761e771 100644 --- a/services/audioflinger/AudioStreamOut.h +++ b/services/audioflinger/AudioStreamOut.h @@ -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 diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp index ac637ef..6af7bce 100644 --- a/services/audioflinger/SpdifStreamOut.cpp +++ b/services/audioflinger/SpdifStreamOut.cpp @@ -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); diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/SpdifStreamOut.h index d81c064..a61a7bd 100644 --- a/services/audioflinger/SpdifStreamOut.h +++ b/services/audioflinger/SpdifStreamOut.h @@ -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);  | 
