From 5300e54295f927d6251b7e83c84644af52e3a02d Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Sun, 15 Sep 2024 11:34:28 +0200 Subject: [PATCH] Video player resources are now completely freed up after finishing view transitions --- es-app/src/views/GamelistView.cpp | 9 ++++++ es-app/src/views/GamelistView.h | 1 + es-app/src/views/SystemView.cpp | 31 ++++++++++++++++--- es-app/src/views/SystemView.h | 1 + es-app/src/views/ViewController.cpp | 14 +++++++++ .../src/components/VideoFFmpegComponent.cpp | 2 +- 6 files changed, 53 insertions(+), 5 deletions(-) diff --git a/es-app/src/views/GamelistView.cpp b/es-app/src/views/GamelistView.cpp index ce9871cab..9edd980d5 100644 --- a/es-app/src/views/GamelistView.cpp +++ b/es-app/src/views/GamelistView.cpp @@ -96,6 +96,15 @@ void GamelistView::onShow() mPrimary->onShowPrimary(); } +void GamelistView::onHide() +{ + for (auto& video : mVideoComponents) + video->stopVideoPlayer(false); + + for (auto& video : mStaticVideoComponents) + video->stopVideoPlayer(false); +} + void GamelistView::onTransition() { for (auto& animation : mLottieAnimComponents) diff --git a/es-app/src/views/GamelistView.h b/es-app/src/views/GamelistView.h index 68f4c7504..a58426a1e 100644 --- a/es-app/src/views/GamelistView.h +++ b/es-app/src/views/GamelistView.h @@ -23,6 +23,7 @@ public: // Called when a FileData* is added, has its metadata changed, or is removed. void onFileChanged(FileData* file, bool reloadGamelist) override; void onShow() override; + void onHide() override; void onTransition() override; void preloadGamelist() { updateView(CursorState::CURSOR_STOPPED); } diff --git a/es-app/src/views/SystemView.cpp b/es-app/src/views/SystemView.cpp index ffb19c4ff..03610444e 100644 --- a/es-app/src/views/SystemView.cpp +++ b/es-app/src/views/SystemView.cpp @@ -50,6 +50,12 @@ void SystemView::onShow() mPrimary->onShowPrimary(); } +void SystemView::onHide() +{ + for (auto& video : mSystemElements[mPrimary->getCursor()].videoComponents) + video->stopVideoPlayer(false); +} + void SystemView::onTransition() { for (auto& anim : mSystemElements[mPrimary->getCursor()].lottieAnimComponents) @@ -284,8 +290,14 @@ void SystemView::onCursorChanged(const CursorState& state) } if (mLastCursor >= 0 && mLastCursor <= static_cast(mSystemElements.size())) { - for (auto& video : mSystemElements[mLastCursor].videoComponents) - video->pauseVideoPlayer(); + if (transitionAnim == ViewTransitionAnimation::INSTANT || isAnimationPlaying(0)) { + for (auto& video : mSystemElements[mLastCursor].videoComponents) + video->stopVideoPlayer(false); + } + else { + for (auto& video : mSystemElements[mLastCursor].videoComponents) + video->pauseVideoPlayer(); + } } for (auto& container : mSystemElements[mPrimary->getCursor()].containerComponents) @@ -316,6 +328,7 @@ void SystemView::onCursorChanged(const CursorState& state) mCamOffset = static_cast(cursor); } + const int prevLastCursor {mLastCursor}; mLastCursor = cursor; for (auto& video : mSystemElements[cursor].videoComponents) @@ -390,7 +403,7 @@ void SystemView::onCursorChanged(const CursorState& state) if (transitionAnim == ViewTransitionAnimation::FADE) { float startFade {mFadeOpacity}; anim = new LambdaAnimation( - [this, startFade, endPos](float t) { + [this, startFade, endPos, prevLastCursor](float t) { if (t < 0.3f) mFadeOpacity = glm::mix(0.0f, 1.0f, glm::clamp(t / 0.2f + startFade, 0.0f, 1.0f)); @@ -405,6 +418,11 @@ void SystemView::onCursorChanged(const CursorState& state) if (mNavigated && t >= 0.7f && t != 1.0f) mMaxFade = true; + if (t == 1.0f && prevLastCursor >= 0) { + for (auto& video : mSystemElements[prevLastCursor].videoComponents) + video->stopVideoPlayer(false); + } + // Update the game count when the entire animation has been completed. if (mFadeOpacity == 1.0f) { mMaxFade = false; @@ -416,7 +434,7 @@ void SystemView::onCursorChanged(const CursorState& state) else if (transitionAnim == ViewTransitionAnimation::SLIDE) { mUpdatedGameCount = false; anim = new LambdaAnimation( - [this, startPos, endPos, posMax](float t) { + [this, startPos, endPos, posMax, prevLastCursor](float t) { // Non-linear interpolation. t = 1.0f - (1.0f - t) * (1.0f - t); float f {(endPos * t) + (startPos * (1.0f - t))}; @@ -428,6 +446,11 @@ void SystemView::onCursorChanged(const CursorState& state) mCamOffset = f; + if (t == 1.0f && prevLastCursor >= 0) { + for (auto& video : mSystemElements[prevLastCursor].videoComponents) + video->stopVideoPlayer(false); + } + // Hack to make the game count being updated in the middle of the animation. bool update {false}; if (endPos == -1.0f && fabs(fabs(posMax) - fabs(mCamOffset)) > 0.5f && diff --git a/es-app/src/views/SystemView.h b/es-app/src/views/SystemView.h index 08b3e404e..49ebc3f5e 100644 --- a/es-app/src/views/SystemView.h +++ b/es-app/src/views/SystemView.h @@ -38,6 +38,7 @@ public: SystemView(); void onShow() override; + void onHide() override; void onTransition() override; void goToSystem(SystemData* system, bool animate); diff --git a/es-app/src/views/ViewController.cpp b/es-app/src/views/ViewController.cpp index 9cf7b59fa..a91c49b31 100644 --- a/es-app/src/views/ViewController.cpp +++ b/es-app/src/views/ViewController.cpp @@ -731,6 +731,14 @@ void ViewController::goToGamelist(SystemData* system) bool slideTransitions {false}; bool fadeTransitions {false}; + // Special case where we moved to another gamelist while the system to gamelist animation + // was still playing, in this case we need to explictly call onHide() so that all system view + // videos are stopped. + if (mState.previouslyViewed == ViewMode::SYSTEM_SELECT && + mState.viewing == ViewMode::GAMELIST && isAnimationPlaying(0)) { + getSystemListView()->onHide(); + } + if (mCurrentView != nullptr) mCurrentView->onTransition(); @@ -926,6 +934,8 @@ void ViewController::playViewTransition(ViewTransition transitionType, bool inst this->mCamera[3].x = -target.x; this->mCamera[3].y = -target.y; this->mCamera[3].z = -target.z; + if (mState.previouslyViewed == ViewMode::SYSTEM_SELECT) + getSystemListView()->onHide(); if (mPreviousView) mPreviousView->onHide(); }, @@ -946,6 +956,8 @@ void ViewController::playViewTransition(ViewTransition transitionType, bool inst }; auto fadeCallback = [this]() { + if (mState.previouslyViewed == ViewMode::SYSTEM_SELECT || mSystemViewTransition) + getSystemListView()->onHide(); if (mPreviousView) mPreviousView->onHide(); }; @@ -975,6 +987,8 @@ void ViewController::playViewTransition(ViewTransition transitionType, bool inst } else if (transitionAnim == ViewTransitionAnimation::SLIDE) { auto slideCallback = [this]() { + if (mState.previouslyViewed == ViewMode::SYSTEM_SELECT || mSystemViewTransition) + getSystemListView()->onHide(); if (mSkipView) { mSkipView->onHide(); mSkipView.reset(); diff --git a/es-core/src/components/VideoFFmpegComponent.cpp b/es-core/src/components/VideoFFmpegComponent.cpp index 913485686..db6c4e5f3 100644 --- a/es-core/src/components/VideoFFmpegComponent.cpp +++ b/es-core/src/components/VideoFFmpegComponent.cpp @@ -1662,7 +1662,7 @@ void VideoFFmpegComponent::stopVideoPlayer(bool muteAudio) std::queue().swap(mAudioFrameQueue); // Clear the audio buffer. - if (AudioManager::sAudioDevice != 0) + if (muteAudio && AudioManager::sAudioDevice != 0) AudioManager::getInstance().clearStream(); if (mFormatContext) {