mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-12 12:45:56 +00:00
Add alternate code paths for handling legacy struct behavior in sceVideodec2GetPictureInfo (#3154)
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions
Build and Release / linux-sdl-gcc (push) Blocked by required conditions
Build and Release / linux-qt-gcc (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions
Some checks are pending
Build and Release / reuse (push) Waiting to run
Build and Release / clang-format (push) Waiting to run
Build and Release / get-info (push) Waiting to run
Build and Release / windows-sdl (push) Blocked by required conditions
Build and Release / windows-qt (push) Blocked by required conditions
Build and Release / macos-sdl (push) Blocked by required conditions
Build and Release / macos-qt (push) Blocked by required conditions
Build and Release / linux-sdl (push) Blocked by required conditions
Build and Release / linux-qt (push) Blocked by required conditions
Build and Release / linux-sdl-gcc (push) Blocked by required conditions
Build and Release / linux-qt-gcc (push) Blocked by required conditions
Build and Release / pre-release (push) Blocked by required conditions
Older games aren't fond of how our sceVideodec2GetPictureInfo implementation outputs AVC picture info after the struct size increase. Adding the old struct, and additional code using it for these games works around this problem.
This commit is contained in:
parent
9f37ede336
commit
0a58ead5f6
4 changed files with 117 additions and 22 deletions
|
@ -171,19 +171,40 @@ s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outp
|
|||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
if (outputInfo->pictureCount == 0 || gPictureInfos.empty()) {
|
||||
if (outputInfo->pictureCount == 0) {
|
||||
LOG_ERROR(Lib_Vdec2, "No picture info available");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
if (p1stPictureInfoOut) {
|
||||
OrbisVideodec2AvcPictureInfo* picInfo =
|
||||
static_cast<OrbisVideodec2AvcPictureInfo*>(p1stPictureInfoOut);
|
||||
if ((picInfo->thisSize | 16) != sizeof(OrbisVideodec2AvcPictureInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
// If the game uses the older Videodec2 structs, we need to accomodate that.
|
||||
if (outputInfo->thisSize != sizeof(OrbisVideodec2OutputInfo)) {
|
||||
if (gLegacyPictureInfos.empty()) {
|
||||
LOG_ERROR(Lib_Vdec2, "No picture info available");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
if (p1stPictureInfoOut) {
|
||||
OrbisVideodec2LegacyAvcPictureInfo* picInfo =
|
||||
static_cast<OrbisVideodec2LegacyAvcPictureInfo*>(p1stPictureInfoOut);
|
||||
if (picInfo->thisSize != sizeof(OrbisVideodec2LegacyAvcPictureInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
*picInfo = gLegacyPictureInfos.back();
|
||||
}
|
||||
} else {
|
||||
if (gPictureInfos.empty()) {
|
||||
LOG_ERROR(Lib_Vdec2, "No picture info available");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
if (p1stPictureInfoOut) {
|
||||
OrbisVideodec2AvcPictureInfo* picInfo =
|
||||
static_cast<OrbisVideodec2AvcPictureInfo*>(p1stPictureInfoOut);
|
||||
if (picInfo->thisSize != sizeof(OrbisVideodec2AvcPictureInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
*picInfo = gPictureInfos.back();
|
||||
}
|
||||
*picInfo = gPictureInfos.back();
|
||||
}
|
||||
|
||||
if (outputInfo->pictureCount > 1) {
|
||||
|
|
|
@ -74,4 +74,57 @@ struct OrbisVideodec2AvcPictureInfo {
|
|||
};
|
||||
static_assert(sizeof(OrbisVideodec2AvcPictureInfo) == 0x78);
|
||||
|
||||
// An older version of the OrbisVideodec2AvcPictureInfo struct
|
||||
// Keeping this is needed for compatiblity with older games.
|
||||
struct OrbisVideodec2LegacyAvcPictureInfo {
|
||||
u64 thisSize;
|
||||
|
||||
bool isValid;
|
||||
|
||||
u64 ptsData;
|
||||
u64 dtsData;
|
||||
u64 attachedData;
|
||||
|
||||
u8 idrPictureflag;
|
||||
|
||||
u8 profile_idc;
|
||||
u8 level_idc;
|
||||
u32 pic_width_in_mbs_minus1;
|
||||
u32 pic_height_in_map_units_minus1;
|
||||
u8 frame_mbs_only_flag;
|
||||
|
||||
u8 frame_cropping_flag;
|
||||
u32 frameCropLeftOffset;
|
||||
u32 frameCropRightOffset;
|
||||
u32 frameCropTopOffset;
|
||||
u32 frameCropBottomOffset;
|
||||
|
||||
u8 aspect_ratio_info_present_flag;
|
||||
u8 aspect_ratio_idc;
|
||||
u16 sar_width;
|
||||
u16 sar_height;
|
||||
|
||||
u8 video_signal_type_present_flag;
|
||||
u8 video_format;
|
||||
u8 video_full_range_flag;
|
||||
u8 colour_description_present_flag;
|
||||
u8 colour_primaries;
|
||||
u8 transfer_characteristics;
|
||||
u8 matrix_coefficients;
|
||||
|
||||
u8 timing_info_present_flag;
|
||||
u32 num_units_in_tick;
|
||||
u32 time_scale;
|
||||
u8 fixed_frame_rate_flag;
|
||||
|
||||
u8 bitstream_restriction_flag;
|
||||
u8 max_dec_frame_buffering;
|
||||
|
||||
u8 pic_struct_present_flag;
|
||||
u8 pic_struct;
|
||||
u8 field_pic_flag;
|
||||
u8 bottom_field_flag;
|
||||
};
|
||||
static_assert(sizeof(OrbisVideodec2LegacyAvcPictureInfo) == 0x68);
|
||||
|
||||
} // namespace Libraries::Vdec2
|
|
@ -12,6 +12,7 @@
|
|||
namespace Libraries::Vdec2 {
|
||||
|
||||
std::vector<OrbisVideodec2AvcPictureInfo> gPictureInfos;
|
||||
std::vector<OrbisVideodec2LegacyAvcPictureInfo> gLegacyPictureInfos;
|
||||
|
||||
static inline void CopyNV12Data(u8* dst, const AVFrame& src) {
|
||||
std::memcpy(dst, src.data[0], src.width * src.height);
|
||||
|
@ -117,27 +118,46 @@ s32 VdecDecoder::Decode(const OrbisVideodec2InputData& inputData,
|
|||
outputInfo.isErrorFrame = false;
|
||||
outputInfo.pictureCount = 1; // TODO: 2 pictures for interlaced video
|
||||
|
||||
// Only set framePitchInBytes if the game uses the newer struct version.
|
||||
// For proper compatibility with older games, check the inputted OutputInfo struct size.
|
||||
if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) {
|
||||
// framePitchInBytes only exists in the newer struct.
|
||||
outputInfo.framePitchInBytes = frame->linesize[0];
|
||||
}
|
||||
if (outputInfo.isValid) {
|
||||
OrbisVideodec2AvcPictureInfo pictureInfo = {};
|
||||
|
||||
if (outputInfo.isValid) {
|
||||
OrbisVideodec2AvcPictureInfo pictureInfo = {};
|
||||
pictureInfo.thisSize = sizeof(OrbisVideodec2AvcPictureInfo);
|
||||
pictureInfo.isValid = true;
|
||||
|
||||
pictureInfo.thisSize = sizeof(OrbisVideodec2AvcPictureInfo);
|
||||
pictureInfo.isValid = true;
|
||||
pictureInfo.ptsData = inputData.ptsData;
|
||||
pictureInfo.dtsData = inputData.dtsData;
|
||||
pictureInfo.attachedData = inputData.attachedData;
|
||||
|
||||
pictureInfo.ptsData = inputData.ptsData;
|
||||
pictureInfo.dtsData = inputData.dtsData;
|
||||
pictureInfo.attachedData = inputData.attachedData;
|
||||
pictureInfo.frameCropLeftOffset = frame->crop_left;
|
||||
pictureInfo.frameCropRightOffset = frame->crop_right;
|
||||
pictureInfo.frameCropTopOffset = frame->crop_top;
|
||||
pictureInfo.frameCropBottomOffset = frame->crop_bottom;
|
||||
|
||||
pictureInfo.frameCropLeftOffset = frame->crop_left;
|
||||
pictureInfo.frameCropRightOffset = frame->crop_right;
|
||||
pictureInfo.frameCropTopOffset = frame->crop_top;
|
||||
pictureInfo.frameCropBottomOffset = frame->crop_bottom;
|
||||
gPictureInfos.push_back(pictureInfo);
|
||||
}
|
||||
} else {
|
||||
if (outputInfo.isValid) {
|
||||
// If the game uses the older struct versions, we need to use it too.
|
||||
OrbisVideodec2LegacyAvcPictureInfo pictureInfo = {};
|
||||
|
||||
gPictureInfos.push_back(pictureInfo);
|
||||
pictureInfo.thisSize = sizeof(OrbisVideodec2LegacyAvcPictureInfo);
|
||||
pictureInfo.isValid = true;
|
||||
|
||||
pictureInfo.ptsData = inputData.ptsData;
|
||||
pictureInfo.dtsData = inputData.dtsData;
|
||||
pictureInfo.attachedData = inputData.attachedData;
|
||||
|
||||
pictureInfo.frameCropLeftOffset = frame->crop_left;
|
||||
pictureInfo.frameCropRightOffset = frame->crop_right;
|
||||
pictureInfo.frameCropTopOffset = frame->crop_top;
|
||||
pictureInfo.frameCropBottomOffset = frame->crop_bottom;
|
||||
|
||||
gLegacyPictureInfos.push_back(pictureInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ extern "C" {
|
|||
namespace Libraries::Vdec2 {
|
||||
|
||||
extern std::vector<OrbisVideodec2AvcPictureInfo> gPictureInfos;
|
||||
extern std::vector<OrbisVideodec2LegacyAvcPictureInfo> gLegacyPictureInfos;
|
||||
|
||||
class VdecDecoder {
|
||||
public:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue