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.
This commit is contained in:
Daniel López Guimaraes 2026-01-14 18:21:56 +00:00 committed by Ani
parent ef9ff09e17
commit f70b5e0c1c
2 changed files with 95 additions and 6 deletions

View file

@ -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<CellVdecMpeg4SpecificInfo> 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::pptr<CellVdecPicI
avc->reserved[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<CellVdecDivxInfo> dvx = picinfo_addr;

View file

@ -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<u64> 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<u32> thisSize;
be_t<u16> maxDecodedFrameWidth;
be_t<u16> maxDecodedFrameHeight;
};