From f70b5e0c1ccec69697adcbcb4c5bcff092dec145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20L=C3=B3pez=20Guimaraes?= Date: Wed, 14 Jan 2026 18:21:56 +0000 Subject: [PATCH] cellVdec: Add support for all MPEG4 profile levels The names are based from the maximum resolution that the PS3 supports and the levels that are listed on the MPEG-4 Part 2 Wikipedia. The PS3 uses a separate decoder for MPEG4 instead of DivX, so the handling on cellVdecGetPicItem should probably be separate too. However, research needs to be done on that side and things seem to be working with what we currently have. --- rpcs3/Emu/Cell/Modules/cellVdec.cpp | 81 +++++++++++++++++++++++++++-- rpcs3/Emu/Cell/Modules/cellVdec.h | 20 +++++-- 2 files changed, 95 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellVdec.cpp b/rpcs3/Emu/Cell/Modules/cellVdec.cpp index 49975b632c..2a8f855d6b 100644 --- a/rpcs3/Emu/Cell/Modules/cellVdec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellVdec.cpp @@ -780,6 +780,83 @@ static error_code vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0 break; } case CELL_VDEC_CODEC_TYPE_MPEG4: + { + cellVdec.warning("cellVdecQueryAttr: MPEG4 (profile=%d)", profile); + + const vm::ptr sinfo = vm::cast(spec_addr); + + if (sinfo) + { + if (sinfo->thisSize != sizeof(CellVdecMpeg4SpecificInfo)) + { + return { CELL_VDEC_ERROR_ARG, "Invalid MPEG4 specific info size %d", sinfo->thisSize }; + } + } + + // TODO: sinfo + + const u32 maxDecH = sinfo ? +sinfo->maxDecodedFrameHeight : 0; + const u32 maxDecW = sinfo ? +sinfo->maxDecodedFrameWidth : 0; + + switch (profile) + { + case CELL_VDEC_MPEG4_SP_L1: + { + if (maxDecW > 176 || maxDecH > 144) + { + return { CELL_VDEC_ERROR_ARG, "Invalid max decoded frame size %dx%d for profile %d", maxDecH, maxDecW, profile }; + } + + memSize = new_sdk ? 0x8B78B : 0xBB70B; + break; + } + case CELL_VDEC_MPEG4_SP_L2: + case CELL_VDEC_MPEG4_SP_L3: + { + if (maxDecW > 352 || maxDecH > 288) + { + return { CELL_VDEC_ERROR_ARG, "Invalid max decoded frame size %dx%d for profile %d", maxDecH, maxDecW, profile }; + } + + memSize = new_sdk ? 0xEFE0B : 0x11FD8B; + break; + } + case CELL_VDEC_MPEG4_SP_D1_NTSC: + { + if (maxDecW > 720 || maxDecH > 480) + { + return { CELL_VDEC_ERROR_ARG, "Invalid max decoded frame size %dx%d for profile %d", maxDecH, maxDecW, profile }; + } + + memSize = new_sdk ? 0x22DB0B : 0x25DA8B; + break; + } + case CELL_VDEC_MPEG4_SP_VGA: + { + if (maxDecW > 640 || maxDecH > 480) + { + return { CELL_VDEC_ERROR_ARG, "Invalid max decoded frame size %dx%d for profile %d", maxDecH, maxDecW, profile }; + } + + memSize = new_sdk ? 0x1FC00B : 0x22BF8B; + break; + } + case CELL_VDEC_MPEG4_SP_D1_PAL: + { + if (maxDecW > 720 || maxDecH > 576) + { + return { CELL_VDEC_ERROR_ARG, "Invalid max decoded frame size %dx%d for profile %d", maxDecH, maxDecW, profile }; + } + + memSize = new_sdk ? 0x28570B : 0x2B568B; + break; + } + default: return { CELL_VDEC_ERROR_ARG, "Invalid MPEG4 profile %d", profile }; + } + + decoderVerLower = 0x1080000; + break; + } case CELL_VDEC_CODEC_TYPE_DIVX: { cellVdec.warning("cellVdecQueryAttr: DivX (profile=%d)", profile); @@ -822,9 +899,6 @@ static error_code vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0 { case CELL_VDEC_DIVX_QMOBILE : memSize = new_sdk ? 0x11B720 : 0x1DEF30; break; case CELL_VDEC_DIVX_MOBILE : memSize = new_sdk ? 0x19A740 : 0x26DED0; break; - case CELL_VDEC_MPEG4_PROFILE_1: - case CELL_VDEC_MPEG4_PROFILE_3: - case CELL_VDEC_MPEG4_PROFILE_4: // just a guess based on the profile used by singstar before and after update case CELL_VDEC_DIVX_HOME_THEATER: memSize = new_sdk ? 0x386A60 : 0x498060; break; case CELL_VDEC_DIVX_HD_720 : memSize = new_sdk ? 0x692070 : 0x805690; break; case CELL_VDEC_DIVX_HD_1080 : memSize = new_sdk ? 0xD78100 : 0xFC9870; break; @@ -1527,6 +1601,7 @@ error_code cellVdecGetPicItem(ppu_thread& ppu, u32 handle, vm::pptrreserved[0] = 0; avc->reserved[1] = 0; } + // TODO: handle MPEG4 properly else if (vdec->type == CELL_VDEC_CODEC_TYPE_MPEG4 || vdec->type == CELL_VDEC_CODEC_TYPE_DIVX) { const vm::ptr dvx = picinfo_addr; diff --git a/rpcs3/Emu/Cell/Modules/cellVdec.h b/rpcs3/Emu/Cell/Modules/cellVdec.h index c8d6df4ae4..b18530ca33 100644 --- a/rpcs3/Emu/Cell/Modules/cellVdec.h +++ b/rpcs3/Emu/Cell/Modules/cellVdec.h @@ -389,9 +389,6 @@ struct CellVdecAvcInfo // DIVX Profile enum DIVX_level : u8 { - CELL_VDEC_MPEG4_PROFILE_1 = 1, // SingStar Vol.2 / Vol.3 - CELL_VDEC_MPEG4_PROFILE_3 = 3, // Used for SingStar recordings - CELL_VDEC_MPEG4_PROFILE_4 = 4, // SingStar Pop CELL_VDEC_DIVX_QMOBILE = 10, CELL_VDEC_DIVX_MOBILE = 11, CELL_VDEC_DIVX_HOME_THEATER = 12, @@ -676,3 +673,20 @@ struct CellVdecMpeg2Info u8 ccData[2][128]; be_t reserved[2]; }; + +enum MPEG4_level +{ + CELL_VDEC_MPEG4_SP_L1, + CELL_VDEC_MPEG4_SP_L2, + CELL_VDEC_MPEG4_SP_L3, + CELL_VDEC_MPEG4_SP_D1_NTSC, + CELL_VDEC_MPEG4_SP_VGA, + CELL_VDEC_MPEG4_SP_D1_PAL, +}; + +struct CellVdecMpeg4SpecificInfo +{ + be_t thisSize; + be_t maxDecodedFrameWidth; + be_t maxDecodedFrameHeight; +};