Loading services/audioflinger/AudioStreamOut.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags) , mRateMultiplier(1) , mHalFormatHasProportionalFrames(false) , mHalFrameSize(0) , mExpectRetrograde(false) { } Loading Loading @@ -69,8 +70,12 @@ status_t AudioStreamOut::getRenderPosition(uint64_t *frames) const uint32_t truncatedPosition = (uint32_t)mRenderPosition; int32_t deltaHalPosition; // initialization not needed, overwitten by __builtin_sub_overflow() (void) __builtin_sub_overflow(halPosition, truncatedPosition, &deltaHalPosition); if (deltaHalPosition > 0) { mRenderPosition += deltaHalPosition; } else if (mExpectRetrograde) { mExpectRetrograde = false; mRenderPosition -= static_cast<uint64_t>(-deltaHalPosition); } // Scale from HAL sample rate to application rate. *frames = mRenderPosition / mRateMultiplier; Loading Loading @@ -187,6 +192,7 @@ audio_config_base_t AudioStreamOut::getAudioProperties() const int AudioStreamOut::flush() { mRenderPosition = 0; mExpectRetrograde = false; mFramesWritten = 0; mFramesWrittenAtStandby = 0; status_t result = stream->flush(); Loading @@ -196,6 +202,7 @@ int AudioStreamOut::flush() int AudioStreamOut::standby() { mRenderPosition = 0; mExpectRetrograde = false; mFramesWrittenAtStandby = mFramesWritten; return stream->standby(); } Loading services/audioflinger/AudioStreamOut.h +9 −1 Original line number Diff line number Diff line Loading @@ -93,13 +93,21 @@ public: virtual status_t flush(); virtual status_t standby(); // Avoid suppressing retrograde motion in mRenderPosition for gapless offload/direct when // transitioning between tracks. // The HAL resets the frame position without flush/stop being called, but calls back prior to // this event. So, on the next occurrence of retrograde motion, we permit backwards movement of // mRenderPosition. virtual void presentationComplete() { mExpectRetrograde = true; } protected: uint64_t mFramesWritten; // reset by flush uint64_t mFramesWrittenAtStandby; uint64_t mRenderPosition; // reset by flush or standby uint64_t mRenderPosition; // reset by flush, standby, or presentation complete int mRateMultiplier; bool mHalFormatHasProportionalFrames; size_t mHalFrameSize; bool mExpectRetrograde; // see presentationComplete }; } // namespace android Loading services/audioflinger/Threads.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -6316,9 +6316,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep track->isStopping_2() || track->isPaused()) { // We have consumed all the buffers of this track. // Remove it from the list of active tracks. bool presComplete = false; if (mStandby || !last || track->presentationComplete(latency_l()) || (presComplete = track->presentationComplete(latency_l())) || track->isPaused() || mHwPaused) { if (presComplete) { mOutput->presentationComplete(); } if (track->isStopping_2()) { track->mState = TrackBase::STOPPED; } Loading Loading @@ -6897,7 +6901,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // Drain has completed or we are in standby, signal presentation complete if (!(mDrainSequence & 1) || !last || mStandby) { track->mState = TrackBase::STOPPED; track->presentationComplete(latency_l()); mOutput->presentationComplete(); track->presentationComplete(latency_l()); // always returns true track->reset(); tracksToRemove->add(track); // OFFLOADED stop resets frame counts. Loading Loading
services/audioflinger/AudioStreamOut.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ AudioStreamOut::AudioStreamOut(AudioHwDevice *dev, audio_output_flags_t flags) , mRateMultiplier(1) , mHalFormatHasProportionalFrames(false) , mHalFrameSize(0) , mExpectRetrograde(false) { } Loading Loading @@ -69,8 +70,12 @@ status_t AudioStreamOut::getRenderPosition(uint64_t *frames) const uint32_t truncatedPosition = (uint32_t)mRenderPosition; int32_t deltaHalPosition; // initialization not needed, overwitten by __builtin_sub_overflow() (void) __builtin_sub_overflow(halPosition, truncatedPosition, &deltaHalPosition); if (deltaHalPosition > 0) { mRenderPosition += deltaHalPosition; } else if (mExpectRetrograde) { mExpectRetrograde = false; mRenderPosition -= static_cast<uint64_t>(-deltaHalPosition); } // Scale from HAL sample rate to application rate. *frames = mRenderPosition / mRateMultiplier; Loading Loading @@ -187,6 +192,7 @@ audio_config_base_t AudioStreamOut::getAudioProperties() const int AudioStreamOut::flush() { mRenderPosition = 0; mExpectRetrograde = false; mFramesWritten = 0; mFramesWrittenAtStandby = 0; status_t result = stream->flush(); Loading @@ -196,6 +202,7 @@ int AudioStreamOut::flush() int AudioStreamOut::standby() { mRenderPosition = 0; mExpectRetrograde = false; mFramesWrittenAtStandby = mFramesWritten; return stream->standby(); } Loading
services/audioflinger/AudioStreamOut.h +9 −1 Original line number Diff line number Diff line Loading @@ -93,13 +93,21 @@ public: virtual status_t flush(); virtual status_t standby(); // Avoid suppressing retrograde motion in mRenderPosition for gapless offload/direct when // transitioning between tracks. // The HAL resets the frame position without flush/stop being called, but calls back prior to // this event. So, on the next occurrence of retrograde motion, we permit backwards movement of // mRenderPosition. virtual void presentationComplete() { mExpectRetrograde = true; } protected: uint64_t mFramesWritten; // reset by flush uint64_t mFramesWrittenAtStandby; uint64_t mRenderPosition; // reset by flush or standby uint64_t mRenderPosition; // reset by flush, standby, or presentation complete int mRateMultiplier; bool mHalFormatHasProportionalFrames; size_t mHalFrameSize; bool mExpectRetrograde; // see presentationComplete }; } // namespace android Loading
services/audioflinger/Threads.cpp +7 −2 Original line number Diff line number Diff line Loading @@ -6316,9 +6316,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep track->isStopping_2() || track->isPaused()) { // We have consumed all the buffers of this track. // Remove it from the list of active tracks. bool presComplete = false; if (mStandby || !last || track->presentationComplete(latency_l()) || (presComplete = track->presentationComplete(latency_l())) || track->isPaused() || mHwPaused) { if (presComplete) { mOutput->presentationComplete(); } if (track->isStopping_2()) { track->mState = TrackBase::STOPPED; } Loading Loading @@ -6897,7 +6901,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // Drain has completed or we are in standby, signal presentation complete if (!(mDrainSequence & 1) || !last || mStandby) { track->mState = TrackBase::STOPPED; track->presentationComplete(latency_l()); mOutput->presentationComplete(); track->presentationComplete(latency_l()); // always returns true track->reset(); tracksToRemove->add(track); // OFFLOADED stop resets frame counts. Loading