summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--services/audioflinger/AudioStreamOut.cpp15
-rw-r--r--services/audioflinger/AudioStreamOut.h23
-rw-r--r--services/audioflinger/SpdifStreamOut.cpp16
-rw-r--r--services/audioflinger/SpdifStreamOut.h25
-rw-r--r--services/audioflinger/Threads.cpp16
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;