summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorPhil Burk <philburk@google.com>2015-07-08 17:56:23 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-07-08 17:56:24 +0000
commit47f986637d7b4d63abe0ab9e1cf6eb23766c6669 (patch)
tree0b5a7b383a6104096a3be059b51df4e11ea9bb7c /services
parent065f6572752dca646b7d60df8e80b6d4ac159281 (diff)
parent90eea7631b07117e46ae8b84889a2baa3eee7aea (diff)
downloadframeworks_av-47f986637d7b4d63abe0ab9e1cf6eb23766c6669.zip
frameworks_av-47f986637d7b4d63abe0ab9e1cf6eb23766c6669.tar.gz
frameworks_av-47f986637d7b4d63abe0ab9e1cf6eb23766c6669.tar.bz2
Merge "AudioFlinger: reset frame position on standby" into mnc-dev
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/AudioStreamOut.cpp85
-rw-r--r--services/audioflinger/AudioStreamOut.h13
-rw-r--r--services/audioflinger/SpdifStreamOut.cpp47
-rw-r--r--services/audioflinger/SpdifStreamOut.h9
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);