From 75e4575ffe2c905c6d4cf8982094cf40731a439c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 22 May 2014 23:40:44 -0700 Subject: [PATCH] Properly schedule psmfplayer video finish. Fixes #2251, hurray. --- Core/HLE/scePsmf.cpp | 52 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 29c09ba5df..ec24e004d5 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -16,6 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Core/HLE/HLE.h" +#include "Core/HLE/HLEHelperThread.h" #include "Core/HLE/FunctionWrappers.h" #include "Common/ChunkFile.h" #include "Core/Reporting.h" @@ -207,6 +208,19 @@ public: ~PsmfPlayer() { if (mediaengine) delete mediaengine; pspFileSystem.CloseFile(filehandle);} void DoState(PointerWrap &p); + void ScheduleFinish(u32 handle) { + if (!finishThread) { + finishThread = new HLEHelperThread("scePsmfPlayer", "scePsmfPlayer", "__PsmfPlayerFinish", playbackThreadPriority, 0x100); + finishThread->Start(handle, 0); + } + } + void AbortFinish() { + if (finishThread) { + delete finishThread; + finishThread = NULL; + } + } + u32 filehandle; u32 fileoffset; int readSize; @@ -236,7 +250,8 @@ public: SceMpegAu psmfPlayerAvcAu; PsmfPlayerStatus status; - MediaEngine* mediaengine; + MediaEngine *mediaengine; + HLEHelperThread *finishThread; }; class PsmfStream { @@ -352,6 +367,7 @@ PsmfPlayer::PsmfPlayer(const PsmfPlayerCreateData *data) { totalDurationTimestamp = 0; status = PSMF_PLAYER_STATUS_INIT; mediaengine = new MediaEngine; + finishThread = NULL; filehandle = 0; fileoffset = 0; readSize = 0; @@ -406,7 +422,7 @@ void Psmf::DoState(PointerWrap &p) { } void PsmfPlayer::DoState(PointerWrap &p) { - auto s = p.Section("PsmfPlayer", 1, 5); + auto s = p.Section("PsmfPlayer", 1, 6); if (!s) return; @@ -463,6 +479,11 @@ void PsmfPlayer::DoState(PointerWrap &p) { p.Do(psmfPlayerAtracAu); } p.Do(psmfPlayerAvcAu); + if (s >= 6) { + p.Do(finishThread); + } else { + finishThread = NULL; + } } void Psmf::setStreamNum(int num) { @@ -1018,6 +1039,7 @@ int scePsmfPlayerStop(u32 psmfPlayer) ERROR_LOG(ME, "scePsmfPlayerStop(%08x): not initialized", psmfPlayer); return ERROR_PSMFPLAYER_INVALID_STATUS; } + psmfplayer->AbortFinish(); INFO_LOG(ME, "scePsmfPlayerStop(%08x)", psmfPlayer); psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; @@ -1038,6 +1060,7 @@ int scePsmfPlayerBreak(u32 psmfPlayer) ERROR_LOG(ME, "scePsmfPlayerBreak(%08x): not initialized", psmfPlayer); return ERROR_PSMFPLAYER_INVALID_STATUS; } + psmfplayer->AbortFinish(); // Fix everybody stress buster psmfplayer->status = PSMF_PLAYER_STATUS_INIT; @@ -1308,6 +1331,7 @@ int scePsmfPlayerStart(u32 psmfPlayer, u32 psmfPlayerData, int initPts) WARN_LOG(ME, "scePsmfPlayerStart(%08x, %08x, %d)", psmfPlayer, psmfPlayerData, initPts); + psmfplayer->AbortFinish(); psmfplayer->mediaengine->setVideoStream(playerData->videoStreamNum); psmfplayer->videoCodec = playerData->videoCodec; psmfplayer->videoStreamNum = playerData->videoStreamNum; @@ -1397,8 +1421,10 @@ int scePsmfPlayerUpdate(u32 psmfPlayer) DEBUG_LOG(ME, "scePsmfPlayerUpdate(%08x)", psmfPlayer); if ((s64)psmfplayer->psmfPlayerAvcAu.pts >= (s64)psmfplayer->totalDurationTimestamp - VIDEO_FRAME_DURATION_TS) { if (videoLoopStatus == PSMF_PLAYER_CONFIG_NO_LOOP && psmfplayer->videoStep >= 1) { - INFO_LOG(ME, "video end reached"); - psmfplayer->status = PSMF_PLAYER_STATUS_PLAYING_FINISHED; + if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING_FINISHED) { + psmfplayer->ScheduleFinish(psmfPlayer); + INFO_LOG(ME, "scePsmfPlayerUpdate(%08x): video end scheduled", psmfPlayer); + } } } psmfplayer->videoStep++; @@ -1934,6 +1960,22 @@ u32 scePsmfPlayerConfigPlayer(u32 psmfPlayer, int configMode, int configAttr) return 0; } +int __PsmfPlayerFinish(u32 psmfPlayer) { + PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); + if (!psmfplayer) { + ERROR_LOG_REPORT(ME, "__PsmfPlayerFinish(%08x): invalid psmf player", psmfPlayer); + return ERROR_PSMFPLAYER_INVALID_STATUS; + } + if (psmfplayer->status != PSMF_PLAYER_STATUS_PLAYING) { + ERROR_LOG_REPORT(ME, "__PsmfPlayerFinish(%08x): unexpected status %d", psmfPlayer, psmfplayer->status); + return ERROR_PSMFPLAYER_INVALID_STATUS; + } + + INFO_LOG(ME, "__PsmfPlayerFinish(%08x): video end reached", psmfPlayer); + psmfplayer->status = PSMF_PLAYER_STATUS_PLAYING_FINISHED; + return 0; +} + const HLEFunction scePsmf[] = { {0xc22c8327, WrapU_UU, "scePsmfSetPsmf"}, {0xC7DB3A5B, WrapU_UUU, "scePsmfGetCurrentStreamType"}, @@ -1992,6 +2034,8 @@ const HLEFunction scePsmfPlayer[] = {0x76C0F4AE, WrapI_UCI, "scePsmfPlayerSetPsmfOffset"}, {0xA72DB4F9, WrapI_UCI, "scePsmfPlayerSetPsmfOffsetCB"}, {0x340c12cb, 0, "scePsmfPlayer_340C12CB"}, + // Fake function for PPSSPP's use. + {0x05b193b7, WrapI_U<__PsmfPlayerFinish>, "__PsmfPlayerFinish"}, }; void Register_scePsmf() {