From 84b343f29063fbfa2ee61b2e3d37ba059ca507d4 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Tue, 22 Mar 2011 10:31:21 -0700 Subject: Delay signaling the end of audio playback until all frames have actually played. Change-Id: I1fa07358a885a818fd0a5d7da425740f86095e10 related-to-bug: 3404000 --- include/media/stagefright/AudioPlayer.h | 2 ++ media/libstagefright/AudioPlayer.cpp | 49 +++++++++++++++++++++++++++- media/libstagefright/AwesomePlayer.cpp | 10 +++--- media/libstagefright/include/AwesomePlayer.h | 4 +-- 4 files changed, 57 insertions(+), 8 deletions(-) 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 @@ private: 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 @@ void AudioPlayer::AudioCallback(int event, void *info) { 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 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) { 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 @@ void AwesomePlayer::postVideoLagEvent_l() { 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 @@ uint32_t AwesomePlayer::flags() const { 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 @@ struct AwesomePlayer { // 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 @@ private: 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(); -- cgit v1.1