Loading media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +39 −6 Original line number Diff line number Diff line Loading @@ -68,6 +68,8 @@ NuPlayer::Renderer::Renderer( mAudioFirstAnchorTimeMediaUs(-1), mAnchorTimeMediaUs(-1), mAnchorTimeRealUs(-1), mAnchorNumFramesWritten(-1), mAnchorMaxMediaUs(-1), mVideoLateByUs(0ll), mHasAudio(false), mHasVideo(false), Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; Loading @@ -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(); } Loading Loading @@ -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(); } Loading @@ -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; Loading @@ -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() { Loading Loading @@ -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 Loading Loading @@ -1103,6 +1134,7 @@ void NuPlayer::Renderer::onAudioSinkChanged() { } CHECK(!mDrainAudioQueuePending); mNumFramesWritten = 0; mAnchorNumFramesWritten = -1; uint32_t written; if (mAudioSink->getFramesWritten(&written) == OK) { mNumFramesWritten = written; Loading Loading @@ -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()) { Loading media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +7 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading @@ -174,6 +178,7 @@ private: int32_t mTotalBuffersQueued; int32_t mLastAudioBufferDrained; size_t fillAudioBuffer(void *buffer, size_t size); bool onDrainAudioQueue(); Loading Loading
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +39 −6 Original line number Diff line number Diff line Loading @@ -68,6 +68,8 @@ NuPlayer::Renderer::Renderer( mAudioFirstAnchorTimeMediaUs(-1), mAnchorTimeMediaUs(-1), mAnchorTimeRealUs(-1), mAnchorNumFramesWritten(-1), mAnchorMaxMediaUs(-1), mVideoLateByUs(0ll), mHasAudio(false), mHasVideo(false), Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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; } Loading Loading @@ -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; Loading @@ -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(); } Loading Loading @@ -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(); } Loading @@ -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; Loading @@ -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() { Loading Loading @@ -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 Loading Loading @@ -1103,6 +1134,7 @@ void NuPlayer::Renderer::onAudioSinkChanged() { } CHECK(!mDrainAudioQueuePending); mNumFramesWritten = 0; mAnchorNumFramesWritten = -1; uint32_t written; if (mAudioSink->getFramesWritten(&written) == OK) { mNumFramesWritten = written; Loading Loading @@ -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()) { Loading
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +7 −2 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading @@ -174,6 +178,7 @@ private: int32_t mTotalBuffersQueued; int32_t mLastAudioBufferDrained; size_t fillAudioBuffer(void *buffer, size_t size); bool onDrainAudioQueue(); Loading