From c913f924271688810f7fddbd30a9102e85d1a129 Mon Sep 17 00:00:00 2001 From: oioitff Date: Tue, 4 Jun 2013 20:25:03 +0800 Subject: [PATCH] More improvement for mpeg pts. The mpeglastTimeStamp is probably wrong in some videos. So a video is end only if there is no more data for decoding. --- Core/HLE/sceMpeg.cpp | 4 ++-- Core/HW/MediaEngine.cpp | 9 +++++++-- Core/HW/MediaEngine.h | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 8eb4d21da..84a8c57a0 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -975,7 +975,7 @@ int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) int result = 0; sceAu.pts = ctx->mediaengine->getVideoTimeStamp(); - if (sceAu.pts >= ctx->mediaengine->getLastTimeStamp()) { + if (ctx->mediaengine->IsVideoEnd()) { INFO_LOG(HLE, "video end reach. pts: %i dts: %i", (int)sceAu.pts, (int)ctx->mediaengine->getLastTimeStamp()); mpegRingbuffer.packetsFree = mpegRingbuffer.packets; Memory::WriteStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer); @@ -1039,7 +1039,7 @@ int sceMpegGetAtracAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) int result = 0; sceAu.pts = ctx->mediaengine->getAudioTimeStamp(); - if (sceAu.pts >= ctx->mediaengine->getLastTimeStamp()) { + if (ctx->mediaengine->IsVideoEnd()) { INFO_LOG(HLE, "video end reach. pts: %i dts: %i", (int)sceAu.pts, (int)ctx->mediaengine->getLastTimeStamp()); mpegRingbuffer.packetsFree = mpegRingbuffer.packets; Memory::WriteStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer); diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 2b98f1a90..f7f26fa04 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -91,6 +91,7 @@ MediaEngine::MediaEngine(): m_streamSize(0), m_readSize(0), m_pdata(0) { m_buffer = 0; m_demux = 0; m_audioContext = 0; + m_isVideoEnd = false; } MediaEngine::~MediaEngine() { @@ -128,6 +129,7 @@ void MediaEngine::closeMedia() { m_pdata = 0; m_demux = 0; Atrac3plus_Decoder::CloseContext(&m_audioContext); + m_isVideoEnd = false; } int _MpegReadbuffer(void *opaque, uint8_t *buf, int buf_size) @@ -208,6 +210,7 @@ bool MediaEngine::openContext() { m_demux->demux(); m_audioPos = 0; m_audioContext = Atrac3plus_Decoder::OpenContext(); + m_isVideoEnd = false; #endif // USE_FFMPEG return true; } @@ -362,13 +365,15 @@ bool MediaEngine::stepVideo(int videoPixelMode) { if(frameFinished) { int firstTimeStamp = bswap32(*(int*)(m_pdata + 86)); - m_videopts = packet.pts + packet.duration - firstTimeStamp; + m_videopts = pFrame->pkt_dts + pFrame->pkt_duration - firstTimeStamp; bGetFrame = true; } } av_free_packet(&packet); if (bGetFrame) break; } + if (!bGetFrame && m_readSize >= m_streamSize) + m_isVideoEnd = true; return bGetFrame; #else return true; @@ -552,7 +557,7 @@ s64 MediaEngine::getVideoTimeStamp() { s64 MediaEngine::getAudioTimeStamp() { if (m_demux) - return m_audiopts; + return std::max(m_audiopts - 4180, (s64)0); return m_videopts; } diff --git a/Core/HW/MediaEngine.h b/Core/HW/MediaEngine.h index 958518cba..7af600096 100644 --- a/Core/HW/MediaEngine.h +++ b/Core/HW/MediaEngine.h @@ -58,6 +58,8 @@ public: s64 getAudioTimeStamp(); s64 getLastTimeStamp(); + bool IsVideoEnd() { return m_isVideoEnd;} + void DoState(PointerWrap &p) { p.Do(m_streamSize); p.Do(m_readSize); @@ -93,4 +95,6 @@ public: int m_audioPos; void* m_audioContext; s64 m_audiopts; + + bool m_isVideoEnd; };