Psmf::Psmf(u32 data) { headerOffset = data; magic = Memory::Read_U32(data); version = Memory::Read_U32(data + 4); streamOffset = bswap32(Memory::Read_U32(data + 8)); streamSize = bswap32(Memory::Read_U32(data + 12)); streamDataTotalSize = bswap32(Memory::Read_U32(data + 0x50)); presentationStartTime = getMpegTimeStamp(Memory::GetPointer(data + PSMF_FIRST_TIMESTAMP_OFFSET)); presentationEndTime = getMpegTimeStamp(Memory::GetPointer(data + PSMF_LAST_TIMESTAMP_OFFSET)); streamDataNextBlockSize = bswap32(Memory::Read_U32(data + 0x6A)); streamDataNextInnerBlockSize = bswap32(Memory::Read_U32(data + 0x7C)); numStreams = bswap16(Memory::Read_U16(data + 0x80)); currentStreamNum = -1; currentAudioStreamNum = -1; currentVideoStreamNum = -1; for (int i = 0; i < numStreams; i++) { PsmfStream *stream = 0; u32 currentStreamAddr = data + 0x82 + i * 16; int streamId = Memory::Read_U8(currentStreamAddr); if ((streamId & PSMF_VIDEO_STREAM_ID) == PSMF_VIDEO_STREAM_ID) { stream = new PsmfStream(PSMF_AVC_STREAM, ++currentVideoStreamNum); stream->readMPEGVideoStreamParams(currentStreamAddr, this); } else if ((streamId & PSMF_AUDIO_STREAM_ID) == PSMF_AUDIO_STREAM_ID) { stream = new PsmfStream(PSMF_ATRAC_STREAM, ++currentAudioStreamNum); stream->readPrivateAudioStreamParams(currentStreamAddr, this); } if (stream) { currentStreamNum++; streamMap[currentStreamNum] = stream; } } }
void AnalyzeMpeg(u32 buffer_addr, MpegContext *ctx) { ctx->mpegStreamAddr = buffer_addr; ctx->mpegMagic = Memory::Read_U32(buffer_addr); ctx->mpegRawVersion = Memory::Read_U32(buffer_addr + PSMF_STREAM_VERSION_OFFSET); switch (ctx->mpegRawVersion) { case PSMF_VERSION_0012: ctx->mpegVersion = MPEG_VERSION_0012; break; case PSMF_VERSION_0013: ctx->mpegVersion = MPEG_VERSION_0013; break; case PSMF_VERSION_0014: ctx->mpegVersion = MPEG_VERSION_0014; break; case PSMF_VERSION_0015: ctx->mpegVersion = MPEG_VERSION_0015; break; default: ctx->mpegVersion = -1; break; } ctx->mpegOffset = bswap32(Memory::Read_U32(buffer_addr + PSMF_STREAM_OFFSET_OFFSET)); ctx->mpegStreamSize = bswap32(Memory::Read_U32(buffer_addr + PSMF_STREAM_SIZE_OFFSET)); ctx->mpegFirstTimestamp = getMpegTimeStamp(Memory::GetPointer(buffer_addr + PSMF_FIRST_TIMESTAMP_OFFSET)); ctx->mpegLastTimestamp = getMpegTimeStamp(Memory::GetPointer(buffer_addr + PSMF_LAST_TIMESTAMP_OFFSET)); ctx->mpegFirstDate = convertTimestampToDate(ctx->mpegFirstTimestamp); ctx->mpegLastDate = convertTimestampToDate(ctx->mpegLastTimestamp); ctx->avc.avcDetailFrameWidth = (Memory::Read_U8(buffer_addr + 142) * 0x10); ctx->avc.avcDetailFrameHeight = (Memory::Read_U8(buffer_addr + 143) * 0x10); ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS; ctx->avc.avcFrameStatus = 0; ctx->videoFrameCount = 0; ctx->audioFrameCount = 0; ctx->endOfAudioReached = false; ctx->endOfVideoReached = false; if (ctx->mpegMagic != PSMF_MAGIC || ctx->mpegVersion < 0 || (ctx->mpegOffset & 2047) != 0 || ctx->mpegOffset == 0) { // mpeg header is invalid! return; } if (ctx->mediaengine && (ctx->mpegStreamSize > 0) && !ctx->isAnalyzed) { // init mediaEngine ctx->mediaengine->loadStream(Memory::GetPointer(buffer_addr), ctx->mpegOffset, ctx->mpegOffset + ctx->mpegStreamSize); ctx->mediaengine->setVideoDim(); } // When used with scePsmf, some applications attempt to use sceMpegQueryStreamOffset // and sceMpegQueryStreamSize, which forces a packet overwrite in the Media Engine and in // the MPEG ringbuffer. // Mark the current MPEG as analyzed to filter this, and restore it at sceMpegFinish. ctx->isAnalyzed = true; INFO_LOG(ME, "Stream offset: %d, Stream size: 0x%X", ctx->mpegOffset, ctx->mpegStreamSize); INFO_LOG(ME, "First timestamp: %lld, Last timestamp: %lld", ctx->mpegFirstTimestamp, ctx->mpegLastTimestamp); }
void AnalyzeMpeg(u8 *buffer, MpegContext *ctx) { ctx->mpegMagic = *(u32_le*)buffer; ctx->mpegRawVersion = *(u32_le*)(buffer + PSMF_STREAM_VERSION_OFFSET); switch (ctx->mpegRawVersion) { case PSMF_VERSION_0012: ctx->mpegVersion = MPEG_VERSION_0012; break; case PSMF_VERSION_0013: ctx->mpegVersion = MPEG_VERSION_0013; break; case PSMF_VERSION_0014: ctx->mpegVersion = MPEG_VERSION_0014; break; case PSMF_VERSION_0015: ctx->mpegVersion = MPEG_VERSION_0015; break; default: ctx->mpegVersion = -1; break; } ctx->mpegOffset = bswap32(*(u32_le*)(buffer + PSMF_STREAM_OFFSET_OFFSET)); ctx->mpegStreamSize = bswap32(*(u32_le*)(buffer + PSMF_STREAM_SIZE_OFFSET)); ctx->mpegFirstTimestamp = getMpegTimeStamp(buffer + PSMF_FIRST_TIMESTAMP_OFFSET); ctx->mpegLastTimestamp = getMpegTimeStamp(buffer + PSMF_LAST_TIMESTAMP_OFFSET); ctx->mpegFirstDate = convertTimestampToDate(ctx->mpegFirstTimestamp); ctx->mpegLastDate = convertTimestampToDate(ctx->mpegLastTimestamp); ctx->avc.avcDetailFrameWidth = (*(u8*)(buffer + 142)) * 0x10; ctx->avc.avcDetailFrameHeight = (*(u8*)(buffer + 143)) * 0x10; ctx->avc.avcDecodeResult = 0; ctx->avc.avcFrameStatus = 0; ctx->videoFrameCount = 0; ctx->audioFrameCount = 0; ctx->endOfAudioReached = false; ctx->endOfVideoReached = false; if (ctx->mpegMagic != PSMF_MAGIC || ctx->mpegVersion < 0 || (ctx->mpegOffset & 2047) != 0 || ctx->mpegOffset == 0) { // mpeg header is invalid! return; } // When used with scePsmf, some applications attempt to use sceMpegQueryStreamOffset // and sceMpegQueryStreamSize, which forces a packet overwrite in the Media Engine and in // the MPEG ringbuffer. // Mark the current MPEG as analyzed to filter this, and restore it at sceMpegFinish. ctx->isAnalyzed = true; // copy header struct to mpeg header. memcpy(ctx->mpegheader, buffer, 2048); *(u32_le*)(ctx->mpegheader + PSMF_STREAM_OFFSET_OFFSET) = 0x80000; INFO_LOG(ME, "Stream offset: %d, Stream size: 0x%X", ctx->mpegOffset, ctx->mpegStreamSize); INFO_LOG(ME, "First timestamp: %lld, Last timestamp: %lld", ctx->mpegFirstTimestamp, ctx->mpegLastTimestamp); }
bool MediaEngine::loadStream(const u8 *buffer, int readSize, int RingbufferSize) { closeMedia(); m_videopts = 0; m_audiopts = 0; m_ringbuffersize = RingbufferSize; m_pdata = new BufferQueue(RingbufferSize + 2048); m_pdata->push(buffer, readSize); m_firstTimeStamp = getMpegTimeStamp(buffer + PSMF_FIRST_TIMESTAMP_OFFSET); m_lastTimeStamp = getMpegTimeStamp(buffer + PSMF_LAST_TIMESTAMP_OFFSET); int mpegoffset = (int)(*(s32_be*)(buffer + 8)); m_demux = new MpegDemux(RingbufferSize + 2048, mpegoffset); m_demux->addStreamData(buffer, readSize); return true; }
PsmfPlayer::PsmfPlayer(u32 data) { videoCodec = Memory::Read_U32(data); videoStreamNum = Memory::Read_U32(data + 4); audioCodec = Memory::Read_U32(data + 8); audioStreamNum = Memory::Read_U32(data + 12); playMode = Memory::Read_U32(data+ 16); playSpeed = Memory::Read_U32(data + 20); psmfPlayerLastTimestamp = getMpegTimeStamp(Memory::GetPointer(data + PSMF_LAST_TIMESTAMP_OFFSET)) ; status = PSMF_PLAYER_STATUS_INIT; mediaengine = new MediaEngine; }