mirror of
				https://github.com/RetroDECK/ES-DE.git
				synced 2025-04-10 19:15:13 +00:00 
			
		
		
		
	Added 'iterationCount' and 'onIterationsDone' properties to the video element
This commit is contained in:
		
							parent
							
								
									89d94bc1b0
								
							
						
					
					
						commit
						c15aa73de2
					
				|  | @ -88,7 +88,7 @@ bool MediaViewer::startMediaViewer(FileData* game) | |||
| void MediaViewer::stopMediaViewer() | ||||
| { | ||||
|     NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); | ||||
|     ViewController::getInstance()->stopViewVideos(); | ||||
|     ViewController::getInstance()->startViewVideos(); | ||||
| 
 | ||||
|     mVideoFile = ""; | ||||
|     mVideo.reset(); | ||||
|  |  | |||
|  | @ -48,7 +48,7 @@ bool PDFViewer::startPDFViewer(FileData* game) | |||
|         LOG(LogError) << "Couldn't find PDF conversion binary es-pdf-convert"; | ||||
| #endif | ||||
|         NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); | ||||
|         ViewController::getInstance()->stopViewVideos(); | ||||
|         ViewController::getInstance()->startViewVideos(); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -58,7 +58,7 @@ bool PDFViewer::startPDFViewer(FileData* game) | |||
|     if (!Utils::FileSystem::exists(mManualPath)) { | ||||
|         LOG(LogError) << "No PDF manual found for game \"" << mGame->getName() << "\""; | ||||
|         NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); | ||||
|         ViewController::getInstance()->stopViewVideos(); | ||||
|         ViewController::getInstance()->startViewVideos(); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -89,7 +89,7 @@ bool PDFViewer::startPDFViewer(FileData* game) | |||
| 
 | ||||
|     if (!getDocumentInfo()) { | ||||
|         LOG(LogError) << "PDFViewer: Couldn't load file \"" << mManualPath << "\""; | ||||
|         ViewController::getInstance()->stopViewVideos(); | ||||
|         ViewController::getInstance()->startViewVideos(); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|  | @ -98,7 +98,7 @@ bool PDFViewer::startPDFViewer(FileData* game) | |||
|     for (int i {1}; i <= mPageCount; ++i) { | ||||
|         if (mPages.find(i) == mPages.end()) { | ||||
|             LOG(LogError) << "Couldn't read information for page " << i << ", invalid PDF file?"; | ||||
|             ViewController::getInstance()->stopViewVideos(); | ||||
|             ViewController::getInstance()->startViewVideos(); | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|  | @ -183,7 +183,7 @@ bool PDFViewer::startPDFViewer(FileData* game) | |||
| void PDFViewer::stopPDFViewer() | ||||
| { | ||||
|     NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); | ||||
|     ViewController::getInstance()->stopViewVideos(); | ||||
|     ViewController::getInstance()->startViewVideos(); | ||||
| 
 | ||||
|     mPages.clear(); | ||||
|     mPageImage.reset(); | ||||
|  |  | |||
|  | @ -305,6 +305,8 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> | |||
|        {"metadataElement", BOOLEAN}, | ||||
|        {"gameselector", STRING}, | ||||
|        {"gameselectorEntry", UNSIGNED_INTEGER}, | ||||
|        {"iterationCount", UNSIGNED_INTEGER}, | ||||
|        {"onIterationsDone", STRING}, | ||||
|        {"audio", BOOLEAN}, | ||||
|        {"interpolation", STRING}, | ||||
|        {"color", COLOR}, | ||||
|  |  | |||
|  | @ -31,6 +31,7 @@ VideoComponent::VideoComponent() | |||
|     , mTopLeftCrop {0.0f, 0.0f} | ||||
|     , mBottomRightCrop {1.0f, 1.0f} | ||||
|     , mPillarboxThreshold {0.85f, 0.90f} | ||||
|     , mOnIterationsDone {OnIterationsDone::NOTHING} | ||||
|     , mStartTime {0} | ||||
|     , mIsPlaying {false} | ||||
|     , mIsActuallyPlaying {false} | ||||
|  | @ -46,6 +47,8 @@ VideoComponent::VideoComponent() | |||
|     , mGeneralFade {false} | ||||
|     , mFadeIn {1.0f} | ||||
|     , mFadeInTime {1000.0f} | ||||
|     , mIterationCount {0} | ||||
|     , mPlayCount {0} | ||||
| { | ||||
|     // Setup default configuration.
 | ||||
|     mConfig.showStaticImageDelay = false; | ||||
|  | @ -186,6 +189,23 @@ void VideoComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, | |||
|     if (elem->has("metadataElement") && elem->get<bool>("metadataElement")) | ||||
|         mComponentThemeFlags |= ComponentThemeFlags::METADATA_ELEMENT; | ||||
| 
 | ||||
|     if (elem->has("iterationCount")) { | ||||
|         mIterationCount = glm::clamp(elem->get<unsigned int>("iterationCount"), 0u, 10u); | ||||
| 
 | ||||
|         if (properties && elem->has("onIterationsDone")) { | ||||
|             const std::string& onIterationsDone {elem->get<std::string>("onIterationsDone")}; | ||||
|             if (onIterationsDone == "nothing") | ||||
|                 mOnIterationsDone = OnIterationsDone::NOTHING; | ||||
|             else if (onIterationsDone == "image") | ||||
|                 mOnIterationsDone = OnIterationsDone::IMAGE; | ||||
|             else | ||||
|                 LOG(LogWarning) << "VideoComponent: Invalid theme configuration, property " | ||||
|                                    "\"onIterationsDone\" for element \"" | ||||
|                                 << element.substr(6) << "\" defined as \"" << onIterationsDone | ||||
|                                 << "\""; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (elem->has("audio")) | ||||
|         mPlayAudio = elem->get<bool>("audio"); | ||||
| 
 | ||||
|  | @ -343,6 +363,9 @@ std::vector<HelpPrompt> VideoComponent::getHelpPrompts() | |||
| 
 | ||||
| void VideoComponent::update(int deltaTime) | ||||
| { | ||||
|     if (mIterationCount != 0 && mPlayCount == mIterationCount) | ||||
|         return; | ||||
| 
 | ||||
|     // A deltaTime value of 0 would lead to mFadeIn being an invalid number which would prevent
 | ||||
|     // the video from being rendered. This can happen on application startup in some instances.
 | ||||
|     if (deltaTime == 0) | ||||
|  | @ -397,6 +420,8 @@ void VideoComponent::update(int deltaTime) | |||
| 
 | ||||
| void VideoComponent::startVideoPlayer() | ||||
| { | ||||
|     mPlayCount = 0; | ||||
| 
 | ||||
|     if (mIsPlaying) | ||||
|         stopVideoPlayer(); | ||||
| 
 | ||||
|  | @ -408,9 +433,9 @@ void VideoComponent::startVideoPlayer() | |||
|     mPaused = false; | ||||
| } | ||||
| 
 | ||||
| void VideoComponent::renderStaticImage(const glm::mat4& parentTrans) | ||||
| void VideoComponent::renderStaticImage(const glm::mat4& parentTrans, bool forceRender) | ||||
| { | ||||
|     if (mHasVideo && (!mConfig.showStaticImageDelay || mConfig.startDelay == 0)) | ||||
|     if (mHasVideo && (!forceRender && (!mConfig.showStaticImageDelay || mConfig.startDelay == 0))) | ||||
|         return; | ||||
| 
 | ||||
|     if (mStaticImagePath != "") { | ||||
|  |  | |||
|  | @ -92,7 +92,12 @@ public: | |||
| 
 | ||||
| protected: | ||||
|     virtual void startVideoStream() {} | ||||
|     void renderStaticImage(const glm::mat4& parentTrans); | ||||
|     void renderStaticImage(const glm::mat4& parentTrans, bool forceRender); | ||||
| 
 | ||||
|     enum class OnIterationsDone { | ||||
|         NOTHING, | ||||
|         IMAGE | ||||
|     }; | ||||
| 
 | ||||
|     ImageComponent mStaticImage; | ||||
| 
 | ||||
|  | @ -116,6 +121,7 @@ protected: | |||
|         "cover", "backcover", "3dbox",   "physicalmedia", "fanart"}; | ||||
| 
 | ||||
|     std::string mVideoPath; | ||||
|     OnIterationsDone mOnIterationsDone; | ||||
|     unsigned mStartTime; | ||||
|     std::atomic<bool> mIsPlaying; | ||||
|     std::atomic<bool> mIsActuallyPlaying; | ||||
|  | @ -131,6 +137,8 @@ protected: | |||
|     bool mGeneralFade; | ||||
|     float mFadeIn; | ||||
|     float mFadeInTime; | ||||
|     int mIterationCount; | ||||
|     int mPlayCount; | ||||
| 
 | ||||
|     Configuration mConfig; | ||||
| }; | ||||
|  |  | |||
|  | @ -165,6 +165,12 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans) | |||
|     if (!mHasVideo && mStaticImagePath == "") | ||||
|         return; | ||||
| 
 | ||||
|     if (mIterationCount != 0 && mPlayCount == mIterationCount) { | ||||
|         if (mOnIterationsDone == OnIterationsDone::IMAGE) | ||||
|             VideoComponent::renderStaticImage(parentTrans, true); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     glm::mat4 trans {parentTrans * getTransform()}; | ||||
|     GuiComponent::renderChildren(trans); | ||||
| 
 | ||||
|  | @ -203,7 +209,7 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans) | |||
|         vertices[3].color = mColorShiftEnd; | ||||
| 
 | ||||
|         // Round vertices.
 | ||||
|         for (int i = 0; i < 4; ++i) | ||||
|         for (int i {0}; i < 4; ++i) | ||||
|             vertices[i].position = glm::round(vertices[i].position); | ||||
| 
 | ||||
|         if (mFadeIn < 1.0f || mThemeOpacity < 1.0f) | ||||
|  | @ -265,8 +271,7 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans) | |||
|                                       Renderer::BlendFactor::ONE_MINUS_SRC_ALPHA); | ||||
|     } | ||||
|     else { | ||||
|         if (mVisible) | ||||
|             VideoComponent::renderStaticImage(parentTrans); | ||||
|         VideoComponent::renderStaticImage(parentTrans, false); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | @ -647,7 +652,7 @@ void VideoFFmpegComponent::readFrames() | |||
|     } | ||||
| 
 | ||||
|     if (mVideoCodecContext && mFormatContext) { | ||||
|         for (int i = 0; i < readLoops; ++i) { | ||||
|         for (int i {0}; i < readLoops; ++i) { | ||||
|             if (static_cast<int>(mVideoFrameQueue.size()) < mVideoTargetQueueSize || | ||||
|                 (mAudioStreamIndex >= 0 && | ||||
|                  static_cast<int>(mAudioFrameQueue.size()) < mAudioTargetQueueSize)) { | ||||
|  | @ -1152,7 +1157,7 @@ bool VideoFFmpegComponent::decoderInitHW() | |||
|     } | ||||
| 
 | ||||
|     // 50 is just an arbitrary number so we don't potentially get stuck in an endless loop.
 | ||||
|     for (int i = 0; i < 50; ++i) { | ||||
|     for (int i {0}; i < 50; ++i) { | ||||
|         const AVCodecHWConfig* config {avcodec_get_hw_config(mHardwareCodec, i)}; | ||||
|         if (!config) { | ||||
|             LOG(LogDebug) << "VideoFFmpegComponent::decoderInitHW(): Hardware decoder \"" | ||||
|  | @ -1245,7 +1250,7 @@ bool VideoFFmpegComponent::decoderInitHW() | |||
|                     // For some videos we need to process at least one extra frame to verify
 | ||||
|                     // that the hardware encoder can actually be used, otherwise the fallback
 | ||||
|                     // to software decoding would take place when it's not necessary.
 | ||||
|                     for (int i = 0; i < 3; ++i) { | ||||
|                     for (int i {0}; i < 3; ++i) { | ||||
|                         if (avcodec_receive_frame(checkCodecContext, checkFrame) < 0) { | ||||
|                             av_packet_unref(checkPacket); | ||||
|                             while (av_read_frame(mFormatContext, checkPacket) == 0) { | ||||
|  | @ -1611,13 +1616,14 @@ void VideoFFmpegComponent::pauseVideoPlayer() | |||
| void VideoFFmpegComponent::handleLooping() | ||||
| { | ||||
|     if (mIsPlaying && mEndOfVideo) { | ||||
|         ++mPlayCount; | ||||
|         // If the screensaver video swap time is set to 0, it means we should
 | ||||
|         // skip to the next game when the video has finished playing.
 | ||||
|         if (mScreensaverMode && | ||||
|             Settings::getInstance()->getInt("ScreensaverSwapVideoTimeout") == 0) { | ||||
|             mWindow->screensaverTriggerNextGame(); | ||||
|         } | ||||
|         else { | ||||
|         else if (mIterationCount == 0 || mPlayCount < mIterationCount) { | ||||
|             stopVideoPlayer(); | ||||
|             startVideoStream(); | ||||
|         } | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Leon Styhre
						Leon Styhre