diff options
author | Phil Burk <philburk@google.com> | 2015-07-17 21:53:17 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-07-17 21:53:28 +0000 |
commit | b9f72ab0b0b7582e021d369e7179022f7be5b37d (patch) | |
tree | 24fde008d3dc114ba463b95d1905b4e6c0d78f15 /services/audioflinger | |
parent | dd761ecee86cc24ac8774bf1f004ea29b1e0d3f7 (diff) | |
parent | ca5e6143740299c877d69e97f7968cd04476d32c (diff) | |
download | frameworks_av-b9f72ab0b0b7582e021d369e7179022f7be5b37d.zip frameworks_av-b9f72ab0b0b7582e021d369e7179022f7be5b37d.tar.gz frameworks_av-b9f72ab0b0b7582e021d369e7179022f7be5b37d.tar.bz2 |
Merge "AudioFlinger: fix repeated underruns for compressed audio" into mnc-dev
Diffstat (limited to 'services/audioflinger')
-rw-r--r-- | services/audioflinger/AudioStreamOut.cpp | 15 | ||||
-rw-r--r-- | services/audioflinger/AudioStreamOut.h | 23 | ||||
-rw-r--r-- | services/audioflinger/SpdifStreamOut.cpp | 16 | ||||
-rw-r--r-- | services/audioflinger/SpdifStreamOut.h | 25 | ||||
-rw-r--r-- | services/audioflinger/Threads.cpp | 16 |
5 files changed, 79 insertions, 16 deletions
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp index f953cc8..b6d1be7 100644 --- a/services/audioflinger/AudioStreamOut.cpp +++ b/services/audioflinger/AudioStreamOut.cpp @@ -143,9 +143,19 @@ status_t AudioStreamOut::open( return status; } -size_t AudioStreamOut::getFrameSize() +audio_format_t AudioStreamOut::getFormat() const { - return mHalFrameSize; + return stream->common.get_format(&stream->common); +} + +uint32_t AudioStreamOut::getSampleRate() const +{ + return stream->common.get_sample_rate(&stream->common); +} + +audio_channel_mask_t AudioStreamOut::getChannelMask() const +{ + return stream->common.get_channels(&stream->common); } int AudioStreamOut::flush() @@ -165,7 +175,6 @@ int AudioStreamOut::standby() ALOG_ASSERT(stream != NULL); mRenderPosition = 0; mFramesWrittenAtStandby = mFramesWritten; - ALOGI("AudioStreamOut::standby(), mFramesWrittenAtStandby = %llu", mFramesWrittenAtStandby); return stream->common.standby(&stream->common); } diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h index 761e771..06a2277 100644 --- a/services/audioflinger/AudioStreamOut.h +++ b/services/audioflinger/AudioStreamOut.h @@ -75,7 +75,28 @@ public: */ virtual ssize_t write(const void *buffer, size_t bytes); - virtual size_t getFrameSize(); + /** + * @return frame size from the perspective of the application and the AudioFlinger. + */ + virtual size_t getFrameSize() const { return mHalFrameSize; } + + /** + * @return format from the perspective of the application and the AudioFlinger. + */ + virtual audio_format_t getFormat() const; + + /** + * The HAL may be running at a higher sample rate if, for example, playing wrapped EAC3. + * @return sample rate from the perspective of the application and the AudioFlinger. + */ + virtual uint32_t getSampleRate() const; + + /** + * The HAL is in stereo mode when playing multi-channel compressed audio over HDMI. + * @return channel mask from the perspective of the application and the AudioFlinger. + */ + virtual audio_channel_mask_t getChannelMask() const; + virtual status_t flush(); virtual status_t standby(); diff --git a/services/audioflinger/SpdifStreamOut.cpp b/services/audioflinger/SpdifStreamOut.cpp index 6af7bce..6b6f5db 100644 --- a/services/audioflinger/SpdifStreamOut.cpp +++ b/services/audioflinger/SpdifStreamOut.cpp @@ -37,6 +37,9 @@ SpdifStreamOut::SpdifStreamOut(AudioHwDevice *dev, audio_format_t format) : AudioStreamOut(dev,flags) , mSpdifEncoder(this, format) + , mApplicationFormat(AUDIO_FORMAT_DEFAULT) + , mApplicationSampleRate(0) + , mApplicationChannelMask(0) { } @@ -48,6 +51,10 @@ status_t SpdifStreamOut::open( { struct audio_config customConfig = *config; + mApplicationFormat = config->format; + mApplicationSampleRate = config->sample_rate; + mApplicationChannelMask = config->channel_mask; + // Some data bursts run at a higher sample rate. // TODO Move this into the audio_utils as a static method. switch(config->format) { @@ -106,20 +113,15 @@ int SpdifStreamOut::standby() return AudioStreamOut::standby(); } -size_t SpdifStreamOut::getFrameSize() -{ - return sizeof(int8_t); -} - ssize_t SpdifStreamOut::writeDataBurst(const void* buffer, size_t bytes) { return AudioStreamOut::write(buffer, bytes); } -ssize_t SpdifStreamOut::write(const void* buffer, size_t bytes) +ssize_t SpdifStreamOut::write(const void* buffer, size_t numBytes) { // Write to SPDIF wrapper. It will call back to writeDataBurst(). - return mSpdifEncoder.write(buffer, bytes); + return mSpdifEncoder.write(buffer, numBytes); } } // namespace android diff --git a/services/audioflinger/SpdifStreamOut.h b/services/audioflinger/SpdifStreamOut.h index a61a7bd..c870250 100644 --- a/services/audioflinger/SpdifStreamOut.h +++ b/services/audioflinger/SpdifStreamOut.h @@ -64,7 +64,27 @@ public: */ virtual ssize_t write(const void* buffer, size_t bytes); - virtual size_t getFrameSize(); + /** + * @return frame size from the perspective of the application and the AudioFlinger. + */ + virtual size_t getFrameSize() const { return sizeof(int8_t); } + + /** + * @return format from the perspective of the application and the AudioFlinger. + */ + virtual audio_format_t getFormat() const { return mApplicationFormat; } + + /** + * The HAL may be running at a higher sample rate if, for example, playing wrapped EAC3. + * @return sample rate from the perspective of the application and the AudioFlinger. + */ + virtual uint32_t getSampleRate() const { return mApplicationSampleRate; } + + /** + * The HAL is in stereo mode when playing multi-channel compressed audio over HDMI. + * @return channel mask from the perspective of the application and the AudioFlinger. + */ + virtual audio_channel_mask_t getChannelMask() const { return mApplicationChannelMask; } virtual status_t flush(); virtual status_t standby(); @@ -89,6 +109,9 @@ private: }; MySPDIFEncoder mSpdifEncoder; + audio_format_t mApplicationFormat; + uint32_t mApplicationSampleRate; + audio_channel_mask_t mApplicationChannelMask; ssize_t writeDataBurst(const void* data, size_t bytes); ssize_t writeInternal(const void* buffer, size_t bytes); diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index d9f1a83..c360051 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2081,8 +2081,8 @@ int AudioFlinger::PlaybackThread::asyncCallback(stream_callback_event_t event, void AudioFlinger::PlaybackThread::readOutputParameters_l() { // unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL - mSampleRate = mOutput->stream->common.get_sample_rate(&mOutput->stream->common); - mChannelMask = mOutput->stream->common.get_channels(&mOutput->stream->common); + mSampleRate = mOutput->getSampleRate(); + mChannelMask = mOutput->getChannelMask(); if (!audio_is_output_channel(mChannelMask)) { LOG_ALWAYS_FATAL("HAL channel mask %#x not valid for output", mChannelMask); } @@ -2092,8 +2092,12 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l() mChannelMask); } mChannelCount = audio_channel_count_from_out_mask(mChannelMask); + + // Get actual HAL format. mHALFormat = mOutput->stream->common.get_format(&mOutput->stream->common); - mFormat = mHALFormat; + // Get format from the shim, which will be different than the HAL format + // if playing compressed audio over HDMI passthrough. + mFormat = mOutput->getFormat(); if (!audio_is_valid_format(mFormat)) { LOG_ALWAYS_FATAL("HAL format %#x not valid for output", mFormat); } @@ -4559,9 +4563,10 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // app does not call stop() and relies on underrun to stop: // hence the test on (track->mRetryCount > 1). // If retryCount<=1 then track is about to underrun and be removed. + // Do not use a high threshold for compressed audio. uint32_t minFrames; if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing() - && (track->mRetryCount > 1)) { + && (track->mRetryCount > 1) && audio_is_linear_pcm(mFormat)) { minFrames = mNormalFrameCount; } else { minFrames = 1; @@ -4650,6 +4655,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep // it will then automatically call start() when data is available android_atomic_or(CBLK_DISABLED, &cblk->mFlags); } else if (last) { + ALOGW("pause because of UNDERRUN, framesReady = %zu," + "minFrames = %u, mFormat = %#x", + track->framesReady(), minFrames, mFormat); mixerStatus = MIXER_TRACKS_ENABLED; if (mHwSupportsPause && !mHwPaused && !mStandby) { doHwPause = true; |