Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cellVdec Fixup #7384

Merged
merged 3 commits into from
Feb 5, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
115 changes: 97 additions & 18 deletions rpcs3/Emu/Cell/Modules/cellVdec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,10 @@ static error_code vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0
{
cellVdec.warning("cellVdecQueryAttr: AVC (profile=%d)", profile);

const vm::ptr<CellVdecAvcSpecificInfo> sinfo = vm::cast(spec_addr);

// TODO: sinfo

switch (profile)
{
case CELL_VDEC_AVC_LEVEL_1P0: memSize = new_sdk ? 0x70167D : 0xA014FD ; break;
Expand All @@ -472,12 +476,63 @@ static error_code vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0
{
cellVdec.warning("cellVdecQueryAttr: MPEG2 (profile=%d)", profile);

const vm::ptr<CellVdecMpeg2SpecificInfo> sinfo = vm::cast(spec_addr);

if (sinfo)
{
if (sinfo->thisSize != sizeof(CellVdecMpeg2SpecificInfo))
{
return CELL_VDEC_ERROR_ARG;
}
}

// TODO: sinfo

const u32 maxDecH = sinfo ? +sinfo->maxDecodedFrameHeight : 0;
const u32 maxDecW = sinfo ? +sinfo->maxDecodedFrameWidth : 0;

switch (profile)
{
case CELL_VDEC_MPEG2_MP_LL : memSize = new_sdk ? 0x11290B : 0x2A610B; break;
case CELL_VDEC_MPEG2_MP_ML : memSize = new_sdk ? 0x2DFB8B : 0x47110B; break;
case CELL_VDEC_MPEG2_MP_H14: memSize = new_sdk ? 0xA0270B : 0xB8F90B; break;
case CELL_VDEC_MPEG2_MP_HL : memSize = new_sdk ? 0xD2F40B : 0xEB990B; break;
case CELL_VDEC_MPEG2_MP_LL:
{
if (maxDecW > 352 || maxDecH > 288)
{
return CELL_VDEC_ERROR_ARG;
}

memSize = new_sdk ? 0x11290B : 0x2A610B;
break;
}
case CELL_VDEC_MPEG2_MP_ML:
{
if (maxDecW > 720 || maxDecH > 576)
{
return CELL_VDEC_ERROR_ARG;
}

memSize = new_sdk ? 0x2DFB8B : 0x47110B;
break;
}
case CELL_VDEC_MPEG2_MP_H14:
{
if (maxDecW > 1440 || maxDecH > 1152)
{
return CELL_VDEC_ERROR_ARG;
}

memSize = new_sdk ? 0xA0270B : 0xB8F90B;
break;
}
case CELL_VDEC_MPEG2_MP_HL:
{
if (maxDecW > 1920 || maxDecH > 1152)
{
return CELL_VDEC_ERROR_ARG;
}

memSize = new_sdk ? 0xD2F40B : 0xEB990B;
break;
}
default: return CELL_VDEC_ERROR_ARG;
}

Expand All @@ -488,6 +543,10 @@ static error_code vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0
{
cellVdec.warning("cellVdecQueryAttr: DivX (profile=%d)", profile);

const vm::ptr<CellVdecDivxSpecificInfo2> sinfo = vm::cast(spec_addr);

// TODO: sinfo

switch (profile)
{
case CELL_VDEC_DIVX_QMOBILE : memSize = new_sdk ? 0x11B720 : 0x1DEF30; break;
Expand All @@ -497,6 +556,7 @@ static error_code vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0
case CELL_VDEC_DIVX_HD_1080 : memSize = new_sdk ? 0xD78100 : 0xFC9870; break;
default: return CELL_VDEC_ERROR_ARG;
}

decoderVerLower = 0x30806;
break;
}
Expand All @@ -505,7 +565,7 @@ static error_code vdecQueryAttr(s32 type, u32 profile, u32 spec_addr /* may be 0

attr->decoderVerLower = decoderVerLower;
attr->decoderVerUpper = 0x4840010;
attr->memSize = verify(HERE, memSize);
attr->memSize = !spec_addr ? verify(HERE, memSize) : 4 * 1024 * 1024;
attr->cmdDepth = 4;
return CELL_OK;
}
Expand Down Expand Up @@ -548,8 +608,15 @@ static error_code vdecOpen(ppu_thread& ppu, T type, U res, vm::cptr<CellVdecCb>
return CELL_VDEC_ERROR_ARG;
}

u32 spec_addr = 0;

if constexpr (std::is_same_v<std::decay_t<typename T::type>, CellVdecTypeEx>)
{
spec_addr = type->codecSpecificInfo_addr;
}

if (CellVdecAttr attr{};
vdecQueryAttr(type->codecType, type->profileLevel, 0, &attr) != CELL_OK ||
vdecQueryAttr(type->codecType, type->profileLevel, spec_addr, &attr) != CELL_OK ||
attr.memSize > res->memSize)
{
return CELL_VDEC_ERROR_ARG;
Expand Down Expand Up @@ -833,11 +900,18 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)

// TODO: return CELL_VDEC_ERROR_SEQ

struct all_info_t
{
CellVdecPicItem picItem;
std::aligned_union_t<0, CellVdecAvcInfo, CellVdecDivxInfo, CellVdecMpeg2Info> picInfo;
};

AVFrame* frame{};
u64 pts;
u64 dts;
u64 usrd;
u32 frc;
vm::ptr<CellVdecPicItem> info;
{
std::lock_guard lock(vdec->mutex);

Expand All @@ -851,6 +925,17 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
dts = picture.dts;
usrd = picture.userdata;
frc = picture.frc;
info.set(vdec->mem_addr + vdec->mem_bias);

constexpr u64 size_needed = sizeof(all_info_t);

if (vdec->mem_bias + size_needed >= vdec->mem_size / size_needed * size_needed)
{
vdec->mem_bias = 0;
break;
}

vdec->mem_bias += size_needed;
break;
}
}
Expand All @@ -862,14 +947,6 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
return CELL_VDEC_ERROR_EMPTY;
}

const vm::ptr<CellVdecPicItem> info = vm::cast(vdec->mem_addr + vdec->mem_bias);

vdec->mem_bias += 512;
if (vdec->mem_bias + 512 > vdec->mem_size)
{
vdec->mem_bias = 0;
}

info->codecType = vdec->type;
info->startAddr = 0x00000123; // invalid value (no address for picture)
const int buffer_size = av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1);
Expand All @@ -888,11 +965,13 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
info->auUserData[1] = 0;
info->status = CELL_OK;
info->attr = CELL_VDEC_PICITEM_ATTR_NORMAL;
info->picInfo_addr = info.addr() + u32{sizeof(CellVdecPicItem)};

const vm::addr_t picinfo_addr{info.addr() + ::offset32(&all_info_t::picInfo)};
info->picInfo_addr = picinfo_addr;

if (vdec->type == CELL_VDEC_CODEC_TYPE_AVC)
{
const vm::ptr<CellVdecAvcInfo> avc = vm::cast(info.addr() + u32{sizeof(CellVdecPicItem)});
const vm::ptr<CellVdecAvcInfo> avc = picinfo_addr;

avc->horizontalSize = frame->width;
avc->verticalSize = frame->height;
Expand Down Expand Up @@ -948,7 +1027,7 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
}
else if (vdec->type == CELL_VDEC_CODEC_TYPE_DIVX)
{
const vm::ptr<CellVdecDivxInfo> dvx = vm::cast(info.addr() + u32{sizeof(CellVdecPicItem)});
const vm::ptr<CellVdecDivxInfo> dvx = picinfo_addr;

switch (s32 pct = frame->pict_type)
{
Expand Down Expand Up @@ -984,7 +1063,7 @@ error_code cellVdecGetPicItem(u32 handle, vm::pptr<CellVdecPicItem> picItem)
}
else if (vdec->type == CELL_VDEC_CODEC_TYPE_MPEG2)
{
const vm::ptr<CellVdecMpeg2Info> mp2 = vm::cast(info.addr() + u32{sizeof(CellVdecPicItem)});
const vm::ptr<CellVdecMpeg2Info> mp2 = picinfo_addr;

std::memset(mp2.get_ptr(), 0, sizeof(CellVdecMpeg2Info));
mp2->horizontal_size = frame->width;
Expand Down