Loading media/libmediaplayerservice/nuplayer/NuPlayer.cpp +20 −28 Original line number Diff line number Diff line Loading @@ -151,7 +151,6 @@ private: NuPlayer::NuPlayer() : mUIDValid(false), mSourceFlags(0), mCurrentPositionUs(0), mVideoIsAVC(false), mOffloadAudio(false), mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), Loading @@ -169,7 +168,6 @@ NuPlayer::NuPlayer() mFlushingVideo(NONE), mSkipRenderingAudioUntilMediaTimeUs(-1ll), mSkipRenderingVideoUntilMediaTimeUs(-1ll), mVideoLateByUs(0ll), mNumFramesTotal(0ll), mNumFramesDropped(0ll), mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), Loading Loading @@ -546,8 +544,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { // the extractor may not yet be started and will assert. // If the video decoder is not set (perhaps audio only in this case) // do not perform a seek as it is not needed. int64_t currentPositionUs = 0; if (getCurrentPosition(¤tPositionUs) == OK) { mDeferredActions.push_back( new SeekAction(mCurrentPositionUs, false /* needNotify */)); new SeekAction(currentPositionUs, false /* needNotify */)); } } // If there is a new surface texture, instantiate decoders Loading Loading @@ -581,7 +582,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mVideoEOS = false; mSkipRenderingAudioUntilMediaTimeUs = -1; mSkipRenderingVideoUntilMediaTimeUs = -1; mVideoLateByUs = 0; mNumFramesTotal = 0; mNumFramesDropped = 0; mStarted = true; Loading Loading @@ -889,22 +889,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { && (mVideoEOS || mVideoDecoder == NULL)) { notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); } } else if (what == Renderer::kWhatPosition) { int64_t positionUs; CHECK(msg->findInt64("positionUs", &positionUs)); mCurrentPositionUs = positionUs; CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs)); if (mDriver != NULL) { sp<NuPlayerDriver> driver = mDriver.promote(); if (driver != NULL) { driver->notifyPosition(positionUs); driver->notifyFrameStats( mNumFramesTotal, mNumFramesDropped); } } } else if (what == Renderer::kWhatFlushComplete) { int32_t audio; CHECK(msg->findInt32("audio", &audio)); Loading Loading @@ -1053,10 +1037,6 @@ void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) { case FLUSHING_DECODER: { *state = FLUSHED; if (!audio) { mVideoLateByUs = 0; } break; } Loading @@ -1066,7 +1046,6 @@ void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) { ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video"); if (!audio) { mVideoLateByUs = 0; // Widevine source reads must stop before releasing the video decoder. if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { mSource->stop(); Loading Loading @@ -1487,7 +1466,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { dropAccessUnit = false; if (!audio && !(mSourceFlags & Source::FLAG_SECURE) && mVideoLateByUs > 100000ll && mRenderer->getVideoLateByUs() > 100000ll && mVideoIsAVC && !IsAVCReferenceFrame(accessUnit)) { dropAccessUnit = true; Loading Loading @@ -1822,6 +1801,20 @@ status_t NuPlayer::selectTrack(size_t trackIndex, bool select) { return err; } status_t NuPlayer::getCurrentPosition(int64_t *mediaUs) { sp<Renderer> renderer = mRenderer; if (renderer == NULL) { return NO_INIT; } return renderer->getCurrentPosition(mediaUs); } void NuPlayer::getStats(int64_t *numFramesTotal, int64_t *numFramesDropped) { *numFramesTotal = mNumFramesTotal; *numFramesDropped = mNumFramesDropped; } sp<MetaData> NuPlayer::getFileMeta() { return mSource->getFileFormatMeta(); } Loading Loading @@ -1879,7 +1872,6 @@ void NuPlayer::performSeek(int64_t seekTimeUs, bool needNotify) { if (mDriver != NULL) { sp<NuPlayerDriver> driver = mDriver.promote(); if (driver != NULL) { driver->notifyPosition(seekTimeUs); if (needNotify) { driver->notifySeekComplete(); } Loading media/libmediaplayerservice/nuplayer/NuPlayer.h +2 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,8 @@ struct NuPlayer : public AHandler { status_t getTrackInfo(Parcel* reply) const; status_t getSelectedTrack(int32_t type, Parcel* reply) const; status_t selectTrack(size_t trackIndex, bool select); status_t getCurrentPosition(int64_t *mediaUs); void getStats(int64_t *mNumFramesTotal, int64_t *mNumFramesDropped); sp<MetaData> getFileMeta(); Loading Loading @@ -126,7 +128,6 @@ private: sp<Source> mSource; uint32_t mSourceFlags; sp<NativeWindowWrapper> mNativeWindow; int64_t mCurrentPositionUs; sp<MediaPlayerBase::AudioSink> mAudioSink; sp<Decoder> mVideoDecoder; bool mVideoIsAVC; Loading Loading @@ -179,7 +180,6 @@ private: int64_t mSkipRenderingAudioUntilMediaTimeUs; int64_t mSkipRenderingVideoUntilMediaTimeUs; int64_t mVideoLateByUs; int64_t mNumFramesTotal, mNumFramesDropped; int32_t mVideoScalingMode; Loading media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +21 −73 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/ALooper.h> #include <media/stagefright/foundation/AUtils.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> Loading @@ -38,10 +39,7 @@ NuPlayerDriver::NuPlayerDriver() mSetSurfaceInProgress(false), mDurationUs(-1), mPositionUs(-1), mNotifyTimeRealUs(-1), mPauseStartedTimeUs(-1), mNumFramesTotal(0), mNumFramesDropped(0), mSeekInProgress(false), mLooper(new ALooper), mPlayerFlags(0), mAtEOS(false), Loading Loading @@ -276,14 +274,6 @@ status_t NuPlayerDriver::start() { mPositionUs = -1; } else { mPlayer->resume(); if (mNotifyTimeRealUs != -1) { // Pause time must be set if here by setPauseStartedTimeIfNeeded(). //CHECK(mPauseStartedTimeUs != -1); // if no seek occurs, adjust our notify time so that getCurrentPosition() // is continuous if read immediately after calling start(). mNotifyTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeUs; } } break; } Loading @@ -293,7 +283,6 @@ status_t NuPlayerDriver::start() { } mState = STATE_RUNNING; mPauseStartedTimeUs = -1; return OK; } Loading Loading @@ -322,7 +311,6 @@ status_t NuPlayerDriver::stop() { default: return INVALID_OPERATION; } setPauseStartedTimeIfNeeded(); return OK; } Loading @@ -336,7 +324,6 @@ status_t NuPlayerDriver::pause() { return OK; case STATE_RUNNING: setPauseStartedTimeIfNeeded(); mState = STATE_PAUSED; notifyListener_l(MEDIA_PAUSED); mPlayer->pause(); Loading Loading @@ -374,6 +361,7 @@ status_t NuPlayerDriver::seekTo(int msec) { case STATE_PAUSED: { mAtEOS = false; mSeekInProgress = true; // seeks can take a while, so we essentially paused notifyListener_l(MEDIA_PAUSED); mPlayer->seekToAsync(seekTimeUs, true /* needNotify */); Loading @@ -385,44 +373,23 @@ status_t NuPlayerDriver::seekTo(int msec) { } mPositionUs = seekTimeUs; mNotifyTimeRealUs = -1; return OK; } status_t NuPlayerDriver::getCurrentPosition(int *msec) { Mutex::Autolock autoLock(mLock); int64_t tempUs = 0; status_t ret = mPlayer->getCurrentPosition(&tempUs); if (mPositionUs < 0) { // mPositionUs is the media time. // It is negative under these cases // (1) == -1 after reset, or very first playback, no stream notification yet. // (2) == -1 start after end of stream, no stream notification yet. // (3) == large negative # after ~292,471 years of continuous playback. //CHECK_EQ(mPositionUs, -1); *msec = 0; } else if (mNotifyTimeRealUs == -1) { // A seek has occurred just occurred, no stream notification yet. // mPositionUs (>= 0) is the new media position. *msec = mPositionUs / 1000; Mutex::Autolock autoLock(mLock); // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a // position value that's different the seek to position. if (ret != OK || mSeekInProgress) { tempUs = (mPositionUs <= 0) ? 0 : mPositionUs; } else { // mPosition must be valid (i.e. >= 0) by the first check above. // We're either playing or have pause time set: mPauseStartedTimeUs is >= 0 //LOG_ALWAYS_FATAL_IF( // !isPlaying() && mPauseStartedTimeUs < 0, // "Player in non-playing mState(%d) and mPauseStartedTimeUs(%lld) < 0", // mState, (long long)mPauseStartedTimeUs); ALOG_ASSERT(mNotifyTimeRealUs >= 0); int64_t nowUs = (isPlaying() ? ALooper::GetNowUs() : mPauseStartedTimeUs); *msec = (mPositionUs + nowUs - mNotifyTimeRealUs + 500ll) / 1000; // It is possible for *msec to be negative if the media position is > 596 hours. // but we turn on this checking in NDEBUG == 0 mode. ALOG_ASSERT(*msec >= 0); ALOGV("getCurrentPosition nowUs(%lld)", (long long)nowUs); } ALOGV("getCurrentPosition returning(%d) mPositionUs(%lld) mNotifyRealTimeUs(%lld)", *msec, (long long)mPositionUs, (long long)mNotifyTimeRealUs); mPositionUs = tempUs; } *msec = (int)divRound(tempUs, (int64_t)(1000)); return OK; } Loading Loading @@ -605,17 +572,10 @@ void NuPlayerDriver::notifyDuration(int64_t durationUs) { mDurationUs = durationUs; } void NuPlayerDriver::notifyPosition(int64_t positionUs) { Mutex::Autolock autoLock(mLock); if (isPlaying()) { mPositionUs = positionUs; mNotifyTimeRealUs = ALooper::GetNowUs(); } } void NuPlayerDriver::notifySeekComplete() { ALOGV("notifySeekComplete(%p)", this); Mutex::Autolock autoLock(mLock); mSeekInProgress = false; notifySeekComplete_l(); } Loading @@ -636,26 +596,21 @@ void NuPlayerDriver::notifySeekComplete_l() { notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED); } void NuPlayerDriver::notifyFrameStats( int64_t numFramesTotal, int64_t numFramesDropped) { Mutex::Autolock autoLock(mLock); mNumFramesTotal = numFramesTotal; mNumFramesDropped = numFramesDropped; } status_t NuPlayerDriver::dump( int fd, const Vector<String16> & /* args */) const { Mutex::Autolock autoLock(mLock); int64_t numFramesTotal; int64_t numFramesDropped; mPlayer->getStats(&numFramesTotal, &numFramesDropped); FILE *out = fdopen(dup(fd), "w"); fprintf(out, " NuPlayer\n"); fprintf(out, " numFramesTotal(%" PRId64 "), numFramesDropped(%" PRId64 "), " "percentageDropped(%.2f)\n", mNumFramesTotal, mNumFramesDropped, mNumFramesTotal == 0 ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal); numFramesTotal, numFramesDropped, numFramesTotal == 0 ? 0.0 : (double)numFramesDropped / numFramesTotal); fclose(out); out = NULL; Loading Loading @@ -690,7 +645,6 @@ void NuPlayerDriver::notifyListener_l( case MEDIA_ERROR: { mAtEOS = true; setPauseStartedTimeIfNeeded(); break; } Loading Loading @@ -758,10 +712,4 @@ void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) { mPlayerFlags = flags; } void NuPlayerDriver::setPauseStartedTimeIfNeeded() { if (mPauseStartedTimeUs == -1) { mPauseStartedTimeUs = ALooper::GetNowUs(); } } } // namespace android media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +1 −7 Original line number Diff line number Diff line Loading @@ -68,10 +68,8 @@ struct NuPlayerDriver : public MediaPlayerInterface { void notifyResetComplete(); void notifySetSurfaceComplete(); void notifyDuration(int64_t durationUs); void notifyPosition(int64_t positionUs); void notifySeekComplete(); void notifySeekComplete_l(); void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped); void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL); void notifyFlagsChanged(uint32_t flags); Loading Loading @@ -106,10 +104,7 @@ private: bool mSetSurfaceInProgress; int64_t mDurationUs; int64_t mPositionUs; int64_t mNotifyTimeRealUs; int64_t mPauseStartedTimeUs; int64_t mNumFramesTotal; int64_t mNumFramesDropped; bool mSeekInProgress; // <<< sp<ALooper> mLooper; Loading @@ -125,7 +120,6 @@ private: status_t prepare_l(); void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL); void setPauseStartedTimeIfNeeded(); DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver); }; Loading media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +124 −108 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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(); Loading Loading @@ -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; } Loading @@ -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: Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); } } Loading Loading @@ -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)); Loading @@ -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) { Loading @@ -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); } } Loading Loading @@ -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(); Loading Loading @@ -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"); Loading @@ -852,7 +909,7 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) { prepareForMediaRenderingStart(); if (offloadingAudio()) { mFirstAnchorTimeMediaUs = -1; setAudioFirstAnchorTime(-1); } } Loading Loading @@ -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!"); Loading @@ -990,9 +1011,7 @@ void NuPlayer::Renderer::onPause() { ++mVideoQueueGeneration; prepareForMediaRenderingStart(); mPaused = true; if (!mHasAudio) { mPauseStartedTimeRealUs = ALooper::GetNowUs(); } setPauseStartedTimeRealUs(ALooper::GetNowUs()); } mDrainAudioQueuePending = false; Loading Loading @@ -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()) { Loading @@ -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. Loading Loading @@ -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(); Loading Loading
media/libmediaplayerservice/nuplayer/NuPlayer.cpp +20 −28 Original line number Diff line number Diff line Loading @@ -151,7 +151,6 @@ private: NuPlayer::NuPlayer() : mUIDValid(false), mSourceFlags(0), mCurrentPositionUs(0), mVideoIsAVC(false), mOffloadAudio(false), mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), Loading @@ -169,7 +168,6 @@ NuPlayer::NuPlayer() mFlushingVideo(NONE), mSkipRenderingAudioUntilMediaTimeUs(-1ll), mSkipRenderingVideoUntilMediaTimeUs(-1ll), mVideoLateByUs(0ll), mNumFramesTotal(0ll), mNumFramesDropped(0ll), mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), Loading Loading @@ -546,8 +544,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { // the extractor may not yet be started and will assert. // If the video decoder is not set (perhaps audio only in this case) // do not perform a seek as it is not needed. int64_t currentPositionUs = 0; if (getCurrentPosition(¤tPositionUs) == OK) { mDeferredActions.push_back( new SeekAction(mCurrentPositionUs, false /* needNotify */)); new SeekAction(currentPositionUs, false /* needNotify */)); } } // If there is a new surface texture, instantiate decoders Loading Loading @@ -581,7 +582,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mVideoEOS = false; mSkipRenderingAudioUntilMediaTimeUs = -1; mSkipRenderingVideoUntilMediaTimeUs = -1; mVideoLateByUs = 0; mNumFramesTotal = 0; mNumFramesDropped = 0; mStarted = true; Loading Loading @@ -889,22 +889,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { && (mVideoEOS || mVideoDecoder == NULL)) { notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0); } } else if (what == Renderer::kWhatPosition) { int64_t positionUs; CHECK(msg->findInt64("positionUs", &positionUs)); mCurrentPositionUs = positionUs; CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs)); if (mDriver != NULL) { sp<NuPlayerDriver> driver = mDriver.promote(); if (driver != NULL) { driver->notifyPosition(positionUs); driver->notifyFrameStats( mNumFramesTotal, mNumFramesDropped); } } } else if (what == Renderer::kWhatFlushComplete) { int32_t audio; CHECK(msg->findInt32("audio", &audio)); Loading Loading @@ -1053,10 +1037,6 @@ void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) { case FLUSHING_DECODER: { *state = FLUSHED; if (!audio) { mVideoLateByUs = 0; } break; } Loading @@ -1066,7 +1046,6 @@ void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) { ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video"); if (!audio) { mVideoLateByUs = 0; // Widevine source reads must stop before releasing the video decoder. if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) { mSource->stop(); Loading Loading @@ -1487,7 +1466,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) { dropAccessUnit = false; if (!audio && !(mSourceFlags & Source::FLAG_SECURE) && mVideoLateByUs > 100000ll && mRenderer->getVideoLateByUs() > 100000ll && mVideoIsAVC && !IsAVCReferenceFrame(accessUnit)) { dropAccessUnit = true; Loading Loading @@ -1822,6 +1801,20 @@ status_t NuPlayer::selectTrack(size_t trackIndex, bool select) { return err; } status_t NuPlayer::getCurrentPosition(int64_t *mediaUs) { sp<Renderer> renderer = mRenderer; if (renderer == NULL) { return NO_INIT; } return renderer->getCurrentPosition(mediaUs); } void NuPlayer::getStats(int64_t *numFramesTotal, int64_t *numFramesDropped) { *numFramesTotal = mNumFramesTotal; *numFramesDropped = mNumFramesDropped; } sp<MetaData> NuPlayer::getFileMeta() { return mSource->getFileFormatMeta(); } Loading Loading @@ -1879,7 +1872,6 @@ void NuPlayer::performSeek(int64_t seekTimeUs, bool needNotify) { if (mDriver != NULL) { sp<NuPlayerDriver> driver = mDriver.promote(); if (driver != NULL) { driver->notifyPosition(seekTimeUs); if (needNotify) { driver->notifySeekComplete(); } Loading
media/libmediaplayerservice/nuplayer/NuPlayer.h +2 −2 Original line number Diff line number Diff line Loading @@ -67,6 +67,8 @@ struct NuPlayer : public AHandler { status_t getTrackInfo(Parcel* reply) const; status_t getSelectedTrack(int32_t type, Parcel* reply) const; status_t selectTrack(size_t trackIndex, bool select); status_t getCurrentPosition(int64_t *mediaUs); void getStats(int64_t *mNumFramesTotal, int64_t *mNumFramesDropped); sp<MetaData> getFileMeta(); Loading Loading @@ -126,7 +128,6 @@ private: sp<Source> mSource; uint32_t mSourceFlags; sp<NativeWindowWrapper> mNativeWindow; int64_t mCurrentPositionUs; sp<MediaPlayerBase::AudioSink> mAudioSink; sp<Decoder> mVideoDecoder; bool mVideoIsAVC; Loading Loading @@ -179,7 +180,6 @@ private: int64_t mSkipRenderingAudioUntilMediaTimeUs; int64_t mSkipRenderingVideoUntilMediaTimeUs; int64_t mVideoLateByUs; int64_t mNumFramesTotal, mNumFramesDropped; int32_t mVideoScalingMode; Loading
media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +21 −73 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/ALooper.h> #include <media/stagefright/foundation/AUtils.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> Loading @@ -38,10 +39,7 @@ NuPlayerDriver::NuPlayerDriver() mSetSurfaceInProgress(false), mDurationUs(-1), mPositionUs(-1), mNotifyTimeRealUs(-1), mPauseStartedTimeUs(-1), mNumFramesTotal(0), mNumFramesDropped(0), mSeekInProgress(false), mLooper(new ALooper), mPlayerFlags(0), mAtEOS(false), Loading Loading @@ -276,14 +274,6 @@ status_t NuPlayerDriver::start() { mPositionUs = -1; } else { mPlayer->resume(); if (mNotifyTimeRealUs != -1) { // Pause time must be set if here by setPauseStartedTimeIfNeeded(). //CHECK(mPauseStartedTimeUs != -1); // if no seek occurs, adjust our notify time so that getCurrentPosition() // is continuous if read immediately after calling start(). mNotifyTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeUs; } } break; } Loading @@ -293,7 +283,6 @@ status_t NuPlayerDriver::start() { } mState = STATE_RUNNING; mPauseStartedTimeUs = -1; return OK; } Loading Loading @@ -322,7 +311,6 @@ status_t NuPlayerDriver::stop() { default: return INVALID_OPERATION; } setPauseStartedTimeIfNeeded(); return OK; } Loading @@ -336,7 +324,6 @@ status_t NuPlayerDriver::pause() { return OK; case STATE_RUNNING: setPauseStartedTimeIfNeeded(); mState = STATE_PAUSED; notifyListener_l(MEDIA_PAUSED); mPlayer->pause(); Loading Loading @@ -374,6 +361,7 @@ status_t NuPlayerDriver::seekTo(int msec) { case STATE_PAUSED: { mAtEOS = false; mSeekInProgress = true; // seeks can take a while, so we essentially paused notifyListener_l(MEDIA_PAUSED); mPlayer->seekToAsync(seekTimeUs, true /* needNotify */); Loading @@ -385,44 +373,23 @@ status_t NuPlayerDriver::seekTo(int msec) { } mPositionUs = seekTimeUs; mNotifyTimeRealUs = -1; return OK; } status_t NuPlayerDriver::getCurrentPosition(int *msec) { Mutex::Autolock autoLock(mLock); int64_t tempUs = 0; status_t ret = mPlayer->getCurrentPosition(&tempUs); if (mPositionUs < 0) { // mPositionUs is the media time. // It is negative under these cases // (1) == -1 after reset, or very first playback, no stream notification yet. // (2) == -1 start after end of stream, no stream notification yet. // (3) == large negative # after ~292,471 years of continuous playback. //CHECK_EQ(mPositionUs, -1); *msec = 0; } else if (mNotifyTimeRealUs == -1) { // A seek has occurred just occurred, no stream notification yet. // mPositionUs (>= 0) is the new media position. *msec = mPositionUs / 1000; Mutex::Autolock autoLock(mLock); // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a // position value that's different the seek to position. if (ret != OK || mSeekInProgress) { tempUs = (mPositionUs <= 0) ? 0 : mPositionUs; } else { // mPosition must be valid (i.e. >= 0) by the first check above. // We're either playing or have pause time set: mPauseStartedTimeUs is >= 0 //LOG_ALWAYS_FATAL_IF( // !isPlaying() && mPauseStartedTimeUs < 0, // "Player in non-playing mState(%d) and mPauseStartedTimeUs(%lld) < 0", // mState, (long long)mPauseStartedTimeUs); ALOG_ASSERT(mNotifyTimeRealUs >= 0); int64_t nowUs = (isPlaying() ? ALooper::GetNowUs() : mPauseStartedTimeUs); *msec = (mPositionUs + nowUs - mNotifyTimeRealUs + 500ll) / 1000; // It is possible for *msec to be negative if the media position is > 596 hours. // but we turn on this checking in NDEBUG == 0 mode. ALOG_ASSERT(*msec >= 0); ALOGV("getCurrentPosition nowUs(%lld)", (long long)nowUs); } ALOGV("getCurrentPosition returning(%d) mPositionUs(%lld) mNotifyRealTimeUs(%lld)", *msec, (long long)mPositionUs, (long long)mNotifyTimeRealUs); mPositionUs = tempUs; } *msec = (int)divRound(tempUs, (int64_t)(1000)); return OK; } Loading Loading @@ -605,17 +572,10 @@ void NuPlayerDriver::notifyDuration(int64_t durationUs) { mDurationUs = durationUs; } void NuPlayerDriver::notifyPosition(int64_t positionUs) { Mutex::Autolock autoLock(mLock); if (isPlaying()) { mPositionUs = positionUs; mNotifyTimeRealUs = ALooper::GetNowUs(); } } void NuPlayerDriver::notifySeekComplete() { ALOGV("notifySeekComplete(%p)", this); Mutex::Autolock autoLock(mLock); mSeekInProgress = false; notifySeekComplete_l(); } Loading @@ -636,26 +596,21 @@ void NuPlayerDriver::notifySeekComplete_l() { notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED); } void NuPlayerDriver::notifyFrameStats( int64_t numFramesTotal, int64_t numFramesDropped) { Mutex::Autolock autoLock(mLock); mNumFramesTotal = numFramesTotal; mNumFramesDropped = numFramesDropped; } status_t NuPlayerDriver::dump( int fd, const Vector<String16> & /* args */) const { Mutex::Autolock autoLock(mLock); int64_t numFramesTotal; int64_t numFramesDropped; mPlayer->getStats(&numFramesTotal, &numFramesDropped); FILE *out = fdopen(dup(fd), "w"); fprintf(out, " NuPlayer\n"); fprintf(out, " numFramesTotal(%" PRId64 "), numFramesDropped(%" PRId64 "), " "percentageDropped(%.2f)\n", mNumFramesTotal, mNumFramesDropped, mNumFramesTotal == 0 ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal); numFramesTotal, numFramesDropped, numFramesTotal == 0 ? 0.0 : (double)numFramesDropped / numFramesTotal); fclose(out); out = NULL; Loading Loading @@ -690,7 +645,6 @@ void NuPlayerDriver::notifyListener_l( case MEDIA_ERROR: { mAtEOS = true; setPauseStartedTimeIfNeeded(); break; } Loading Loading @@ -758,10 +712,4 @@ void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) { mPlayerFlags = flags; } void NuPlayerDriver::setPauseStartedTimeIfNeeded() { if (mPauseStartedTimeUs == -1) { mPauseStartedTimeUs = ALooper::GetNowUs(); } } } // namespace android
media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +1 −7 Original line number Diff line number Diff line Loading @@ -68,10 +68,8 @@ struct NuPlayerDriver : public MediaPlayerInterface { void notifyResetComplete(); void notifySetSurfaceComplete(); void notifyDuration(int64_t durationUs); void notifyPosition(int64_t positionUs); void notifySeekComplete(); void notifySeekComplete_l(); void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped); void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL); void notifyFlagsChanged(uint32_t flags); Loading Loading @@ -106,10 +104,7 @@ private: bool mSetSurfaceInProgress; int64_t mDurationUs; int64_t mPositionUs; int64_t mNotifyTimeRealUs; int64_t mPauseStartedTimeUs; int64_t mNumFramesTotal; int64_t mNumFramesDropped; bool mSeekInProgress; // <<< sp<ALooper> mLooper; Loading @@ -125,7 +120,6 @@ private: status_t prepare_l(); void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL); void setPauseStartedTimeIfNeeded(); DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver); }; Loading
media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +124 −108 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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(); Loading Loading @@ -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; } Loading @@ -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: Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading Loading @@ -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); } } Loading Loading @@ -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)); Loading @@ -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) { Loading @@ -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); } } Loading Loading @@ -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(); Loading Loading @@ -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"); Loading @@ -852,7 +909,7 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) { prepareForMediaRenderingStart(); if (offloadingAudio()) { mFirstAnchorTimeMediaUs = -1; setAudioFirstAnchorTime(-1); } } Loading Loading @@ -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!"); Loading @@ -990,9 +1011,7 @@ void NuPlayer::Renderer::onPause() { ++mVideoQueueGeneration; prepareForMediaRenderingStart(); mPaused = true; if (!mHasAudio) { mPauseStartedTimeRealUs = ALooper::GetNowUs(); } setPauseStartedTimeRealUs(ALooper::GetNowUs()); } mDrainAudioQueuePending = false; Loading Loading @@ -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()) { Loading @@ -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. Loading Loading @@ -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(); Loading