Delay signaling the end of audio playback until all frames have actually played.

Change-Id: I1fa07358a885a818fd0a5d7da425740f86095e10
related-to-bug: 3404000
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index d12ee9c..0b79324 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -108,6 +108,8 @@
 
     void reset();
 
+    uint32_t getNumFramesPendingPlayout() const;
+
     AudioPlayer(const AudioPlayer &);
     AudioPlayer &operator=(const AudioPlayer &);
 };
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index e7c0299..07f250a 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -280,6 +280,26 @@
     buffer->size = numBytesWritten;
 }
 
+uint32_t AudioPlayer::getNumFramesPendingPlayout() const {
+    uint32_t numFramesPlayedOut;
+    status_t err;
+
+    if (mAudioSink != NULL) {
+        err = mAudioSink->getPosition(&numFramesPlayedOut);
+    } else {
+        err = mAudioTrack->getPosition(&numFramesPlayedOut);
+    }
+
+    if (err != OK || mNumFramesPlayed < numFramesPlayedOut) {
+        return 0;
+    }
+
+    // mNumFramesPlayed is the number of frames submitted
+    // to the audio sink for playback, but not all of them
+    // may have played out by now.
+    return mNumFramesPlayed - numFramesPlayedOut;
+}
+
 size_t AudioPlayer::fillBuffer(void *data, size_t size) {
     if (mNumFramesPlayed == 0) {
         LOGV("AudioCallback");
@@ -342,7 +362,34 @@
 
             if (err != OK) {
                 if (mObserver && !mReachedEOS) {
-                    mObserver->postAudioEOS();
+                    // We don't want to post EOS right away but only
+                    // after all frames have actually been played out.
+
+                    // These are the number of frames submitted to the
+                    // AudioTrack that you haven't heard yet.
+                    uint32_t numFramesPendingPlayout =
+                        getNumFramesPendingPlayout();
+
+                    // These are the number of frames we're going to
+                    // submit to the AudioTrack by returning from this
+                    // callback.
+                    uint32_t numAdditionalFrames = size_done / mFrameSize;
+
+                    numFramesPendingPlayout += numAdditionalFrames;
+
+                    int64_t timeToCompletionUs =
+                        (1000000ll * numFramesPendingPlayout) / mSampleRate;
+
+                    LOGV("total number of frames played: %lld (%lld us)",
+                            (mNumFramesPlayed + numAdditionalFrames),
+                            1000000ll * (mNumFramesPlayed + numAdditionalFrames)
+                                / mSampleRate);
+
+                    LOGV("%d frames left to play, %lld us (%.2f secs)",
+                         numFramesPendingPlayout,
+                         timeToCompletionUs, timeToCompletionUs / 1E6);
+
+                    mObserver->postAudioEOS(timeToCompletionUs + mLatencyUs);
                 }
 
                 mReachedEOS = true;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 35bc0b8..7fdb1a1 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1513,12 +1513,12 @@
     mQueue.postEventWithDelay(mVideoLagEvent, 1000000ll);
 }
 
-void AwesomePlayer::postCheckAudioStatusEvent_l() {
+void AwesomePlayer::postCheckAudioStatusEvent_l(int64_t delayUs) {
     if (mAudioStatusEventPending) {
         return;
     }
     mAudioStatusEventPending = true;
-    mQueue.postEvent(mCheckAudioStatusEvent);
+    mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
 }
 
 void AwesomePlayer::onCheckAudioStatus() {
@@ -1810,12 +1810,12 @@
     return mExtractorFlags;
 }
 
-void AwesomePlayer::postAudioEOS() {
-    postCheckAudioStatusEvent_l();
+void AwesomePlayer::postAudioEOS(int64_t delayUs) {
+    postCheckAudioStatusEvent_l(delayUs);
 }
 
 void AwesomePlayer::postAudioSeekComplete() {
-    postCheckAudioStatusEvent_l();
+    postCheckAudioStatusEvent_l(0 /* delayUs */);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index b26f202..a9b7ae8 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -93,7 +93,7 @@
     // This is a mask of MediaExtractor::Flags.
     uint32_t flags() const;
 
-    void postAudioEOS();
+    void postAudioEOS(int64_t delayUs = 0ll);
     void postAudioSeekComplete();
 
 private:
@@ -203,7 +203,7 @@
     void postVideoEvent_l(int64_t delayUs = -1);
     void postBufferingEvent_l();
     void postStreamDoneEvent_l(status_t status);
-    void postCheckAudioStatusEvent_l();
+    void postCheckAudioStatusEvent_l(int64_t delayUs);
     void postVideoLagEvent_l();
     status_t play_l();