mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-10 01:24:41 -06:00
h264: Improve H264DECMemoryRequirement
This commit is contained in:
parent
a5d8ceb0dd
commit
a39e99ecd4
@ -39,7 +39,7 @@ namespace H264
|
|||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
MEMPTR<void> outputFunc{ nullptr };
|
MEMPTR<void> outputFunc{ nullptr };
|
||||||
uint8be outputPerFrame{ 0 }; // whats the default?
|
uint8be outputPerFrame{ 0 }; // default is 0
|
||||||
MEMPTR<void> userMemoryParam{ nullptr };
|
MEMPTR<void> userMemoryParam{ nullptr };
|
||||||
}Param;
|
}Param;
|
||||||
// misc
|
// misc
|
||||||
@ -52,18 +52,18 @@ namespace H264
|
|||||||
}decoderState;
|
}decoderState;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32 H264DECMemoryRequirement(uint32 codecProfile, uint32 codecLevel, uint32 width, uint32 height, uint32be* sizeRequirementOut)
|
H264DEC_STATUS H264DECMemoryRequirement(uint32 codecProfile, uint32 codecLevel, uint32 width, uint32 height, uint32be* sizeRequirementOut)
|
||||||
{
|
{
|
||||||
if (H264_IsBotW())
|
if (H264_IsBotW())
|
||||||
{
|
{
|
||||||
static_assert(sizeof(H264Context) < 256);
|
static_assert(sizeof(H264Context) < 256);
|
||||||
*sizeRequirementOut = 256;
|
*sizeRequirementOut = 256;
|
||||||
return 0;
|
return H264DEC_STATUS::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: On console this seems to check if maxWidth or maxHeight < 64 but Pikmin 3 passes 32x32 and crashes if this function fails ?
|
// note: On console this seems to check if maxWidth or maxHeight < 64 but Pikmin 3 passes 32x32 and crashes if this function fails ?
|
||||||
if (width < 0x20 || height < 0x20 || width > 2800 || height > 1408 || sizeRequirementOut == MPTR_NULL || codecLevel >= 52 || (codecProfile != 0x42 && codecProfile != 0x4D && codecProfile != 0x64))
|
if (width < 32 || height < 32 || width > 2800 || height > 1408 || !sizeRequirementOut || codecLevel >= 52 || (codecProfile != 66 && codecProfile != 77 && codecProfile != 100))
|
||||||
return 0x1010000;
|
return H264DEC_STATUS::INVALID_PARAM;
|
||||||
|
|
||||||
uint32 workbufferSize = 0;
|
uint32 workbufferSize = 0;
|
||||||
if (codecLevel < 0xB)
|
if (codecLevel < 0xB)
|
||||||
@ -112,7 +112,7 @@ namespace H264
|
|||||||
}
|
}
|
||||||
workbufferSize += 0x447;
|
workbufferSize += 0x447;
|
||||||
*sizeRequirementOut = workbufferSize;
|
*sizeRequirementOut = workbufferSize;
|
||||||
return 0;
|
return H264DEC_STATUS::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 H264DECCheckMemSegmentation(MPTR memory, uint32 size)
|
uint32 H264DECCheckMemSegmentation(MPTR memory, uint32 size)
|
||||||
@ -189,16 +189,15 @@ namespace H264
|
|||||||
return H264DEC_STATUS::BAD_STREAM;
|
return H264DEC_STATUS::BAD_STREAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
H264DEC_STATUS H264DECGetImageSize(uint8* stream, uint32 length, uint32 offset, uint32be* outputWidth, uint32be* outputHeight)
|
H264DEC_STATUS H264DECGetImageSize(uint8* stream, sint32 streamSize, sint32 offset, uint32be* outputWidth, uint32be* outputHeight)
|
||||||
{
|
{
|
||||||
if(!stream || length < 4 || !outputWidth || !outputHeight)
|
if (!stream || streamSize < 4 || offset < 0 || !outputWidth || !outputHeight || offset < streamSize)
|
||||||
return H264DEC_STATUS::INVALID_PARAM;
|
return H264DEC_STATUS::INVALID_PARAM;
|
||||||
if( (offset+4) > length )
|
if ( (offset+4) >= streamSize )
|
||||||
return H264DEC_STATUS::INVALID_PARAM;
|
return H264DEC_STATUS::INVALID_PARAM;
|
||||||
uint8* cur = stream + offset;
|
uint8* cur = stream + offset;
|
||||||
uint8* end = stream + length;
|
uint8* end = stream + streamSize;
|
||||||
cur += 2; // we access cur[-2] and cur[-1] so we need to start at offset 2
|
while (cur < end-2)
|
||||||
while(cur < end-2)
|
|
||||||
{
|
{
|
||||||
// check for start code
|
// check for start code
|
||||||
if(*cur != 1)
|
if(*cur != 1)
|
||||||
@ -207,7 +206,7 @@ namespace H264
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// check if this is a valid NAL header
|
// check if this is a valid NAL header
|
||||||
if(cur[-2] != 0 || cur[-1] != 0 || cur[0] != 1)
|
if(cur[-2] != 0 || cur[-1] != 0 || cur[0] != 1) // if offset is < 2, this will read out of bounds. The console implementation has this behavior too so we have to replicate this bug
|
||||||
{
|
{
|
||||||
cur++;
|
cur++;
|
||||||
continue;
|
continue;
|
||||||
@ -226,7 +225,14 @@ namespace H264
|
|||||||
return H264DEC_STATUS::BAD_STREAM;
|
return H264DEC_STATUS::BAD_STREAM;
|
||||||
}
|
}
|
||||||
*outputWidth = (psp.pic_width_in_mbs_minus1 + 1) * 16;
|
*outputWidth = (psp.pic_width_in_mbs_minus1 + 1) * 16;
|
||||||
*outputHeight = (psp.pic_height_in_map_units_minus1 + 1) * 16; // affected by frame_mbs_only_flag?
|
*outputHeight = (psp.pic_height_in_map_units_minus1 + 1) * 16;
|
||||||
|
if (!psp.frame_mbs_only_flag)
|
||||||
|
*outputHeight *= 2;
|
||||||
|
if (!*outputHeight || !*outputWidth)
|
||||||
|
return H264DEC_STATUS::BAD_STREAM;
|
||||||
|
// BotW 1080p video support
|
||||||
|
if (H264_IsBotW() && *outputWidth == 1920 && *outputHeight == 1088)
|
||||||
|
*outputHeight = 1080;
|
||||||
return H264DEC_STATUS::SUCCESS;
|
return H264DEC_STATUS::SUCCESS;
|
||||||
}
|
}
|
||||||
return H264DEC_STATUS::BAD_STREAM;
|
return H264DEC_STATUS::BAD_STREAM;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user