diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index b9d6b25a88..3c32a0fe31 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -93,7 +93,7 @@ static const s64 UNKNOWN_TIMESTAMP = -1; static const int MPEG_HEADER_BUFFER_MINIMUM_SIZE = 2048; // For PMP media -static u32 pmp_videoSource = 0; //pointer to the video source (SceMpegLLi structure) +static u32 pmp_videoSource = 0; //pointer to the video source (SceMpegLLi structure) static int pmp_nBlocks = 0; //number of blocks received in the last sceMpegBasePESpacketCopy call #ifdef USE_FFMPEG static std::list pmp_queue; //list of pmp video frames have been decoded and will be played @@ -105,7 +105,7 @@ static bool pmp_oldStateLoaded = false; // for dostate static int ringbufferPutPacketsAdded = 0; static bool useRingbufferPutCallbackMulti = true; -#ifdef USE_FFMPEG +#ifdef USE_FFMPEG extern "C" { #include "libavformat/avformat.h" @@ -164,7 +164,7 @@ struct AvcContext { int avcFrameStatus; }; -struct StreamInfo { +struct StreamInfo { int type; int num; int sid; @@ -269,7 +269,7 @@ static std::map mpegMap; static MpegContext *getMpegCtx(u32 mpegAddr) { if (!Memory::IsValidAddress(mpegAddr)) return nullptr; - + u32 mpeg = Memory::Read_U32(mpegAddr); auto found = mpegMap.find(mpeg); if (found == mpegMap.end()) @@ -407,7 +407,7 @@ void __MpegDoState(PointerWrap &p) { ringbufferPutPacketsAdded = 0; } else { Do(p, ringbufferPutPacketsAdded); - } + } if (s < 4) { mpegLibCrc = 0; } @@ -690,7 +690,7 @@ static int sceMpegRegistStream(u32 mpeg, u32 streamType, u32 streamNum) case MPEG_DATA_STREAM: ctx->dataRegistered = true; break; - default : + default : DEBUG_LOG(Log::ME, "sceMpegRegistStream(%i) : unknown stream type", streamType); break; } @@ -741,7 +741,7 @@ static int sceMpegFreeAvcEsBuf(u32 mpeg, int esBuf) return hleLogDebug(Log::ME, 0); } -// check the existence of pmp media context +// check the existence of pmp media context static bool isContextExist(u32 ctxAddr){ for (auto it = pmp_ContextList.begin(); it != pmp_ContextList.end(); ++it){ if (*it == ctxAddr){ @@ -764,7 +764,7 @@ static bool InitPmp(MpegContext * ctx){ // wanted output pixel format // reference values for pix_fmt: - // GE_CMODE_16BIT_BGR5650 <--> AV_PIX_FMT_BGR565LE + // GE_CMODE_16BIT_BGR5650 <--> AV_PIX_FMT_BGR565LE // GE_CMODE_16BIT_ABGR5551 <--> AV_PIX_FMT_BGR555LE; // GE_CMODE_16BIT_ABGR4444 <--> AV_PIX_FMT_BGR444LE; // GE_CMODE_32BIT_ABGR8888 <--> AV_PIX_FMT_RGBA; @@ -826,14 +826,14 @@ static bool InitPmp(MpegContext * ctx){ } // This class H264Frames is used for collecting small pieces of frames into larger frames for ffmpeg to decode -// Basically, this will avoid incomplete frame decoding issue and improve much better the video quality. +// Basically, this will avoid incomplete frame decoding issue and improve much better the video quality. class H264Frames{ public: int size; u8* stream; - + H264Frames() :size(0), stream(NULL){}; - + H264Frames(u8* str, int sz) :size(sz){ stream = new u8[size]; memcpy(stream, str, size); @@ -852,7 +852,7 @@ public: stream = NULL; } }; - + void add(const H264Frames *p) { add(p->stream, p->size); }; @@ -936,7 +936,7 @@ static bool decodePmpVideo(PSPPointer ringbuffer, u32 pmpctxA AVFrame* pFrameRGB = mediaengine->m_pFrameRGB; auto pCodecCtx = mediaengine->m_pCodecCtxs[0]; - // pmpframes could be destroied when close a video to load another one + // pmpframes could be destroied when close a video to load another one if (!pmpframes) pmpframes = new H264Frames; @@ -1016,7 +1016,7 @@ static bool decodePmpVideo(PSPPointer ringbuffer, u32 pmpctxA ERROR_LOG(Log::ME, "sws_scale: Error while converting %d", swsRet); return false; } - // free sws context + // free sws context sws_freeContext(img_convert_ctx); // update timestamp @@ -1048,7 +1048,7 @@ static bool decodePmpVideo(PSPPointer ringbuffer, u32 pmpctxA av_free_packet(&packet); #endif pmpframes->~H264Frames(); - // must reset pmp_VideoSource address to zero after decoding. + // must reset pmp_VideoSource address to zero after decoding. pmp_videoSource = 0; return true; } @@ -1111,12 +1111,12 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr SceMpegAu avcAu; avcAu.read(auAddr); - + auto ringbuffer = PSPPointer::Create(ctx->mpegRingbufferAddr); if (!ringbuffer.IsValid()) { return hleLogError(Log::ME, -1, "Bogus mpegringbufferaddr"); } - + u32 buffer = Memory::Read_U32(bufferAddr); u32 init = Memory::Read_U32(initAddr); DEBUG_LOG(Log::ME, "video: bufferAddr = %08x, *buffer = %08x, *init = %08x", bufferAddr, buffer, init); @@ -1148,7 +1148,7 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr gpu->PerformWriteFormattedFromMemory(buffer, bufferSize, frameWidth, (GEBufferFormat)ctx->videoPixelMode); ctx->avc.avcFrameStatus = 1; ctx->videoFrameCount++; - + // free front frame accumDelay += 30; pmp_queue.pop_front(); @@ -1181,7 +1181,7 @@ static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr Memory::Write_U32(1, initAddr); } else { - // Save the current frame's status to initAddr + // Save the current frame's status to initAddr Memory::Write_U32(ctx->avc.avcFrameStatus, initAddr); } ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS; @@ -1232,7 +1232,7 @@ static u32 sceMpegUnRegistStream(u32 mpeg, int streamUid) { case MPEG_DATA_STREAM: ctx->dataRegistered = false; break; - default : + default : DEBUG_LOG(Log::ME, "sceMpegUnRegistStream(%i) : unknown streamID ", streamUid); break; } @@ -1333,7 +1333,7 @@ static int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initA if (mpegLibVersion >= 0x010A) { // Sunday Vs Magazine Shuuketsu! Choujou Daikessen expect, issue #11060 Memory::Write_U32(1, initAddr); - } else { + } else { // Save the current frame's status to initAddr Memory::Write_U32(ctx->avc.avcFrameStatus, initAddr); } @@ -1568,7 +1568,7 @@ static int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) // Would have crashed before, TODO test behavior. return hleLogError(Log::ME, -1, "invalid ringbuffer address"); } - + if (PSP_CoreParameter().compat.flags().MpegAvcWarmUp) { if (ctx->mpegwarmUp == 0) { ctx->mpegwarmUp++; @@ -1624,7 +1624,7 @@ static int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) // The avcau struct may have been modified by mediaengine, write it back. avcAu.write(auAddr); - // Jeanne d'Arc return 00000000 as attrAddr here and cause WriteToHardware error + // Jeanne d'Arc return 00000000 as attrAddr here and cause WriteToHardware error if (Memory::IsValidAddress(attrAddr)) { Memory::Write_U32(1, attrAddr); } @@ -1694,7 +1694,7 @@ static int sceMpegGetAtracAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) int result = 0; atracAu.pts = ctx->mediaengine->getAudioTimeStamp() + ctx->mpegFirstTimestamp; - + if (ctx->mediaengine->IsVideoEnd()) { INFO_LOG(Log::ME, "video end reach. pts: %i dts: %i", (int)atracAu.pts, (int)ctx->mediaengine->getLastTimeStamp()); ringbuffer->packetsAvail = 0; @@ -1715,7 +1715,7 @@ static int sceMpegGetAtracAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr) atracAu.write(auAddr); - // 3rd birthday return 00000000 as attrAddr here and cause WriteToHardware error + // 3rd birthday return 00000000 as attrAddr here and cause WriteToHardware error if (Memory::IsValidAddress(attrAddr)) { Memory::Write_U32(0, attrAddr); } @@ -2056,6 +2056,7 @@ static u32 sceMpegAvcResourceInit(u32 mpeg) return 0; } +// TODO: SIMD this (or rather, the caller). static u32 convertABGRToYCbCr(u32 abgr) { //see http://en.wikipedia.org/wiki/Yuv#Y.27UV444_to_RGB888_conversion for more information. u8 r = (abgr >> 0) & 0xFF; @@ -2065,10 +2066,22 @@ static u32 convertABGRToYCbCr(u32 abgr) { int cb = -0.169f * r - 0.331f * g + 0.499f * b + 128.0f; int cr = 0.499f * r - 0.418f * g - 0.0813f * b + 128.0f; - // check yCbCr value - if ( y > 0xFF) y = 0xFF; if ( y < 0) y = 0; - if (cb > 0xFF) cb = 0xFF; if (cb < 0) cb = 0; - if (cr > 0xFF) cr = 0xFF; if (cr < 0) cr = 0; + // clamp values before packing. + if (y > 0xFF) { + y = 0xFF; + } else if ( y < 0) { + y = 0; + } + if (cb > 0xFF) { + cb = 0xFF; + } else if (cb < 0) { + cb = 0; + } + if (cr > 0xFF) { + cr = 0xFF; + } else if (cr < 0) { + cr = 0; + } return (y << 16) | (cb << 8) | cr; } @@ -2096,7 +2109,7 @@ static int __MpegAvcConvertToYuv420(const void *data, u32 bufferOutputAddr, int u32 yCbCr1 = convertABGRToYCbCr(abgr1); u32 yCbCr2 = convertABGRToYCbCr(abgr2); u32 yCbCr3 = convertABGRToYCbCr(abgr3); - + Y[width * (y + 0) + x + 0] = (yCbCr0 >> 16) & 0xFF; Y[width * (y + 0) + x + 1] = (yCbCr1 >> 16) & 0xFF; Y[width * (y + 1) + x + 0] = (yCbCr2 >> 16) & 0xFF; @@ -2337,7 +2350,7 @@ static u32 sceMpegBasePESpacketCopy(u32 p) } ++lli; } - + DEBUG_LOG(Log::ME, "sceMpegBasePESpacketCopy(%08x), received %d block(s)", pmp_videoSource, pmp_nBlocks); return 0; }