From c970a7e689a8a75ed24a0048f8013d16d208ee30 Mon Sep 17 00:00:00 2001 From: oioitff Date: Sun, 16 Jun 2013 03:27:14 +0800 Subject: [PATCH 1/7] Use ringbuffer as a real PSP instead huge buffer. --- Core/HLE/sceMpeg.cpp | 10 ++- Core/HLE/scePsmf.cpp | 48 ++++++++++-- Core/HW/MediaEngine.cpp | 157 +++++++++------------------------------- Core/HW/MediaEngine.h | 16 ++-- Core/HW/MpegDemux.cpp | 82 ++++++++++++++++----- Core/HW/MpegDemux.h | 25 +++++-- Core/HW/atrac3plus.h | 30 ++++++++ 7 files changed, 198 insertions(+), 170 deletions(-) diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 0f9d1d7c7e..75503dc383 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -271,7 +271,11 @@ void AnalyzeMpeg(u32 buffer_addr, MpegContext *ctx) { if (ctx->mediaengine && (ctx->mpegStreamSize > 0) && !ctx->isAnalyzed) { // init mediaEngine - ctx->mediaengine->loadStream(Memory::GetPointer(buffer_addr), ctx->mpegOffset, ctx->mpegOffset + ctx->mpegStreamSize); + SceMpegRingBuffer ringbuffer = {0}; + if(ctx->mpegRingbufferAddr != 0){ + Memory::ReadStruct(ctx->mpegRingbufferAddr, &ringbuffer); + }; + ctx->mediaengine->loadStream(Memory::GetPointer(buffer_addr), ctx->mpegOffset, ringbuffer.packets * ringbuffer.packetSize); ctx->mediaengine->setVideoDim(); } // When used with scePsmf, some applications attempt to use sceMpegQueryStreamOffset @@ -643,7 +647,7 @@ u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 i } else { ctx->avc.avcFrameStatus = 0; } - ringbuffer.packetsFree = std::max(0, ringbuffer.packets - ctx->mediaengine->getBufferedSize() / 2048); + ringbuffer.packetsFree = ctx->mediaengine->getRemainSize() / 2048; avcAu.pts = ctx->mediaengine->getVideoTimeStamp() + ctx->mpegFirstTimestamp; @@ -788,7 +792,7 @@ int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initAddr) }else { ctx->avc.avcFrameStatus = 0; } - ringbuffer.packetsFree = std::max(0, ringbuffer.packets - ctx->mediaengine->getBufferedSize() / 2048); + ringbuffer.packetsFree = ctx->mediaengine->getRemainSize() / 2048; avcAu.pts = ctx->mediaengine->getVideoTimeStamp() + ctx->mpegFirstTimestamp; diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 651f2b4834..d57d1488db 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -156,11 +156,15 @@ public: class PsmfPlayer { public: // For savestates only. - PsmfPlayer() { mediaengine = new MediaEngine;} + PsmfPlayer() { mediaengine = new MediaEngine; filehandle = 0;} PsmfPlayer(u32 data); - ~PsmfPlayer() { if (mediaengine) delete mediaengine;} + ~PsmfPlayer() { if (mediaengine) delete mediaengine; pspFileSystem.CloseFile(filehandle);} void DoState(PointerWrap &p); + u32 filehandle; + u32 tempbuf; + u32 tempbufSize; + int videoCodec; int videoStreamNum; int audioCodec; @@ -276,6 +280,9 @@ PsmfPlayer::PsmfPlayer(u32 data) { psmfPlayerLastTimestamp = getMpegTimeStamp(Memory::GetPointer(data + PSMF_LAST_TIMESTAMP_OFFSET)) ; status = PSMF_PLAYER_STATUS_INIT; mediaengine = new MediaEngine; + filehandle = 0; + tempbuf = 0; + tempbufSize = 0; } void Psmf::DoState(PointerWrap &p) { @@ -321,6 +328,9 @@ void PsmfPlayer::DoState(PointerWrap &p) { p.Do(psmfMaxAheadTimestamp); p.Do(psmfPlayerLastTimestamp); p.DoClass(mediaengine); + p.Do(filehandle); + p.Do(tempbuf); + p.Do(tempbufSize); p.DoMarker("PsmfPlayer"); } @@ -763,8 +773,14 @@ int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) { INFO_LOG(HLE, "scePsmfPlayerSetPsmf(%08x, %s)", psmfPlayer, filename); psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; - psmfplayer->mediaengine->loadFile(filename); - psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); + psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); + if (psmfplayer->filehandle && psmfplayer->tempbuf) { + u8* buf = Memory::GetPointer(psmfplayer->tempbuf); + int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, psmfplayer->tempbufSize); + if (size) + psmfplayer->mediaengine->loadStream(buf, size, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); + psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); + } } else { @@ -782,8 +798,14 @@ int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) { INFO_LOG(HLE, "scePsmfPlayerSetPsmfCB(%08x, %s)", psmfPlayer, filename); psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; - psmfplayer->mediaengine->loadFile(filename); - psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); + psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); + if (psmfplayer->filehandle && psmfplayer->tempbuf) { + u8* buf = Memory::GetPointer(psmfplayer->tempbuf); + int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, psmfplayer->tempbufSize); + if (size) + psmfplayer->mediaengine->loadStream(buf, size, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); + psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); + } } else { @@ -900,6 +922,13 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) Memory::Write_U32(psmfplayer->psmfPlayerAvcAu.pts, videoDataAddr + 8); } + int addSize = std::min(psmfplayer->mediaengine->getRemainSize(), (int)psmfplayer->tempbufSize); + if (psmfplayer->filehandle && psmfplayer->tempbuf && addSize > 0) { + u8* buf = Memory::GetPointer(psmfplayer->tempbuf); + int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, addSize); + if (size) + psmfplayer->mediaengine->addStreamData(buf, size); + } int ret = psmfplayer->mediaengine->IsVideoEnd() ? ERROR_PSMFPLAYER_NO_MORE_DATA : 0; s64 deltapts = psmfplayer->mediaengine->getVideoTimeStamp() - psmfplayer->mediaengine->getAudioTimeStamp(); @@ -1036,10 +1065,13 @@ u32 scePsmfPlayerGetCurrentAudioStream(u32 psmfPlayer, u32 audioCodecAddr, u32 a int scePsmfPlayerSetTempBuf(u32 psmfPlayer, u32 tempBufAddr, u32 tempBufSize) { - ERROR_LOG(HLE, "UNIMPL scePsmfPlayerSetTempBuf(%08x, %08x, %08x)", psmfPlayer, tempBufAddr, tempBufSize); + INFO_LOG(HLE, "scePsmfPlayerSetTempBuf(%08x, %08x, %08x)", psmfPlayer, tempBufAddr, tempBufSize); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); - if (psmfplayer) + if (psmfplayer) { psmfplayer->status = PSMF_PLAYER_STATUS_INIT; + psmfplayer->tempbuf = tempBufAddr; + psmfplayer->tempbufSize = tempBufSize; + } return 0; } diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 92bc603a57..625921e111 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -80,7 +80,7 @@ static int getPixelFormatBytes(int pspFormat) } } -MediaEngine::MediaEngine(): m_streamSize(0), m_readSize(0), m_decodedPos(0), m_pdata(0) { +MediaEngine::MediaEngine(): m_pdata(0) { m_pFormatCtx = 0; m_pCodecCtx = 0; m_pFrame = 0; @@ -117,7 +117,7 @@ void MediaEngine::closeMedia() { avformat_close_input(&m_pFormatCtx); #endif // USE_FFMPEG if (m_pdata) - delete [] m_pdata; + delete m_pdata; if (m_demux) delete m_demux; m_buffer = 0; @@ -136,21 +136,8 @@ void MediaEngine::closeMedia() { int _MpegReadbuffer(void *opaque, uint8_t *buf, int buf_size) { MediaEngine *mpeg = (MediaEngine *)opaque; - if ((u32)mpeg->m_decodeNextPos > (u32)mpeg->m_streamSize) - return -1; - int size = std::min(mpeg->m_bufSize, buf_size); - int available = mpeg->m_readSize - mpeg->m_decodeNextPos; - int remaining = mpeg->m_streamSize - mpeg->m_decodeNextPos; - - // There's more in the file, and there's not as much as requested available. - // Return nothing. Partial packets will cause artifacts or green frames. - if (available < remaining && size > available) - return 0; - - size = std::min(size, remaining); - if (size > 0) - memcpy(buf, mpeg->m_pdata + mpeg->m_decodeNextPos, size); + int size = mpeg->m_pdata->pop_front(buf, buf_size); mpeg->m_decodeNextPos += size; return size; } @@ -166,14 +153,14 @@ int64_t _MpegSeekbuffer(void *opaque, int64_t offset, int whence) mpeg->m_decodeNextPos += offset; break; case SEEK_END: - mpeg->m_decodeNextPos = mpeg->m_streamSize - (u32)offset; + mpeg->m_decodeNextPos = 0xFFFFF - (u32)offset; break; #ifdef USE_FFMPEG // Don't seek, just return the full size. // Returning this means FFmpeg won't think frames are truncated if we don't have them yet. case AVSEEK_SIZE: - return mpeg->m_streamSize; + return 0xFFFFF; #endif } return mpeg->m_decodeNextPos; @@ -194,13 +181,13 @@ bool MediaEngine::openContext() { av_log_set_level(AV_LOG_VERBOSE); av_log_set_callback(&ffmpeg_logger); #endif - if (m_readSize <= 0x2000 || m_pFormatCtx || !m_pdata) + if (m_pFormatCtx || !m_pdata) return false; u8* tempbuf = (u8*)av_malloc(m_bufSize); m_pFormatCtx = avformat_alloc_context(); - m_pIOContext = avio_alloc_context(tempbuf, m_bufSize, 0, (void*)this, _MpegReadbuffer, NULL, _MpegSeekbuffer); + m_pIOContext = avio_alloc_context(tempbuf, m_bufSize, 0, (void*)this, _MpegReadbuffer, NULL, 0); m_pFormatCtx->pb = m_pIOContext; // Open video file @@ -236,20 +223,15 @@ bool MediaEngine::openContext() { return false; // Could not open codec setVideoDim(); - int mpegoffset = bswap32(*(int*)(m_pdata + 8)); - m_demux = new MpegDemux(m_pdata, m_streamSize, mpegoffset); - m_demux->setReadSize(m_readSize); - m_demux->demux(m_audioStream); m_audioPos = 0; m_audioContext = Atrac3plus_Decoder::OpenContext(); m_isVideoEnd = false; m_isAudioEnd = false; - m_decodedPos = mpegoffset; #endif // USE_FFMPEG return true; } -bool MediaEngine::loadStream(u8* buffer, int readSize, int StreamSize) +bool MediaEngine::loadStream(u8* buffer, int readSize, int RingbufferSize) { closeMedia(); // force to clear the useless FBO @@ -259,51 +241,27 @@ bool MediaEngine::loadStream(u8* buffer, int readSize, int StreamSize) m_audiopts = 0; m_bufSize = 0x2000; m_decodeNextPos = 0; - m_readSize = readSize; - m_streamSize = StreamSize; - m_pdata = new u8[StreamSize]; + m_pdata = new Atrac3plus_Decoder::BufferQueue(RingbufferSize + 2048); if (!m_pdata) return false; - memcpy(m_pdata, buffer, m_readSize); - - return true; -} - -bool MediaEngine::loadFile(const char* filename) -{ - PSPFileInfo info = pspFileSystem.GetFileInfo(filename); - s64 infosize = info.size; - u8* buf = new u8[infosize]; - if (!buf) - return false; - u32 h = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); - pspFileSystem.ReadFile(h, buf, infosize); - pspFileSystem.CloseFile(h); - - closeMedia(); - // force to clear the useless FBO - gpu->Resized(); - - m_videopts = 0; - m_audiopts = 0; - m_bufSize = 0x2000; - m_decodeNextPos = 0; - m_readSize = infosize; - m_streamSize = infosize; - m_pdata = buf; - + m_pdata->push(buffer, readSize); + m_firstTimeStamp = getMpegTimeStamp(buffer + PSMF_FIRST_TIMESTAMP_OFFSET); + m_lastTimeStamp = getMpegTimeStamp(buffer + PSMF_LAST_TIMESTAMP_OFFSET); + int mpegoffset = bswap32(*(int*)(buffer + 8)); + m_demux = new MpegDemux(RingbufferSize + 2048, mpegoffset); + m_demux->addStreamData(buffer, readSize); return true; } int MediaEngine::addStreamData(u8* buffer, int addSize) { - int size = std::min(addSize, m_streamSize - m_readSize); + int size = addSize; if (size > 0 && m_pdata) { - memcpy(m_pdata + m_readSize, buffer, size); - m_readSize += size; - if (!m_pFormatCtx && (m_readSize > 0x20000 || m_readSize >= m_streamSize)) + if (!m_pdata->push(buffer, size)) + size = 0; + if (!m_pFormatCtx) openContext(); if (m_demux) { - m_demux->setReadSize(m_readSize); + m_demux->addStreamData(buffer, addSize); m_demux->demux(m_audioStream); } } @@ -389,14 +347,6 @@ bool MediaEngine::stepVideo(int videoPixelMode) { bool bGetFrame = false; while (!bGetFrame) { bool dataEnd = av_read_frame(m_pFormatCtx, &packet) < 0; - if (!dataEnd) { - if (packet.pos != -1) { - m_decodedPos = packet.pos; - } else { - // Packet doesn't know where it is in the file, let's try to approximate. - m_decodedPos += packet.size; - } - } // Even if we've read all frames, some may have been re-ordered frames at the end. // Still need to decode those, so keep calling avcodec_decode_video2(). @@ -410,16 +360,13 @@ bool MediaEngine::stepVideo(int videoPixelMode) { sws_scale(m_sws_ctx, m_pFrame->data, m_pFrame->linesize, 0, m_pCodecCtx->height, m_pFrameRGB->data, m_pFrameRGB->linesize); - s64 firstTimeStamp = getMpegTimeStamp(m_pdata + PSMF_FIRST_TIMESTAMP_OFFSET); - m_videopts = m_pFrame->pkt_dts + av_frame_get_pkt_duration(m_pFrame) - firstTimeStamp; + m_videopts = m_pFrame->pkt_dts + av_frame_get_pkt_duration(m_pFrame) - m_firstTimeStamp; bGetFrame = true; } if (result <= 0 && dataEnd) { // 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; + m_isVideoEnd = !bGetFrame && (m_pdata->getRemainSize() == 0); break; } } @@ -593,54 +540,23 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP return 0; } -static bool isHeader(u8* audioStream, int offset) -{ - const u8 header1 = (u8)0x0F; - const u8 header2 = (u8)0xD0; - return (audioStream[offset] == header1) && (audioStream[offset+1] == header2); -} - -static int getNextHeaderPosition(u8* audioStream, int curpos, int limit, int frameSize) -{ - int endScan = limit - 1; - - // Most common case: the header can be found at each frameSize - int offset = curpos + frameSize - 8; - if (offset < endScan && isHeader(audioStream, offset)) - return offset; - for (int scan = curpos; scan < endScan; scan++) { - if (isHeader(audioStream, scan)) - return scan; - } - - return -1; -} - -int MediaEngine::getBufferedSize() { - return std::max(0, m_readSize - (int)m_decodedPos); +int MediaEngine::getRemainSize() { + if (!m_pdata) + return 0; + return std::max(m_pdata->getRemainSize() - 2048, 0); } int MediaEngine::getAudioSamples(u8* buffer) { if (!m_demux) { return 0; } - u8* audioStream = 0; - int audioSize = m_demux->getaudioStream(&audioStream); - if (m_audioPos >= audioSize || !isHeader(audioStream, m_audioPos)) - { - m_isAudioEnd = m_demux->getFilePosition() >= m_streamSize; + u8 *audioFrame = 0; + int headerCode1, headerCode2; + int frameSize = m_demux->getNextaudioFrame(&audioFrame, &headerCode1, &headerCode2); + if (frameSize == 0) return 0; - } - u8 headerCode1 = audioStream[2]; - u8 headerCode2 = audioStream[3]; - int frameSize = ((headerCode1 & 0x03) << 8) | (headerCode2 & 0xFF) * 8 + 0x10; - if (m_audioPos + frameSize > audioSize) - return 0; - m_audioPos += 8; - int nextHeader = getNextHeaderPosition(audioStream, m_audioPos, audioSize, frameSize); - u8* frame = audioStream + m_audioPos; int outbytes = 0; - Atrac3plus_Decoder::Decode(m_audioContext, frame, frameSize - 8, &outbytes, buffer); + Atrac3plus_Decoder::Decode(m_audioContext, audioFrame, frameSize, &outbytes, buffer); if (headerCode1 == 0x24) { // it a mono atrac3plus, convert it to stereo s16 *outbuf = (s16*)buffer; @@ -651,13 +567,8 @@ int MediaEngine::getAudioSamples(u8* buffer) { outbuf[i * 2 + 1] = sample; } } - if (nextHeader >= 0) { - m_audioPos = nextHeader; - } else - m_audioPos = audioSize; m_audiopts += 4180; - m_decodedPos += frameSize; - return outbytes; + return 0x2000; } s64 MediaEngine::getVideoTimeStamp() { @@ -673,7 +584,5 @@ s64 MediaEngine::getAudioTimeStamp() { s64 MediaEngine::getLastTimeStamp() { if (!m_pdata) return 0; - s64 firstTimeStamp = getMpegTimeStamp(m_pdata + PSMF_FIRST_TIMESTAMP_OFFSET); - s64 lastTimeStamp = getMpegTimeStamp(m_pdata + PSMF_LAST_TIMESTAMP_OFFSET); - return lastTimeStamp - firstTimeStamp; + return m_lastTimeStamp - m_firstTimeStamp; } diff --git a/Core/HW/MediaEngine.h b/Core/HW/MediaEngine.h index 46bacf9d6a..a1ae3090d2 100644 --- a/Core/HW/MediaEngine.h +++ b/Core/HW/MediaEngine.h @@ -48,8 +48,7 @@ public: ~MediaEngine(); void closeMedia(); - bool loadStream(u8* buffer, int readSize, int StreamSize); - bool loadFile(const char* filename); + bool loadStream(u8* buffer, int readSize, int RingbufferSize); // open the mpeg context bool openContext(); // Returns number of packets actually added. @@ -58,8 +57,7 @@ public: void setVideoStream(int streamNum) { m_videoStream = streamNum; } void setAudioStream(int streamNum) { m_audioStream = streamNum; } - int getRemainSize() { return m_streamSize - m_readSize;} - int getBufferedSize(); + int getRemainSize(); bool stepVideo(int videoPixelMode); int writeVideoImage(u8* buffer, int frameWidth = 512, int videoPixelMode = 3); @@ -76,8 +74,6 @@ public: bool IsAudioEnd() { return m_isAudioEnd; } void DoState(PointerWrap &p) { - p.Do(m_streamSize); - p.Do(m_readSize); p.DoMarker("MediaEngine"); } @@ -99,19 +95,19 @@ public: int m_desWidth; int m_desHeight; - int m_streamSize; - int m_readSize; int m_decodeNextPos; - s64 m_decodedPos; int m_bufSize; s64 m_videopts; - u8* m_pdata; + Atrac3plus_Decoder::BufferQueue *m_pdata; MpegDemux *m_demux; int m_audioPos; void* m_audioContext; s64 m_audiopts; + s64 m_firstTimeStamp; + s64 m_lastTimeStamp; + bool m_isVideoEnd; bool m_isAudioEnd; }; diff --git a/Core/HW/MpegDemux.cpp b/Core/HW/MpegDemux.cpp index 65fab4fb12..634f21f71e 100644 --- a/Core/HW/MpegDemux.cpp +++ b/Core/HW/MpegDemux.cpp @@ -18,13 +18,12 @@ const int PRIVATE_STREAM_1 = 0x000001bd; const int PADDING_STREAM = 0x000001be; const int PRIVATE_STREAM_2 = 0x000001bf; -MpegDemux::MpegDemux(u8* buffer, int size, int offset) +MpegDemux::MpegDemux(int size, int offset) : m_audioStream(size) { - m_buf = buffer; + m_buf = new u8[size]; + m_len = size; m_index = offset; - m_audioStream = 0; - m_audiopos = 0; m_audioChannel = -1; m_readSize = 0; } @@ -32,13 +31,14 @@ MpegDemux::MpegDemux(u8* buffer, int size, int offset) MpegDemux::~MpegDemux(void) { - if (m_audioStream) - delete [] m_audioStream; } -void MpegDemux::setReadSize(int readSize) -{ - m_readSize = readSize; +bool MpegDemux::addStreamData(u8* buf, int addSize) { + if (m_readSize + addSize > m_len) + return false; + memcpy(m_buf + m_readSize, buf, addSize); + m_readSize += addSize; + return true; } int MpegDemux::readPesHeader(PesHeader &pesHeader, int length, int startCode) { @@ -133,8 +133,7 @@ int MpegDemux::demuxStream(bool bdemux, int startCode, int channel) length = readPesHeader(pesHeader, length, startCode); if (pesHeader.channel == channel || channel < 0) { channel = pesHeader.channel; - memcpy(m_audioStream + m_audiopos, m_buf + m_index, length); - m_audiopos += length; + m_audioStream.push(m_buf + m_index, length); } skip(length); } else { @@ -145,14 +144,12 @@ int MpegDemux::demuxStream(bool bdemux, int startCode, int channel) void MpegDemux::demux(int audioChannel) { - if (!m_audioStream) - m_audioStream = new u8[m_len - m_index]; if (audioChannel >= 0) m_audioChannel = audioChannel; while (m_index < m_len) { - if (m_readSize != m_len && m_index + 2048 > m_readSize) - return; + if (m_index + 2048 > m_readSize) + break; // Search for start code int startCode = 0xFF; while ((startCode & PACKET_START_CODE_MASK) != PACKET_START_CODE_PREFIX && !isEOF()) { @@ -191,10 +188,59 @@ void MpegDemux::demux(int audioChannel) break; } } + if (m_index < m_readSize) { + int size = m_readSize - m_index; + memcpy(m_buf, m_buf + m_index, size); + m_index = 0; + m_readSize = size; + } else { + m_index = 0; + m_readSize = 0; + } } -int MpegDemux::getaudioStream(u8** audioStream) +static bool isHeader(u8* audioStream, int offset) { - *audioStream = m_audioStream; - return m_audiopos; + const u8 header1 = (u8)0x0F; + const u8 header2 = (u8)0xD0; + return (audioStream[offset] == header1) && (audioStream[offset+1] == header2); +} + +static int getNextHeaderPosition(u8* audioStream, int curpos, int limit, int frameSize) +{ + int endScan = limit - 1; + + // Most common case: the header can be found at each frameSize + int offset = curpos + frameSize - 8; + if (offset < endScan && isHeader(audioStream, offset)) + return offset; + for (int scan = curpos; scan < endScan; scan++) { + if (isHeader(audioStream, scan)) + return scan; + } + + return -1; +} + +int MpegDemux::getNextaudioFrame(u8** buf, int *headerCode1, int *headerCode2) +{ + int gotsize = m_audioStream.get_front(m_audioFrame, 0x2000); + if (gotsize == 0 || !isHeader(m_audioFrame, 0)) + return 0; + u8 Code1 = m_audioFrame[2]; + u8 Code2 = m_audioFrame[3]; + int frameSize = ((Code1 & 0x03) << 8) | (Code2 & 0xFF) * 8 + 0x10; + if (frameSize > gotsize) + return 0; + int audioPos = 8; + int nextHeader = getNextHeaderPosition(m_audioFrame, audioPos, gotsize, frameSize); + if (nextHeader >= 0) { + audioPos = nextHeader; + } else + audioPos = gotsize; + m_audioStream.pop_front(m_audioFrame, audioPos); + *buf = m_audioFrame + 8; + if (headerCode1) *headerCode1 = Code1; + if (headerCode2) *headerCode2 = Code2; + return frameSize - 8; } diff --git a/Core/HW/MpegDemux.h b/Core/HW/MpegDemux.h index 4e529a0b66..44718ef86d 100644 --- a/Core/HW/MpegDemux.h +++ b/Core/HW/MpegDemux.h @@ -4,19 +4,20 @@ #pragma once #include "../../Globals.h" +#include "Core/HW/atrac3plus.h" +#include "Common/ChunkFile.h" class MpegDemux { public: - MpegDemux(u8* buffer, int size, int offset); + MpegDemux(int size, int offset); ~MpegDemux(void); - void setReadSize(int readSize); - + bool addStreamData(u8* buf, int addSize); void demux(int audioChannel); - // return its size - int getaudioStream(u8 **audioStream); + // return its framesize + int getNextaudioFrame(u8** buf, int *headerCode1, int *headerCode2); int getFilePosition() { return m_index; } private: struct PesHeader { @@ -52,12 +53,22 @@ private: } int readPesHeader(PesHeader &pesHeader, int length, int startCode); int demuxStream(bool bdemux, int startCode, int channel); + + void DoState(PointerWrap &p) { + p.Do(m_index); + p.Do(m_len); + p.Do(m_audioChannel); + p.Do(m_readSize); + if (m_buf) + p.DoArray(m_buf, m_len); + p.DoClass(m_audioStream); + } private: int m_index; int m_len; u8* m_buf; - u8* m_audioStream; - int m_audiopos; + Atrac3plus_Decoder::BufferQueue m_audioStream; + u8 m_audioFrame[0x2000]; int m_audioChannel; int m_readSize; }; diff --git a/Core/HW/atrac3plus.h b/Core/HW/atrac3plus.h index 480733b4c4..ba67b043b6 100644 --- a/Core/HW/atrac3plus.h +++ b/Core/HW/atrac3plus.h @@ -1,6 +1,8 @@ #ifndef _ATRAC3PLUS_DECODER_ #define _ATRAC3PLUS_DECODER_ +#include "Common/ChunkFile.h" + namespace Atrac3plus_Decoder { bool IsSupported(); bool IsInstalled(); @@ -49,6 +51,10 @@ namespace Atrac3plus_Decoder { return (end + bufQueueSize - start) % bufQueueSize; } + inline int getRemainSize() { + return bufQueueSize - getQueueSize(); + } + bool push(unsigned char *buf, int addsize) { int queuesz = getQueueSize(); int space = bufQueueSize - queuesz; @@ -82,6 +88,30 @@ namespace Atrac3plus_Decoder { return bytesgot; } + int get_front(unsigned char *buf, int wantedsize) { + if (wantedsize <= 0) + return 0; + int bytesgot = getQueueSize(); + if (wantedsize < bytesgot) + bytesgot = wantedsize; + if (start + bytesgot <= bufQueueSize) { + memcpy(buf, bufQueue + start, bytesgot); + } else { + int size = bufQueueSize - start; + memcpy(buf, bufQueue + start, size); + memcpy(buf + size, bufQueue, bytesgot - size); + } + return bytesgot; + } + + void DoState(PointerWrap &p) { + p.Do(bufQueueSize); + p.Do(start); + p.Do(end); + if (bufQueue) + p.DoArray(bufQueue, bufQueueSize); + } + unsigned char* bufQueue; int start, end; int bufQueueSize; From 7bde93d5347c5e1e6ff4e06486f5d7d9053033c8 Mon Sep 17 00:00:00 2001 From: oioitff Date: Tue, 18 Jun 2013 04:08:48 +0800 Subject: [PATCH 2/7] Fix corrupted frames and implement savestate for mpeg. --- Core/HLE/scePsmf.cpp | 15 ++++++++--- Core/HW/MediaEngine.cpp | 57 ++++++++++++++++++++++++++++++++++++----- Core/HW/MediaEngine.h | 9 ++++--- 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index d57d1488db..97f972e092 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -332,6 +332,9 @@ void PsmfPlayer::DoState(PointerWrap &p) { p.Do(tempbuf); p.Do(tempbufSize); + p.Do(status); + p.Do(psmfPlayerAvcAu); + p.DoMarker("PsmfPlayer"); } @@ -777,8 +780,10 @@ int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) if (psmfplayer->filehandle && psmfplayer->tempbuf) { u8* buf = Memory::GetPointer(psmfplayer->tempbuf); int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, psmfplayer->tempbufSize); - if (size) - psmfplayer->mediaengine->loadStream(buf, size, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); + if (size) { + psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); + psmfplayer->mediaengine->addStreamData(buf + 2048, size - 2048); + } psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); } } @@ -802,8 +807,10 @@ int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) if (psmfplayer->filehandle && psmfplayer->tempbuf) { u8* buf = Memory::GetPointer(psmfplayer->tempbuf); int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, psmfplayer->tempbufSize); - if (size) - psmfplayer->mediaengine->loadStream(buf, size, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); + if (size) { + psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); + psmfplayer->mediaengine->addStreamData(buf + 2048, size - 2048); + } psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); } } diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 625921e111..7915e2330c 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -93,6 +93,8 @@ MediaEngine::MediaEngine(): m_pdata(0) { m_audioContext = 0; m_isVideoEnd = false; m_isAudioEnd = false; + m_bufSize = 0x2000; + m_mpegheaderReadPos = 0; } MediaEngine::~MediaEngine() { @@ -133,11 +135,49 @@ void MediaEngine::closeMedia() { m_isAudioEnd = false; } +void MediaEngine::DoState(PointerWrap &p){ + p.Do(m_videoStream); + p.Do(m_audioStream); + + p.DoArray(m_mpegheader, sizeof(m_mpegheader)); + + p.Do(m_ringbuffersize); + + u32 hasloadStream = m_pdata != NULL; + p.Do(hasloadStream); + if (hasloadStream && p.mode == p.MODE_READ) + loadStream(m_mpegheader, 2048, m_ringbuffersize); + u32 hasopencontext = m_pFormatCtx != NULL; + p.Do(hasopencontext); + if (hasopencontext && p.mode == p.MODE_READ) + openContext(); + if (m_pdata) + m_pdata->DoState(p); + if (m_demux) + m_demux->DoState(p); + + p.Do(m_videopts); + p.Do(m_audiopts); + + p.Do(m_isVideoEnd); + p.Do(m_isAudioEnd); + p.DoMarker("MediaEngine"); +} + int _MpegReadbuffer(void *opaque, uint8_t *buf, int buf_size) { MediaEngine *mpeg = (MediaEngine *)opaque; - int size = mpeg->m_pdata->pop_front(buf, buf_size); + int size = buf_size; + const int mpegheaderSize = sizeof(mpeg->m_mpegheader); + if (mpeg->m_mpegheaderReadPos < mpegheaderSize) { + size = std::min(buf_size, mpegheaderSize - mpeg->m_mpegheaderReadPos); + memcpy(buf, mpeg->m_mpegheader + mpeg->m_mpegheaderReadPos, size); + mpeg->m_mpegheaderReadPos += size; + } else if (mpeg->m_mpegheaderReadPos == mpegheaderSize) { + return 0; + } else + size = mpeg->m_pdata->pop_front(buf, buf_size); mpeg->m_decodeNextPos += size; return size; } @@ -183,6 +223,7 @@ bool MediaEngine::openContext() { #endif if (m_pFormatCtx || !m_pdata) return false; + m_mpegheaderReadPos = 0; u8* tempbuf = (u8*)av_malloc(m_bufSize); @@ -223,10 +264,11 @@ bool MediaEngine::openContext() { return false; // Could not open codec setVideoDim(); - m_audioPos = 0; m_audioContext = Atrac3plus_Decoder::OpenContext(); m_isVideoEnd = false; m_isAudioEnd = false; + m_mpegheaderReadPos++; + av_seek_frame(m_pFormatCtx, m_videoStream, 0, 0); #endif // USE_FFMPEG return true; } @@ -239,8 +281,8 @@ bool MediaEngine::loadStream(u8* buffer, int readSize, int RingbufferSize) m_videopts = 0; m_audiopts = 0; - m_bufSize = 0x2000; m_decodeNextPos = 0; + m_ringbuffersize = RingbufferSize; m_pdata = new Atrac3plus_Decoder::BufferQueue(RingbufferSize + 2048); if (!m_pdata) return false; @@ -258,12 +300,16 @@ int MediaEngine::addStreamData(u8* buffer, int addSize) { if (size > 0 && m_pdata) { if (!m_pdata->push(buffer, size)) size = 0; - if (!m_pFormatCtx) - openContext(); if (m_demux) { m_demux->addStreamData(buffer, addSize); m_demux->demux(m_audioStream); } +#ifdef USE_FFMPEG + if (!m_pFormatCtx) { + m_pdata->get_front(m_mpegheader, sizeof(m_mpegheader)); + openContext(); + } +#endif // USE_FFMPEG } return size; } @@ -347,7 +393,6 @@ bool MediaEngine::stepVideo(int videoPixelMode) { bool bGetFrame = false; while (!bGetFrame) { bool dataEnd = av_read_frame(m_pFormatCtx, &packet) < 0; - // Even if we've read all frames, some may have been re-ordered frames at the end. // Still need to decode those, so keep calling avcodec_decode_video2(). if (dataEnd || packet.stream_index == m_videoStream) { diff --git a/Core/HW/MediaEngine.h b/Core/HW/MediaEngine.h index a1ae3090d2..ecf04bf8ab 100644 --- a/Core/HW/MediaEngine.h +++ b/Core/HW/MediaEngine.h @@ -73,9 +73,7 @@ public: bool IsVideoEnd() { return m_isVideoEnd; } bool IsAudioEnd() { return m_isAudioEnd; } - void DoState(PointerWrap &p) { - p.DoMarker("MediaEngine"); - } + void DoState(PointerWrap &p); private: void updateSwsFormat(int videoPixelMode); @@ -101,7 +99,6 @@ public: Atrac3plus_Decoder::BufferQueue *m_pdata; MpegDemux *m_demux; - int m_audioPos; void* m_audioContext; s64 m_audiopts; @@ -110,4 +107,8 @@ public: bool m_isVideoEnd; bool m_isAudioEnd; + + int m_ringbuffersize; + u8 m_mpegheader[0x10000]; + int m_mpegheaderReadPos; }; From b1cc94b9bf340f080b0546d7806bfd962b3b545c Mon Sep 17 00:00:00 2001 From: oioitff Date: Tue, 18 Jun 2013 13:10:24 +0800 Subject: [PATCH 3/7] Bug fix for mpeg. --- Core/HW/MediaEngine.cpp | 2 ++ Core/HW/MpegDemux.cpp | 2 +- Core/HW/MpegDemux.h | 3 +-- Core/HW/atrac3plus.h | 14 ++++++++------ 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 7915e2330c..68855927d5 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -307,6 +307,8 @@ int MediaEngine::addStreamData(u8* buffer, int addSize) { #ifdef USE_FFMPEG if (!m_pFormatCtx) { m_pdata->get_front(m_mpegheader, sizeof(m_mpegheader)); + int mpegoffset = bswap32(*(int*)(m_mpegheader + 8)); + m_pdata->pop_front(0, mpegoffset); openContext(); } #endif // USE_FFMPEG diff --git a/Core/HW/MpegDemux.cpp b/Core/HW/MpegDemux.cpp index 634f21f71e..328d4f0a72 100644 --- a/Core/HW/MpegDemux.cpp +++ b/Core/HW/MpegDemux.cpp @@ -238,7 +238,7 @@ int MpegDemux::getNextaudioFrame(u8** buf, int *headerCode1, int *headerCode2) audioPos = nextHeader; } else audioPos = gotsize; - m_audioStream.pop_front(m_audioFrame, audioPos); + m_audioStream.pop_front(0, audioPos); *buf = m_audioFrame + 8; if (headerCode1) *headerCode1 = Code1; if (headerCode2) *headerCode2 = Code2; diff --git a/Core/HW/MpegDemux.h b/Core/HW/MpegDemux.h index 44718ef86d..5e068ee7e3 100644 --- a/Core/HW/MpegDemux.h +++ b/Core/HW/MpegDemux.h @@ -18,7 +18,6 @@ public: // return its framesize int getNextaudioFrame(u8** buf, int *headerCode1, int *headerCode2); - int getFilePosition() { return m_index; } private: struct PesHeader { long pts; @@ -53,7 +52,7 @@ private: } int readPesHeader(PesHeader &pesHeader, int length, int startCode); int demuxStream(bool bdemux, int startCode, int channel); - +public: void DoState(PointerWrap &p) { p.Do(m_index); p.Do(m_len); diff --git a/Core/HW/atrac3plus.h b/Core/HW/atrac3plus.h index ba67b043b6..f0e93b9999 100644 --- a/Core/HW/atrac3plus.h +++ b/Core/HW/atrac3plus.h @@ -77,12 +77,14 @@ namespace Atrac3plus_Decoder { int bytesgot = getQueueSize(); if (wantedsize < bytesgot) bytesgot = wantedsize; - if (start + bytesgot <= bufQueueSize) { - memcpy(buf, bufQueue + start, bytesgot); - } else { - int size = bufQueueSize - start; - memcpy(buf, bufQueue + start, size); - memcpy(buf + size, bufQueue, bytesgot - size); + if (buf) { + if (start + bytesgot <= bufQueueSize) { + memcpy(buf, bufQueue + start, bytesgot); + } else { + int size = bufQueueSize - start; + memcpy(buf, bufQueue + start, size); + memcpy(buf + size, bufQueue, bytesgot - size); + } } start = (start + bytesgot) % bufQueueSize; return bytesgot; From 1e4d896980bcbaeb1f4cd48c90a8c85e876d7538 Mon Sep 17 00:00:00 2001 From: oioitff Date: Tue, 18 Jun 2013 16:05:15 +0800 Subject: [PATCH 4/7] Implement scePsmfPlayerSetPsmfOffset and scePsmfPlayerSetPsmfOffsetCB. And use memory buffer for PsmfPlayer directly instead. --- Core/HLE/FunctionWrappers.h | 5 ++ Core/HLE/scePsmf.cpp | 101 ++++++++++++++++++++++++------------ 2 files changed, 74 insertions(+), 32 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 5952f68d55..1bf3870581 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -221,6 +221,11 @@ template void WrapI_UC() { RETURN(retval); } +template void WrapI_UCI() { + int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2)); + RETURN(retval); +} + template void WrapU_UIIIII() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5)); RETURN(retval); diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 97f972e092..b0c9c20d37 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -162,8 +162,9 @@ public: void DoState(PointerWrap &p); u32 filehandle; - u32 tempbuf; - u32 tempbufSize; + u32 fileoffset; + u32 filesize; + u8 tempbuf[0x10000]; int videoCodec; int videoStreamNum; @@ -281,8 +282,8 @@ PsmfPlayer::PsmfPlayer(u32 data) { status = PSMF_PLAYER_STATUS_INIT; mediaengine = new MediaEngine; filehandle = 0; - tempbuf = 0; - tempbufSize = 0; + fileoffset = 0; + filesize = 0; } void Psmf::DoState(PointerWrap &p) { @@ -329,8 +330,8 @@ void PsmfPlayer::DoState(PointerWrap &p) { p.Do(psmfPlayerLastTimestamp); p.DoClass(mediaengine); p.Do(filehandle); - p.Do(tempbuf); - p.Do(tempbufSize); + p.Do(fileoffset); + p.Do(filesize); p.Do(status); p.Do(psmfPlayerAvcAu); @@ -769,6 +770,23 @@ int scePsmfPlayerBreak(u32 psmfPlayer) return 0; } +int _PsmfPlayerSetPsmfOffset(PsmfPlayer *psmfplayer, const char * filename, int offset, bool docallback) { + psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); + psmfplayer->fileoffset = offset; + if (psmfplayer->filehandle && psmfplayer->tempbuf) { + pspFileSystem.SeekFile(psmfplayer->filehandle, offset, FILEMOVE_BEGIN); + u8* buf = psmfplayer->tempbuf; + u32 tempbufSize = sizeof(psmfplayer->tempbuf); + int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, tempbufSize); + if (size) { + psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, (int)tempbufSize)); + psmfplayer->mediaengine->addStreamData(buf + 2048, size - 2048); + } + psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); + } + return 0; +} + int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) { PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); @@ -776,16 +794,7 @@ int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) { INFO_LOG(HLE, "scePsmfPlayerSetPsmf(%08x, %s)", psmfPlayer, filename); psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; - psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); - if (psmfplayer->filehandle && psmfplayer->tempbuf) { - u8* buf = Memory::GetPointer(psmfplayer->tempbuf); - int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, psmfplayer->tempbufSize); - if (size) { - psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); - psmfplayer->mediaengine->addStreamData(buf + 2048, size - 2048); - } - psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); - } + _PsmfPlayerSetPsmfOffset(psmfplayer, filename, 0, false); } else { @@ -803,16 +812,7 @@ int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) { INFO_LOG(HLE, "scePsmfPlayerSetPsmfCB(%08x, %s)", psmfPlayer, filename); psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; - psmfplayer->filehandle = pspFileSystem.OpenFile(filename, (FileAccess) FILEACCESS_READ); - if (psmfplayer->filehandle && psmfplayer->tempbuf) { - u8* buf = Memory::GetPointer(psmfplayer->tempbuf); - int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, psmfplayer->tempbufSize); - if (size) { - psmfplayer->mediaengine->loadStream(buf, 2048, std::max(2048 * 500, (int)psmfplayer->tempbufSize)); - psmfplayer->mediaengine->addStreamData(buf + 2048, size - 2048); - } - psmfplayer->psmfPlayerLastTimestamp = psmfplayer->mediaengine->getLastTimeStamp(); - } + _PsmfPlayerSetPsmfOffset(psmfplayer, filename, 0, true); } else { @@ -822,6 +822,41 @@ int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) return 0; } +int scePsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset) +{ + PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); + if (psmfplayer) + { + INFO_LOG(HLE, "scePsmfPlayerSetPsmfOffset(%08x, %s, %i)", psmfPlayer, filename, offset); + psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; + _PsmfPlayerSetPsmfOffset(psmfplayer, filename, offset, false); + } + else + { + INFO_LOG(HLE, "scePsmfPlayerSetPsmfOffset(%08x, %s, %i): invalid psmf player", psmfPlayer, filename, offset); + } + + return 0; +} + +int scePsmfPlayerSetPsmfOffsetCB(u32 psmfPlayer, const char *filename, int offset) +{ + // TODO: hleCheckCurrentCallbacks? + PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); + if (psmfplayer) + { + INFO_LOG(HLE, "scePsmfPlayerSetPsmfOffsetCB(%08x, %s, %i)", psmfPlayer, filename, offset); + psmfplayer->status = PSMF_PLAYER_STATUS_STANDBY; + _PsmfPlayerSetPsmfOffset(psmfplayer, filename, offset, true); + } + else + { + INFO_LOG(HLE, "scePsmfPlayerSetPsmfOffsetCB(%08x, %s, %i): invalid psmf player", psmfPlayer, filename, offset); + } + + return 0; +} + int scePsmfPlayerGetAudioOutSize(u32 psmfPlayer) { WARN_LOG(HLE, "scePsmfPlayerGetAudioOutSize(%08x)", psmfPlayer); @@ -929,9 +964,10 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr) Memory::Write_U32(psmfplayer->psmfPlayerAvcAu.pts, videoDataAddr + 8); } - int addSize = std::min(psmfplayer->mediaengine->getRemainSize(), (int)psmfplayer->tempbufSize); + u32 tempbufSize = sizeof(psmfplayer->tempbuf); + int addSize = std::min(psmfplayer->mediaengine->getRemainSize(), (int)tempbufSize); if (psmfplayer->filehandle && psmfplayer->tempbuf && addSize > 0) { - u8* buf = Memory::GetPointer(psmfplayer->tempbuf); + u8* buf = psmfplayer->tempbuf; int size = pspFileSystem.ReadFile(psmfplayer->filehandle, buf, addSize); if (size) psmfplayer->mediaengine->addStreamData(buf, size); @@ -1076,8 +1112,9 @@ int scePsmfPlayerSetTempBuf(u32 psmfPlayer, u32 tempBufAddr, u32 tempBufSize) PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (psmfplayer) { psmfplayer->status = PSMF_PLAYER_STATUS_INIT; - psmfplayer->tempbuf = tempBufAddr; - psmfplayer->tempbufSize = tempBufSize; + // fake it right now, use tempbuf from memory directly + //psmfplayer->tempbuf = tempBufAddr; + //psmfplayer->tempbufSize = tempBufSize; } return 0; } @@ -1226,8 +1263,8 @@ const HLEFunction scePsmfPlayer[] = {0xf3efaa91, WrapU_UUU, "scePsmfPlayerGetCurrentPlayMode"}, {0xf8ef08a6, WrapI_U, "scePsmfPlayerGetCurrentStatus"}, {0x2D0E4E0A, WrapI_UUU, "scePsmfPlayerSetTempBuf"}, - {0x76C0F4AE, 0, "scePsmfPlayerSetPsmfOffset"}, - {0xA72DB4F9, 0, "scePsmfPlayerSetPsmfOffsetCB"}, + {0x76C0F4AE, WrapI_UCI, "scePsmfPlayerSetPsmfOffset"}, + {0xA72DB4F9, WrapI_UCI, "scePsmfPlayerSetPsmfOffsetCB"}, }; void Register_scePsmf() { From fa4ad234a132f2f2dad9fdda9ee570021fb118d6 Mon Sep 17 00:00:00 2001 From: oioitff Date: Sun, 23 Jun 2013 15:25:39 +0800 Subject: [PATCH 5/7] Use ERROR_LOG for error messages instead. --- Core/HLE/scePsmf.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index b0c9c20d37..5dd7ac9588 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -798,7 +798,7 @@ int scePsmfPlayerSetPsmf(u32 psmfPlayer, const char *filename) } else { - INFO_LOG(HLE, "scePsmfPlayerSetPsmf(%08x, %s): invalid psmf player", psmfPlayer, filename); + ERROR_LOG(HLE, "scePsmfPlayerSetPsmf(%08x, %s): invalid psmf player", psmfPlayer, filename); } return 0; @@ -816,7 +816,7 @@ int scePsmfPlayerSetPsmfCB(u32 psmfPlayer, const char *filename) } else { - INFO_LOG(HLE, "scePsmfPlayerSetPsmfCB(%08x, %s): invalid psmf player", psmfPlayer, filename); + ERROR_LOG(HLE, "scePsmfPlayerSetPsmfCB(%08x, %s): invalid psmf player", psmfPlayer, filename); } return 0; @@ -833,7 +833,7 @@ int scePsmfPlayerSetPsmfOffset(u32 psmfPlayer, const char *filename, int offset) } else { - INFO_LOG(HLE, "scePsmfPlayerSetPsmfOffset(%08x, %s, %i): invalid psmf player", psmfPlayer, filename, offset); + ERROR_LOG(HLE, "scePsmfPlayerSetPsmfOffset(%08x, %s, %i): invalid psmf player", psmfPlayer, filename, offset); } return 0; @@ -851,7 +851,7 @@ int scePsmfPlayerSetPsmfOffsetCB(u32 psmfPlayer, const char *filename, int offse } else { - INFO_LOG(HLE, "scePsmfPlayerSetPsmfOffsetCB(%08x, %s, %i): invalid psmf player", psmfPlayer, filename, offset); + ERROR_LOG(HLE, "scePsmfPlayerSetPsmfOffsetCB(%08x, %s, %i): invalid psmf player", psmfPlayer, filename, offset); } return 0; From 7f7e7adfe27be815543e6b896175598723b7b72e Mon Sep 17 00:00:00 2001 From: oioitff Date: Sun, 23 Jun 2013 15:36:28 +0800 Subject: [PATCH 6/7] Free loaded data in Ringbuffer only while ffmpeg is requiring more data. Clean up some codes. --- Core/HW/MediaEngine.cpp | 34 ++++++---------------------------- Core/HW/MediaEngine.h | 2 +- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 68855927d5..0ec8c4e712 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -176,34 +176,12 @@ int _MpegReadbuffer(void *opaque, uint8_t *buf, int buf_size) mpeg->m_mpegheaderReadPos += size; } else if (mpeg->m_mpegheaderReadPos == mpegheaderSize) { return 0; - } else - size = mpeg->m_pdata->pop_front(buf, buf_size); - mpeg->m_decodeNextPos += size; - return size; -} - -int64_t _MpegSeekbuffer(void *opaque, int64_t offset, int whence) -{ - MediaEngine *mpeg = (MediaEngine*)opaque; - switch (whence) { - case SEEK_SET: - mpeg->m_decodeNextPos = offset; - break; - case SEEK_CUR: - mpeg->m_decodeNextPos += offset; - break; - case SEEK_END: - mpeg->m_decodeNextPos = 0xFFFFF - (u32)offset; - break; - -#ifdef USE_FFMPEG - // Don't seek, just return the full size. - // Returning this means FFmpeg won't think frames are truncated if we don't have them yet. - case AVSEEK_SIZE: - return 0xFFFFF; -#endif + } else { + mpeg->m_pdata->pop_front(0, mpeg->m_decodingsize); + size = mpeg->m_pdata->get_front(buf, buf_size); + mpeg->m_decodingsize = size; } - return mpeg->m_decodeNextPos; + return size; } #ifdef _DEBUG @@ -224,6 +202,7 @@ bool MediaEngine::openContext() { if (m_pFormatCtx || !m_pdata) return false; m_mpegheaderReadPos = 0; + m_decodingsize = 0; u8* tempbuf = (u8*)av_malloc(m_bufSize); @@ -281,7 +260,6 @@ bool MediaEngine::loadStream(u8* buffer, int readSize, int RingbufferSize) m_videopts = 0; m_audiopts = 0; - m_decodeNextPos = 0; m_ringbuffersize = RingbufferSize; m_pdata = new Atrac3plus_Decoder::BufferQueue(RingbufferSize + 2048); if (!m_pdata) diff --git a/Core/HW/MediaEngine.h b/Core/HW/MediaEngine.h index ecf04bf8ab..d6f9fe5b84 100644 --- a/Core/HW/MediaEngine.h +++ b/Core/HW/MediaEngine.h @@ -93,7 +93,7 @@ public: int m_desWidth; int m_desHeight; - int m_decodeNextPos; + int m_decodingsize; int m_bufSize; s64 m_videopts; Atrac3plus_Decoder::BufferQueue *m_pdata; From 2b9f9283c2a92af211651794e8ffeaf2557fa574 Mon Sep 17 00:00:00 2001 From: oioitff Date: Sun, 23 Jun 2013 20:25:11 +0900 Subject: [PATCH 7/7] Improve getRemainSize for MediaEngine. It's more accurate now. --- Core/HW/MediaEngine.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp index 0ec8c4e712..e957b2846d 100644 --- a/Core/HW/MediaEngine.cpp +++ b/Core/HW/MediaEngine.cpp @@ -177,9 +177,9 @@ int _MpegReadbuffer(void *opaque, uint8_t *buf, int buf_size) } else if (mpeg->m_mpegheaderReadPos == mpegheaderSize) { return 0; } else { - mpeg->m_pdata->pop_front(0, mpeg->m_decodingsize); - size = mpeg->m_pdata->get_front(buf, buf_size); - mpeg->m_decodingsize = size; + size = mpeg->m_pdata->pop_front(buf, buf_size); + if (size > 0) + mpeg->m_decodingsize = size; } return size; } @@ -391,7 +391,9 @@ bool MediaEngine::stepVideo(int videoPixelMode) { if (result <= 0 && dataEnd) { // 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_pdata->getRemainSize() == 0); + m_isVideoEnd = !bGetFrame && (m_pdata->getQueueSize() == 0); + if (m_isVideoEnd) + m_decodingsize = 0; break; } } @@ -568,7 +570,7 @@ int MediaEngine::writeVideoImageWithRange(u8* buffer, int frameWidth, int videoP int MediaEngine::getRemainSize() { if (!m_pdata) return 0; - return std::max(m_pdata->getRemainSize() - 2048, 0); + return std::max(m_pdata->getRemainSize() - m_decodingsize - 2048, 0); } int MediaEngine::getAudioSamples(u8* buffer) {