mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
Merge pull request #22322 from hrydgard/pace-video-decode
Add PaceVideocodecDecode compat.ini option
This commit is contained in:
6 files changed
+42
-1
No files matched your search
@@ -169,6 +169,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
CheckSetting(iniFile, gameID, "SpriteBorderFix", &flags_.SpriteBorderFix);
|
||||
CheckSetting(iniFile, gameID, "TextureCLUTInShader", &flags_.TextureCLUTInShader);
|
||||
CheckSetting(iniFile, gameID, "DisableRangeCulling", &flags_.DisableRangeCulling);
|
||||
CheckSetting(iniFile, gameID, "PaceVideocodecDecode", &flags_.PaceVideocodecDecode);
|
||||
}
|
||||
|
||||
void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
|
||||
@@ -124,6 +124,7 @@ struct CompatFlags {
|
||||
float SpriteBorderFix;
|
||||
bool TextureCLUTInShader;
|
||||
bool DisableRangeCulling;
|
||||
bool PaceVideocodecDecode;
|
||||
};
|
||||
|
||||
struct VRCompat {
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
|
||||
#include "Common/Serialize/Serializer.h"
|
||||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/HLE/ErrorCodes.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/FunctionWrappers.h"
|
||||
@@ -95,6 +98,9 @@ struct VideocodecCtx {
|
||||
u32 frameBuffersSize = 0;
|
||||
int frameBufferWidth = 0;
|
||||
int frameBufferHeight = 0;
|
||||
// When the next decode may finish, for PaceVideocodecDecode. Not serialized: a restored state
|
||||
// just paces from scratch.
|
||||
s64 pacedUntilUs = 0;
|
||||
};
|
||||
|
||||
static std::map<u32, VideocodecCtx> g_videocodecCtxs;
|
||||
@@ -583,12 +589,25 @@ static int sceVideocodecDecode(u32 ctxAddr, int type) {
|
||||
out32(36, published ? 0 : 1);
|
||||
}
|
||||
|
||||
// This is a compat hack for games that do not seem to pace playback in any way, such as Ys I & II.
|
||||
if (gotFrame && PSP_CoreParameter().compat.flags().PaceVideocodecDecode && vctx.decoder) {
|
||||
const int period = vctx.decoder->FramePeriodUs();
|
||||
if (period > 0) {
|
||||
const s64 now = CoreTiming::GetGlobalTimeUs();
|
||||
const int wait = (int)std::max((s64)0, vctx.pacedUntilUs - now);
|
||||
vctx.pacedUntilUs = now + wait + period;
|
||||
if (wait > 0) {
|
||||
return hleDelayResult(hleLogDebug(Log::ME, 0, "type %d, %d bytes -> frame %dx%d",
|
||||
type, auBytes, width, height), "videocodec decode", wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
return hleLogDebug(Log::ME, 0, "type %d, %d bytes -> %s %dx%d",
|
||||
type, auBytes, gotFrame ? "frame" : "no frame yet", width, height);
|
||||
}
|
||||
|
||||
// Stopping or deleting the decoder is an ME round-trip and takes real time on hardware. Returning
|
||||
// immediately matters beyond speed: a game can be relying on a thread of its own getting to run
|
||||
// immediately is not correct, because a game can be relying on a thread of its own getting to run
|
||||
// once more before it tears things down. Jak and Daxter deletes its video_sound_thread straight
|
||||
// after sceVideocodecDelete without waiting for it to exit, and with no time passing here the audio
|
||||
// thread never gets to deliver the wake that would let it exit - so the delete fails with
|
||||
|
||||
@@ -193,6 +193,17 @@ bool AvcDecoder::Decode(const u8 *data, int size) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int AvcDecoder::FramePeriodUs() const {
|
||||
#ifdef USE_FFMPEG
|
||||
if (!codecCtx_ || codecCtx_->framerate.num <= 0 || codecCtx_->framerate.den <= 0) {
|
||||
return 0;
|
||||
}
|
||||
return (int)((s64)1000000 * codecCtx_->framerate.den / codecCtx_->framerate.num);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
const u8 *AvcDecoder::Plane(int index) const {
|
||||
#ifdef USE_FFMPEG
|
||||
if (!haveFrame_ || !frame_ || index < 0 || index >= 3) {
|
||||
|
||||
@@ -56,6 +56,8 @@ public:
|
||||
// necessarily the width.
|
||||
const u8 *Plane(int index) const;
|
||||
int Stride(int index) const;
|
||||
// The frame period the bitstream declares, in microseconds, or 0 if it says nothing useful.
|
||||
int FramePeriodUs() const;
|
||||
|
||||
// True if we were built without ffmpeg, in which case nothing decodes.
|
||||
static bool IsAvailable();
|
||||
|
||||
@@ -2209,3 +2209,10 @@ UCJS10100 = true
|
||||
UCKS45127 = true
|
||||
UCJS18055 = true
|
||||
NPJG00027 = true
|
||||
|
||||
[PaceVideocodecDecode]
|
||||
# Ys I & II Chronicles - the game never paces the video itself, so an instant decode runs
|
||||
# the picture ahead of the audio and the movie ends early.
|
||||
ULUS10547 = true
|
||||
ULJM05475 = true
|
||||
NPUH10091 = true
|
||||
Reference in new issue
Block a user