Merge "Allow frame count regress in AudioStreamOut" into tm-dev am: f8ec839056
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/av/+/18230820
Change-Id: Ic52c937d02ace2697e0495eaa44b4e74f9f9ff6f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index d8565bd..65ec0e8 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -39,6 +39,7 @@
, mRateMultiplier(1)
, mHalFormatHasProportionalFrames(false)
, mHalFrameSize(0)
+ , mExpectRetrograde(false)
{
}
@@ -69,8 +70,12 @@
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;
@@ -187,6 +192,7 @@
int AudioStreamOut::flush()
{
mRenderPosition = 0;
+ mExpectRetrograde = false;
mFramesWritten = 0;
mFramesWrittenAtStandby = 0;
status_t result = stream->flush();
@@ -196,6 +202,7 @@
int AudioStreamOut::standby()
{
mRenderPosition = 0;
+ mExpectRetrograde = false;
mFramesWrittenAtStandby = mFramesWritten;
return stream->standby();
}
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h
index 565f43a..82fe238 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/AudioStreamOut.h
@@ -93,13 +93,21 @@
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
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 49f6bfc..56ebb6e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6316,9 +6316,13 @@
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;
}
@@ -6897,7 +6901,8 @@
// 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.