diff options
Diffstat (limited to 'services')
-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); |