diff options
Diffstat (limited to 'media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp')
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp | 232 |
1 files changed, 124 insertions, 108 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index e5c64f6..7b9dbb7 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -25,6 +25,7 @@ #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/foundation/AUtils.h> #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> @@ -63,22 +64,21 @@ NuPlayer::Renderer::Renderer( mDrainVideoQueuePending(false), mAudioQueueGeneration(0), mVideoQueueGeneration(0), - mFirstAnchorTimeMediaUs(-1), - mAnchorTimeMediaUs(-1), - mAnchorTimeRealUs(-1), - mFlushingAudio(false), - mFlushingVideo(false), + mAudioFirstAnchorTimeMediaUs(-1), + mVideoAnchorTimeMediaUs(-1), + mVideoAnchorTimeRealUs(-1), + mVideoLateByUs(0ll), mHasAudio(false), mHasVideo(false), + mPauseStartedTimeRealUs(-1), + mFlushingAudio(false), + mFlushingVideo(false), mSyncQueues(false), mPaused(false), - mPauseStartedTimeRealUs(-1), mVideoSampleReceived(false), mVideoRenderingStarted(false), mVideoRenderingStartGeneration(0), mAudioRenderingStartGeneration(0), - mLastPositionUpdateUs(-1ll), - mVideoLateByUs(0ll), mAudioOffloadPauseTimeoutGeneration(0), mAudioOffloadTornDown(false) { readProperties(); @@ -137,9 +137,9 @@ void NuPlayer::Renderer::signalTimeDiscontinuity() { Mutex::Autolock autoLock(mLock); // CHECK(mAudioQueue.empty()); // CHECK(mVideoQueue.empty()); - mFirstAnchorTimeMediaUs = -1; - mAnchorTimeMediaUs = -1; - mAnchorTimeRealUs = -1; + setAudioFirstAnchorTime(-1); + setVideoAnchorTime(-1, -1); + setVideoLateByUs(0); mSyncQueues = false; } @@ -165,6 +165,78 @@ void NuPlayer::Renderer::setVideoFrameRate(float fps) { msg->post(); } +status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) { + return getCurrentPosition(mediaUs, ALooper::GetNowUs()); +} + +status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs, int64_t nowUs) { + Mutex::Autolock autoLock(mTimeLock); + if (!mHasAudio && !mHasVideo) { + return NO_INIT; + } + + int64_t positionUs = 0; + if (!mHasAudio) { + if (mVideoAnchorTimeMediaUs < 0) { + return NO_INIT; + } + positionUs = (nowUs - mVideoAnchorTimeRealUs) + mVideoAnchorTimeMediaUs; + + if (mPauseStartedTimeRealUs != -1) { + positionUs -= (nowUs - mPauseStartedTimeRealUs); + } + } else { + if (mAudioFirstAnchorTimeMediaUs < 0) { + return NO_INIT; + } + positionUs = mAudioFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs); + } + *mediaUs = (positionUs <= 0) ? 0 : positionUs; + return OK; +} + +void NuPlayer::Renderer::setHasMedia(bool audio) { + Mutex::Autolock autoLock(mTimeLock); + if (audio) { + mHasAudio = true; + } else { + mHasVideo = true; + } +} + +void NuPlayer::Renderer::setAudioFirstAnchorTime(int64_t mediaUs) { + Mutex::Autolock autoLock(mTimeLock); + mAudioFirstAnchorTimeMediaUs = mediaUs; +} + +void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) { + Mutex::Autolock autoLock(mTimeLock); + if (mAudioFirstAnchorTimeMediaUs == -1) { + mAudioFirstAnchorTimeMediaUs = mediaUs; + } +} + +void NuPlayer::Renderer::setVideoAnchorTime(int64_t mediaUs, int64_t realUs) { + Mutex::Autolock autoLock(mTimeLock); + mVideoAnchorTimeMediaUs = mediaUs; + mVideoAnchorTimeRealUs = realUs; +} + +void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) { + Mutex::Autolock autoLock(mTimeLock); + mVideoLateByUs = lateUs; +} + +int64_t NuPlayer::Renderer::getVideoLateByUs() { + Mutex::Autolock autoLock(mTimeLock); + return mVideoLateByUs; +} + +void NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) { + Mutex::Autolock autoLock(mTimeLock); + mPauseStartedTimeRealUs = realUs; +} + void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatStopAudioSink: @@ -388,16 +460,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); - if (mFirstAnchorTimeMediaUs == -1) { - mFirstAnchorTimeMediaUs = mediaTimeUs; - } - - int64_t nowUs = ALooper::GetNowUs(); - mAnchorTimeMediaUs = - mFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs); - mAnchorTimeRealUs = nowUs; - - notifyPosition(); + setAudioFirstAnchorTimeIfNeeded(mediaTimeUs); } size_t copy = entry->mBuffer->size() - entry->mOffset; @@ -468,15 +531,8 @@ bool NuPlayer::Renderer::onDrainAudioQueue() { int64_t mediaTimeUs; CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6); - if (mFirstAnchorTimeMediaUs == -1) { - mFirstAnchorTimeMediaUs = mediaTimeUs; - } - mAnchorTimeMediaUs = mediaTimeUs; - - int64_t nowUs = ALooper::GetNowUs(); - mAnchorTimeRealUs = nowUs + getPendingAudioPlayoutDurationUs(nowUs); - notifyPosition(); + setAudioFirstAnchorTimeIfNeeded(mediaTimeUs); } size_t copy = entry->mBuffer->size() - entry->mOffset; @@ -534,6 +590,14 @@ int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) { return writtenAudioDurationUs - getPlayedOutAudioDurationUs(nowUs); } +int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) { + int64_t currentPositionUs; + if (getCurrentPosition(¤tPositionUs, nowUs) != OK) { + currentPositionUs = 0; + } + return (mediaTimeUs - currentPositionUs) + nowUs; +} + void NuPlayer::Renderer::postDrainVideoQueue() { if (mDrainVideoQueuePending || mSyncQueues @@ -568,21 +632,11 @@ void NuPlayer::Renderer::postDrainVideoQueue() { int64_t mediaTimeUs; CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); - if (mFirstAnchorTimeMediaUs == -1 && !mHasAudio) { - mFirstAnchorTimeMediaUs = mediaTimeUs; - } - if (mAnchorTimeMediaUs < 0) { - if (!mHasAudio) { - mAnchorTimeMediaUs = mediaTimeUs; - mAnchorTimeRealUs = nowUs; - if (!mPaused || mVideoSampleReceived) { - notifyPosition(); - } - } + if (mVideoAnchorTimeMediaUs < 0) { + setVideoAnchorTime(mediaTimeUs, nowUs); realTimeUs = nowUs; } else { - realTimeUs = - (mediaTimeUs - mAnchorTimeMediaUs) + mAnchorTimeRealUs; + realTimeUs = getRealTimeUs(mediaTimeUs, nowUs); } } @@ -618,10 +672,11 @@ void NuPlayer::Renderer::onDrainVideoQueue() { mVideoQueue.erase(mVideoQueue.begin()); entry = NULL; - mVideoLateByUs = 0ll; + setVideoLateByUs(0); return; } + int64_t nowUs = -1; int64_t realTimeUs; if (mFlags & FLAG_REAL_TIME) { CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs)); @@ -629,13 +684,17 @@ void NuPlayer::Renderer::onDrainVideoQueue() { int64_t mediaTimeUs; CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs)); - realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs; + nowUs = ALooper::GetNowUs(); + realTimeUs = getRealTimeUs(mediaTimeUs, nowUs); } bool tooLate = false; if (!mPaused) { - mVideoLateByUs = ALooper::GetNowUs() - realTimeUs; + if (nowUs == -1) { + nowUs = ALooper::GetNowUs(); + } + setVideoLateByUs(nowUs - realTimeUs); tooLate = (mVideoLateByUs > 40000); if (tooLate) { @@ -644,13 +703,14 @@ void NuPlayer::Renderer::onDrainVideoQueue() { } else { ALOGV("rendering video at media time %.2f secs", (mFlags & FLAG_REAL_TIME ? realTimeUs : - (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6); + (realTimeUs + mVideoAnchorTimeMediaUs - mVideoAnchorTimeRealUs)) / 1E6); } } else { - mVideoLateByUs = 0ll; - if (!mHasAudio && !mVideoSampleReceived) { - mAnchorTimeMediaUs = -1; - mAnchorTimeRealUs = -1; + setVideoLateByUs(0); + if (!mVideoSampleReceived) { + // This will ensure that the first frame after a flush won't be used as anchor + // when renderer is in paused state, because resume can happen any time after seek. + setVideoAnchorTime(-1, -1); } } @@ -693,10 +753,9 @@ void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) { int32_t audio; CHECK(msg->findInt32("audio", &audio)); - if (audio) { - mHasAudio = true; - } else { - mHasVideo = true; + setHasMedia(audio); + + if (mHasVideo) { if (mVideoScheduler == NULL) { mVideoScheduler = new VideoFrameScheduler(); mVideoScheduler->init(); @@ -837,9 +896,7 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) { { Mutex::Autolock autoLock(mLock); syncQueuesDone_l(); - if (!mHasAudio) { - mPauseStartedTimeRealUs = -1; - } + setPauseStartedTimeRealUs(-1); } ALOGV("flushing %s", audio ? "audio" : "video"); @@ -852,7 +909,7 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) { prepareForMediaRenderingStart(); if (offloadingAudio()) { - mFirstAnchorTimeMediaUs = -1; + setAudioFirstAnchorTime(-1); } } @@ -943,42 +1000,6 @@ void NuPlayer::Renderer::onDisableOffloadAudio() { ++mAudioQueueGeneration; } -void NuPlayer::Renderer::notifyPosition() { - // notifyPosition() must be called only after setting mAnchorTimeRealUs - // and mAnchorTimeMediaUs, and must not be paused as it extrapolates position. - //CHECK_GE(mAnchorTimeRealUs, 0); - //CHECK_GE(mAnchorTimeMediaUs, 0); - //CHECK(!mPaused || !mHasAudio); // video-only does display in paused mode. - - int64_t nowUs = ALooper::GetNowUs(); - - if (mLastPositionUpdateUs >= 0 - && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) { - return; - } - mLastPositionUpdateUs = nowUs; - - int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs; - - //ALOGD("notifyPosition: positionUs(%lld) nowUs(%lld) mAnchorTimeRealUs(%lld)" - // " mAnchorTimeMediaUs(%lld) mFirstAnchorTimeMediaUs(%lld)", - // (long long)positionUs, (long long)nowUs, (long long)mAnchorTimeRealUs, - // (long long)mAnchorTimeMediaUs, (long long)mFirstAnchorTimeMediaUs); - - // Due to adding the latency to mAnchorTimeRealUs in onDrainAudioQueue(), - // positionUs may be less than the first media time. This is avoided - // here to prevent potential retrograde motion of the position bar - // when starting up after a seek. - if (positionUs < mFirstAnchorTimeMediaUs) { - positionUs = mFirstAnchorTimeMediaUs; - } - sp<AMessage> notify = mNotify->dup(); - notify->setInt32("what", kWhatPosition); - notify->setInt64("positionUs", positionUs); - notify->setInt64("videoLateByUs", mVideoLateByUs); - notify->post(); -} - void NuPlayer::Renderer::onPause() { if (mPaused) { ALOGW("Renderer::onPause() called while already paused!"); @@ -990,9 +1011,7 @@ void NuPlayer::Renderer::onPause() { ++mVideoQueueGeneration; prepareForMediaRenderingStart(); mPaused = true; - if (!mHasAudio) { - mPauseStartedTimeRealUs = ALooper::GetNowUs(); - } + setPauseStartedTimeRealUs(ALooper::GetNowUs()); } mDrainAudioQueuePending = false; @@ -1021,9 +1040,11 @@ void NuPlayer::Renderer::onResume() { Mutex::Autolock autoLock(mLock); mPaused = false; - if (!mHasAudio && mPauseStartedTimeRealUs != -1) { - mAnchorTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeRealUs; - mPauseStartedTimeRealUs = -1; + if (mPauseStartedTimeRealUs != -1) { + int64_t newAnchorRealUs = + mVideoAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs; + setVideoAnchorTime(mVideoAnchorTimeMediaUs, newAnchorRealUs); + setPauseStartedTimeRealUs(-1); } if (!mAudioQueue.empty()) { @@ -1045,7 +1066,6 @@ void NuPlayer::Renderer::onSetVideoFrameRate(float fps) { // TODO: Remove unnecessary calls to getPlayedOutAudioDurationUs() // as it acquires locks and may query the audio driver. // -// Some calls are not needed since notifyPosition() doesn't always deliver a message. // Some calls could conceivably retrieve extrapolated data instead of // accessing getTimestamp() or getPosition() every time a data buffer with // a media time is received. @@ -1113,15 +1133,11 @@ void NuPlayer::Renderer::onAudioOffloadTearDown(AudioOffloadTearDownReason reaso } mAudioOffloadTornDown = true; - int64_t firstAudioTimeUs; - { - Mutex::Autolock autoLock(mLock); - firstAudioTimeUs = mFirstAnchorTimeMediaUs; + int64_t currentPositionUs; + if (getCurrentPosition(¤tPositionUs) != OK) { + currentPositionUs = 0; } - int64_t currentPositionUs = - firstAudioTimeUs + getPlayedOutAudioDurationUs(ALooper::GetNowUs()); - mAudioSink->stop(); mAudioSink->flush(); |