int scePsmfPlayerCreate(u32 psmfPlayer, u32 psmfPlayerDataAddr) { WARN_LOG(HLE, "scePsmfPlayerCreate(%08x, %08x)", psmfPlayer, psmfPlayerDataAddr); PsmfPlayer *psmfplayer = getPsmfPlayer(psmfPlayer); if (!psmfplayer) { // TODO: This is the wrong data. PsmfPlayer needs a new interface. psmfplayer = new PsmfPlayer(psmfPlayerDataAddr); psmfPlayerMap[psmfPlayer] = psmfplayer; } if (Memory::IsValidAddress(psmfPlayerDataAddr)) { psmfplayer->displayBuffer = Memory::Read_U32(psmfPlayerDataAddr); psmfplayer->displayBufferSize = Memory::Read_U32(psmfPlayerDataAddr + 4); psmfplayer->playbackThreadPriority = Memory::Read_U32(psmfPlayerDataAddr + 8); } psmfplayer->psmfMaxAheadTimestamp = getMaxAheadTimestamp(581); psmfplayer->status = PSMF_PLAYER_STATUS_INIT; return 0; }
int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) { MpegContext *ctx = getMpegCtx(mpeg); if (!ctx) { WARN_LOG(HLE, "sceMpegGetAvcAu(%08x, %08x, %08x, %08x): bad mpeg handle", mpeg, streamId, auAddr, attrAddr); return -1; } SceMpegRingBuffer mpegRingbuffer; Memory::ReadStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer); SceMpegAu sceAu; sceAu.read(auAddr); if (mpegRingbuffer.packetsRead == 0 || mpegRingbuffer.packetsFree == mpegRingbuffer.packets) { DEBUG_LOG(HLE, "PSP_ERROR_MPEG_NO_DATA=sceMpegGetAvcAu(%08x, %08x, %08x, %08x)", mpeg, streamId, auAddr, attrAddr); // TODO: Does this really reschedule? return hleDelayResult(PSP_ERROR_MPEG_NO_DATA, "mpeg get avc", mpegDecodeErrorDelayMs); } auto streamInfo = ctx->streamMap.find(streamId); if (streamInfo == ctx->streamMap.end()) { ERROR_LOG(HLE, "sceMpegGetAvcAu - bad stream id %i", streamId); return -1; } if (streamInfo->second.needsReset) { sceAu.pts = 0; streamInfo->second.needsReset = false; } // Wait for audio if too much ahead if (ctx->atracRegistered && (sceAu.pts > sceAu.pts + getMaxAheadTimestamp(mpegRingbuffer))) { ERROR_LOG(HLE, "sceMpegGetAvcAu - video too much ahead"); // TODO: Does this really reschedule? return hleDelayResult(PSP_ERROR_MPEG_NO_DATA, "mpeg get avc", mpegDecodeErrorDelayMs); } int result = 0; // read the au struct from ram // TODO: For now, always checking, since readVideoAu() is stubbed. if (!ctx->mediaengine->readVideoAu(&sceAu) || true) { // Only return this after the video already ended. if (ctx->endOfVideoReached) { if (mpegRingbuffer.packetsFree < mpegRingbuffer.packets) { mpegRingbuffer.packetsFree = mpegRingbuffer.packets; Memory::WriteStruct(ctx->mpegRingbufferAddr, &mpegRingbuffer); } result = PSP_ERROR_MPEG_NO_DATA; } if (ctx->mpegLastTimestamp <= 0 || sceAu.pts >= ctx->mpegLastTimestamp) { NOTICE_LOG(HLE, "End of video reached"); ctx->endOfVideoReached = true; } else { ctx->endOfAudioReached = false; } } // The avcau struct may have been modified by mediaengine, write it back. sceAu.write(auAddr); if (Memory::IsValidAddress(attrAddr)) { Memory::Write_U32(1, attrAddr); } DEBUG_LOG(HLE, "%x=sceMpegGetAvcAu(%08x, %08x, %08x, %08x)", result, mpeg, streamId, auAddr, attrAddr); // TODO: sceMpegGetAvcAu seems to modify esSize, and delay when it's > 1000 or something. // There's definitely more to it, but ultimately it seems games should expect it to delay randomly. return hleDelayResult(result, "mpeg get avc", 100); }