diff options
| -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;  | 
