From 4cbd44a6caffa7d96579b97f1e207a9defa5cba4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 10 Jun 2013 23:18:08 -0700 Subject: [PATCH 1/2] Add fixes to sceMpegAvcDecodeYCbCr(). It seems a lot like sceMpegAvcDecode(), these are just copy/paste. --- Core/HLE/sceMpeg.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index ec0d6bcfd..a266cc64a 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -756,11 +756,16 @@ int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initAddr) SceMpegAu avcAu; avcAu.read(auAddr); - SceMpegRingBuffer ringbuffer; - Memory::ReadStruct(ctx->mpegRingbufferAddr, &ringbuffer); + SceMpegRingBuffer ringbuffer = {0}; + if (Memory::IsValidAddress(ctx->mpegRingbufferAddr)) { + Memory::ReadStruct(ctx->mpegRingbufferAddr, &ringbuffer); + } else { + ERROR_LOG(HLE, "Bogus mpegringbufferaddr"); + return -1; + } - if (ringbuffer.packetsRead == 0) { - // empty! + if (ringbuffer.packetsRead == 0 || ctx->mediaengine->IsVideoEnd()) { + WARN_LOG(HLE, "sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x): mpeg buffer empty", mpeg, auAddr, bufferAddr, initAddr); return hleDelayResult(MPEG_AVC_DECODE_ERROR_FATAL, "mpeg buffer empty", avcEmptyDelayMs); } @@ -769,15 +774,15 @@ int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initAddr) DEBUG_LOG(HLE, "*buffer = %08x, *init = %08x", buffer, init); if (ctx->mediaengine->stepVideo(ctx->videoPixelMode)) { - // do nothing - ; + // Don't draw here, we'll draw in the Csc func. + ctx->avc.avcFrameStatus = 1; + ctx->videoFrameCount++; + }else { + ctx->avc.avcFrameStatus = 0; } - ringbuffer.packetsFree = std::max(0, ringbuffer.packets - ctx->mediaengine->getBufferedSize() / 2048); avcAu.pts = ctx->mediaengine->getVideoTimeStamp(); - ctx->avc.avcFrameStatus = 1; - ctx->videoFrameCount++; ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS; @@ -787,7 +792,7 @@ int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initAddr) Memory::Write_U32(ctx->avc.avcFrameStatus, initAddr); // 1 = showing, 0 = not showing - DEBUG_LOG(HLE, "UNIMPL sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x)", mpeg, auAddr, bufferAddr, initAddr); + DEBUG_LOG(HLE, "sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x)", mpeg, auAddr, bufferAddr, initAddr); if (ctx->videoFrameCount <= 1) return hleDelayResult(0, "mpeg decode", avcFirstDelayMs); From 2ce4cd245f23d1e31a8c6236267b8825e7f4d802 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 10 Jun 2013 23:18:36 -0700 Subject: [PATCH 2/2] Allow a video end a couple packets from end. Fixes #2206, Patapon 3. Possibly we don't even need this check at all, but I'm not sure. --- Core/HW/MediaEngine.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index c05fc6d54..054f4ebfc 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -399,7 +399,9 @@ bool MediaEngine::stepVideo(int videoPixelMode) { bGetFrame = true; } if (result <= 0 && dataEnd) { - m_isVideoEnd = !bGetFrame && m_readSize >= m_streamSize; + // Sometimes, m_readSize is less than m_streamSize at the end, but not by much. + // This is kinda a hack, but the ringbuffer would have to be prematurely empty too. + m_isVideoEnd = !bGetFrame && m_readSize >= (m_streamSize - 4096); if (m_isVideoEnd) m_decodedPos = m_readSize; break;