From: Lajos Molnar Date: Tue, 21 Oct 2014 16:36:43 +0000 (-0700) Subject: mediaplayer: don't report position past last queued position X-Git-Tag: android-x86-6.0-r1~852^2~155^2~12 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f592671336be0a061799033e47ceeacb648ed3bf;p=android-x86%2Fframeworks-av.git mediaplayer: don't report position past last queued position also reanchor offloaded audio track correctly Bug: 17653702 Change-Id: If05394d3b119be8d80b7764847496246d34a2133 --- diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index 638d9bcbf4..86ce3855db 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -68,6 +68,8 @@ NuPlayer::Renderer::Renderer( mAudioFirstAnchorTimeMediaUs(-1), mAnchorTimeMediaUs(-1), mAnchorTimeRealUs(-1), + mAnchorNumFramesWritten(-1), + mAnchorMaxMediaUs(-1), mVideoLateByUs(0ll), mHasAudio(false), mHasVideo(false), @@ -173,7 +175,8 @@ status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) { return getCurrentPosition(mediaUs, ALooper::GetNowUs()); } -status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs, int64_t nowUs) { +status_t NuPlayer::Renderer::getCurrentPosition( + int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo) { Mutex::Autolock autoLock(mTimeLock); if (!mHasAudio && !mHasVideo) { return NO_INIT; @@ -182,12 +185,21 @@ status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs, int64_t nowUs) if (mAnchorTimeMediaUs < 0) { return NO_INIT; } + int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs; if (mPauseStartedTimeRealUs != -1) { positionUs -= (nowUs - mPauseStartedTimeRealUs); } + // limit position to the last queued media time (for video only stream + // position will be discrete as we don't know how long each frame lasts) + if (mAnchorMaxMediaUs >= 0 && !allowPastQueuedVideo) { + if (positionUs > mAnchorMaxMediaUs) { + positionUs = mAnchorMaxMediaUs; + } + } + if (positionUs < mAudioFirstAnchorTimeMediaUs) { positionUs = mAudioFirstAnchorTimeMediaUs; } @@ -217,10 +229,12 @@ void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) { } } -void NuPlayer::Renderer::setAnchorTime(int64_t mediaUs, int64_t realUs, bool resume) { +void NuPlayer::Renderer::setAnchorTime( + int64_t mediaUs, int64_t realUs, int64_t numFramesWritten, bool resume) { Mutex::Autolock autoLock(mTimeLock); mAnchorTimeMediaUs = mediaUs; mAnchorTimeRealUs = realUs; + mAnchorNumFramesWritten = numFramesWritten; if (resume) { mPauseStartedTimeRealUs = -1; } @@ -541,7 +555,7 @@ size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) { int64_t mediaTimeUs; CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6); - onNewAudioMediaTime(mediaTimeUs); + setAudioFirstAnchorTimeIfNeeded(mediaTimeUs); } size_t copy = entry->mBuffer->size() - entry->mOffset; @@ -564,6 +578,14 @@ size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) { notifyIfMediaRenderingStarted(); } + if (mAudioFirstAnchorTimeMediaUs >= 0) { + int64_t nowUs = ALooper::GetNowUs(); + setAnchorTime(mAudioFirstAnchorTimeMediaUs, nowUs - getPlayedOutAudioDurationUs(nowUs)); + } + + // we don't know how much data we are queueing for offloaded tracks + mAnchorMaxMediaUs = -1; + if (hasEOS) { (new AMessage(kWhatStopAudioSink, id()))->post(); } @@ -663,6 +685,11 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { break; } } + mAnchorMaxMediaUs = + mAnchorTimeMediaUs + + (int64_t)(max((long long)mNumFramesWritten - mAnchorNumFramesWritten, 0LL) + * 1000LL * mAudioSink->msecsPerFrame()); + return !mAudioQueue.empty(); } @@ -674,7 +701,7 @@ int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) { int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) { int64_t currentPositionUs; - if (getCurrentPosition(¤tPositionUs, nowUs) != OK) { + if (getCurrentPosition(¤tPositionUs, nowUs, true /* allowPastQueuedVideo */) != OK) { // If failed to get current position, e.g. due to audio clock is not ready, then just // play out video immediately without delay. return nowUs; @@ -690,7 +717,8 @@ void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) { } setAudioFirstAnchorTimeIfNeeded(mediaTimeUs); int64_t nowUs = ALooper::GetNowUs(); - setAnchorTime(mediaTimeUs, nowUs + getPendingAudioPlayoutDurationUs(nowUs)); + setAnchorTime( + mediaTimeUs, nowUs + getPendingAudioPlayoutDurationUs(nowUs), mNumFramesWritten); } void NuPlayer::Renderer::postDrainVideoQueue() { @@ -733,6 +761,9 @@ void NuPlayer::Renderer::postDrainVideoQueue() { } else { realTimeUs = getRealTimeUs(mediaTimeUs, nowUs); } + if (!mHasAudio) { + mAnchorMaxMediaUs = mediaTimeUs + 100000; // smooth out videos >= 10fps + } // Heuristics to handle situation when media time changed without a // discontinuity. If we have not drained an audio buffer that was @@ -1103,6 +1134,7 @@ void NuPlayer::Renderer::onAudioSinkChanged() { } CHECK(!mDrainAudioQueuePending); mNumFramesWritten = 0; + mAnchorNumFramesWritten = -1; uint32_t written; if (mAudioSink->getFramesWritten(&written) == OK) { mNumFramesWritten = written; @@ -1158,7 +1190,8 @@ void NuPlayer::Renderer::onResume() { if (mPauseStartedTimeRealUs != -1) { int64_t newAnchorRealUs = mAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs; - setAnchorTime(mAnchorTimeMediaUs, newAnchorRealUs, true /* resume */); + setAnchorTime( + mAnchorTimeMediaUs, newAnchorRealUs, mAnchorNumFramesWritten, true /* resume */); } if (!mAudioQueue.empty()) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index b15a266e0d..7b46a5936c 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -61,11 +61,13 @@ struct NuPlayer::Renderer : public AHandler { // Following setters and getters are protected by mTimeLock. status_t getCurrentPosition(int64_t *mediaUs); - status_t getCurrentPosition(int64_t *mediaUs, int64_t nowUs); + status_t getCurrentPosition( + int64_t *mediaUs, int64_t nowUs, bool allowPastQueuedVideo = false); void setHasMedia(bool audio); void setAudioFirstAnchorTime(int64_t mediaUs); void setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs); - void setAnchorTime(int64_t mediaUs, int64_t realUs, bool resume = false); + void setAnchorTime( + int64_t mediaUs, int64_t realUs, int64_t numFramesWritten = -1, bool resume = false); void setVideoLateByUs(int64_t lateUs); int64_t getVideoLateByUs(); void setPauseStartedTimeRealUs(int64_t realUs); @@ -148,6 +150,8 @@ private: int64_t mAudioFirstAnchorTimeMediaUs; int64_t mAnchorTimeMediaUs; int64_t mAnchorTimeRealUs; + int64_t mAnchorNumFramesWritten; + int64_t mAnchorMaxMediaUs; int64_t mVideoLateByUs; bool mHasAudio; bool mHasVideo; @@ -174,6 +178,7 @@ private: int32_t mTotalBuffersQueued; int32_t mLastAudioBufferDrained; + size_t fillAudioBuffer(void *buffer, size_t size); bool onDrainAudioQueue();