mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
456 lines
14 KiB
C++
456 lines
14 KiB
C++
#include "common/abi.h"
|
|
#include "libs/errno.h"
|
|
#include "libs/libs.h"
|
|
#include "loader/symbolDatabase.h"
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <mutex>
|
|
#include <unordered_set>
|
|
|
|
namespace Libs {
|
|
|
|
LIB_VERSION("Videodec2", 1, "Videodec2", 1, 1);
|
|
|
|
namespace VideoDec2 {
|
|
|
|
constexpr int32_t VIDEODEC2_ERROR_STRUCT_SIZE = -2128805631; // 0x811d0101
|
|
constexpr int32_t VIDEODEC2_ERROR_ARGUMENT_POINTER = -2128805630; // 0x811d0102
|
|
constexpr int32_t VIDEODEC2_ERROR_DECODER_INSTANCE = -2128805629; // 0x811d0103
|
|
constexpr int32_t VIDEODEC2_ERROR_MEMORY_SIZE = -2128805628; // 0x811d0104
|
|
constexpr int32_t VIDEODEC2_ERROR_MEMORY_POINTER = -2128805627; // 0x811d0105
|
|
constexpr int32_t VIDEODEC2_ERROR_FRAME_BUFFER_SIZE = -2128805626; // 0x811d0106
|
|
constexpr int32_t VIDEODEC2_ERROR_FRAME_BUFFER_POINTER = -2128805625; // 0x811d0107
|
|
constexpr int32_t VIDEODEC2_ERROR_CONFIG_INFO = -2128805376; // 0x811d0200
|
|
constexpr int32_t VIDEODEC2_ERROR_COMPUTE_PIPE_ID = -2128805375; // 0x811d0201
|
|
constexpr int32_t VIDEODEC2_ERROR_COMPUTE_QUEUE_ID = -2128805374; // 0x811d0202
|
|
constexpr int32_t VIDEODEC2_ERROR_RESOURCE_TYPE = -2128805373; // 0x811d0203
|
|
constexpr int32_t VIDEODEC2_ERROR_INPUT_QUEUE_DEPTH = -2128805370; // 0x811d0206
|
|
constexpr int32_t VIDEODEC2_ERROR_DPB_FRAME_COUNT = -2128805367; // 0x811d0209
|
|
constexpr int32_t VIDEODEC2_ERROR_FRAME_WIDTH_HEIGHT = -2128805366; // 0x811d020a
|
|
|
|
constexpr uint32_t VIDEODEC2_RESOURCE_TYPE_COMPUTE = 1;
|
|
constexpr size_t VIDEODEC2_MIN_MEMORY_SIZE = 16ull * 1024ull * 1024ull;
|
|
constexpr uint32_t VIDEODEC2_FRAME_FORMAT_DEFAULT = 0;
|
|
|
|
using Videodec2Decoder = void*;
|
|
using Videodec2ComputeQueue = void*;
|
|
|
|
struct Videodec2DecoderConfigInfo {
|
|
size_t this_size;
|
|
uint32_t resource_type;
|
|
uint32_t codec_type;
|
|
uint32_t profile;
|
|
uint32_t max_level;
|
|
int32_t max_frame_width;
|
|
int32_t max_frame_height;
|
|
int32_t max_dpb_frame_count;
|
|
uint32_t decode_input_queue_depth;
|
|
Videodec2ComputeQueue compute_queue;
|
|
uint64_t cpu_affinity_mask;
|
|
int32_t cpu_thread_priority;
|
|
bool optimize_progressive_video;
|
|
bool check_memory_type;
|
|
uint8_t reserved0;
|
|
uint8_t reserved1;
|
|
void* extra_config_info;
|
|
};
|
|
|
|
struct Videodec2DecoderMemoryInfo {
|
|
size_t this_size;
|
|
size_t cpu_memory_size;
|
|
void* cpu_memory;
|
|
size_t gpu_memory_size;
|
|
void* gpu_memory;
|
|
size_t cpu_gpu_memory_size;
|
|
void* cpu_gpu_memory;
|
|
size_t max_frame_buffer_size;
|
|
uint32_t frame_buffer_alignment;
|
|
uint32_t reserved0;
|
|
};
|
|
|
|
struct Videodec2InputData {
|
|
size_t this_size;
|
|
void* au_data;
|
|
size_t au_size;
|
|
uint64_t pts_data;
|
|
uint64_t dts_data;
|
|
uint64_t attached_data;
|
|
};
|
|
|
|
struct Videodec2OutputInfo {
|
|
size_t this_size;
|
|
bool is_valid;
|
|
bool is_error_frame;
|
|
uint8_t picture_count;
|
|
bool is_discarded_frame;
|
|
uint32_t codec_type;
|
|
uint32_t frame_width;
|
|
uint32_t frame_pitch;
|
|
uint32_t frame_height;
|
|
void* frame_buffer;
|
|
size_t frame_buffer_size;
|
|
uint32_t frame_format;
|
|
uint32_t frame_pitch_in_bytes;
|
|
};
|
|
|
|
struct Videodec2FrameBuffer {
|
|
size_t this_size;
|
|
void* frame_buffer;
|
|
size_t frame_buffer_size;
|
|
bool is_accepted;
|
|
};
|
|
|
|
struct Videodec2ComputeMemoryInfo {
|
|
size_t this_size;
|
|
size_t cpu_gpu_memory_size;
|
|
void* cpu_gpu_memory;
|
|
};
|
|
|
|
struct Videodec2ComputeConfigInfo {
|
|
size_t this_size;
|
|
uint16_t compute_pipe_id;
|
|
uint16_t compute_queue_id;
|
|
bool check_memory_type;
|
|
uint8_t reserved0;
|
|
uint16_t reserved1;
|
|
};
|
|
|
|
struct DecoderState {
|
|
uint64_t magic;
|
|
uint32_t codec_type;
|
|
};
|
|
|
|
static_assert(sizeof(Videodec2ComputeMemoryInfo) == 24);
|
|
static_assert(sizeof(Videodec2ComputeConfigInfo) == 16);
|
|
static_assert(sizeof(Videodec2DecoderConfigInfo) == 72);
|
|
static_assert(sizeof(Videodec2DecoderMemoryInfo) == 72);
|
|
static_assert(sizeof(Videodec2InputData) == 48);
|
|
static_assert(sizeof(Videodec2OutputInfo) == 56);
|
|
static_assert(sizeof(Videodec2FrameBuffer) == 32);
|
|
|
|
constexpr uint64_t DECODER_MAGIC = 0x4b59545956444543ull; // KYTYVDEC
|
|
|
|
static std::mutex g_decoder_mutex;
|
|
static std::unordered_set<void*> g_decoders;
|
|
|
|
static bool IsOutputInfoSizeValid(size_t this_size) {
|
|
return this_size == sizeof(Videodec2OutputInfo) ||
|
|
(this_size | 8u) == sizeof(Videodec2OutputInfo);
|
|
}
|
|
|
|
static DecoderState* GetDecoder(Videodec2Decoder decoder) {
|
|
std::scoped_lock lock(g_decoder_mutex);
|
|
return g_decoders.contains(decoder) ? static_cast<DecoderState*>(decoder) : nullptr;
|
|
}
|
|
|
|
static void FillNoPictureOutput(const Videodec2FrameBuffer* frame_buffer,
|
|
Videodec2OutputInfo* output_info, uint32_t codec_type) {
|
|
output_info->is_valid = false;
|
|
output_info->is_error_frame = false;
|
|
output_info->picture_count = 0;
|
|
output_info->is_discarded_frame = false;
|
|
output_info->codec_type = codec_type;
|
|
output_info->frame_width = 0;
|
|
output_info->frame_pitch = 0;
|
|
output_info->frame_height = 0;
|
|
output_info->frame_buffer = frame_buffer != nullptr ? frame_buffer->frame_buffer : nullptr;
|
|
output_info->frame_buffer_size = frame_buffer != nullptr ? frame_buffer->frame_buffer_size : 0;
|
|
output_info->frame_format = VIDEODEC2_FRAME_FORMAT_DEFAULT;
|
|
output_info->frame_pitch_in_bytes = 0;
|
|
}
|
|
|
|
static int32_t ValidateDecoderConfig(const Videodec2DecoderConfigInfo* config) {
|
|
if (config->resource_type != VIDEODEC2_RESOURCE_TYPE_COMPUTE) {
|
|
return VIDEODEC2_ERROR_RESOURCE_TYPE;
|
|
}
|
|
|
|
if (config->reserved0 != 0 || config->reserved1 != 0) {
|
|
return VIDEODEC2_ERROR_CONFIG_INFO;
|
|
}
|
|
|
|
if (config->decode_input_queue_depth == 0) {
|
|
return VIDEODEC2_ERROR_INPUT_QUEUE_DEPTH;
|
|
}
|
|
|
|
if (config->max_dpb_frame_count < -1 || config->max_dpb_frame_count == 0) {
|
|
return VIDEODEC2_ERROR_DPB_FRAME_COUNT;
|
|
}
|
|
|
|
if (config->max_frame_width < -1 || config->max_frame_height < -1 ||
|
|
config->max_frame_width == 0 || config->max_frame_height == 0) {
|
|
return VIDEODEC2_ERROR_FRAME_WIDTH_HEIGHT;
|
|
}
|
|
|
|
if (config->compute_queue == nullptr) {
|
|
return VIDEODEC2_ERROR_CONFIG_INFO;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI
|
|
QueryComputeMemoryInfo(Videodec2ComputeMemoryInfo* compute_memory_info) {
|
|
PRINT_NAME();
|
|
|
|
if (compute_memory_info == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (compute_memory_info->this_size != sizeof(Videodec2ComputeMemoryInfo)) {
|
|
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
|
}
|
|
|
|
compute_memory_info->cpu_gpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
|
compute_memory_info->cpu_gpu_memory = nullptr;
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI AllocateComputeQueue(
|
|
const Videodec2ComputeConfigInfo* compute_config_info,
|
|
const Videodec2ComputeMemoryInfo* compute_memory_info, Videodec2ComputeQueue* compute_queue) {
|
|
PRINT_NAME();
|
|
|
|
if (compute_config_info == nullptr || compute_memory_info == nullptr ||
|
|
compute_queue == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (compute_config_info->this_size != sizeof(Videodec2ComputeConfigInfo) ||
|
|
compute_memory_info->this_size != sizeof(Videodec2ComputeMemoryInfo)) {
|
|
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
|
}
|
|
|
|
if (compute_config_info->reserved0 != 0 || compute_config_info->reserved1 != 0) {
|
|
return VIDEODEC2_ERROR_CONFIG_INFO;
|
|
}
|
|
|
|
if (compute_config_info->compute_pipe_id > 4) {
|
|
return VIDEODEC2_ERROR_COMPUTE_PIPE_ID;
|
|
}
|
|
|
|
if (compute_config_info->compute_queue_id > 7) {
|
|
return VIDEODEC2_ERROR_COMPUTE_QUEUE_ID;
|
|
}
|
|
|
|
if (compute_memory_info->cpu_gpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE) {
|
|
return VIDEODEC2_ERROR_MEMORY_SIZE;
|
|
}
|
|
|
|
if (compute_memory_info->cpu_gpu_memory == nullptr) {
|
|
return VIDEODEC2_ERROR_MEMORY_POINTER;
|
|
}
|
|
|
|
*compute_queue = compute_memory_info->cpu_gpu_memory;
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI ReleaseComputeQueue(Videodec2ComputeQueue compute_queue) {
|
|
PRINT_NAME();
|
|
|
|
return compute_queue != nullptr ? OK : VIDEODEC2_ERROR_COMPUTE_QUEUE_ID;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI QueryDecoderMemoryInfo(const Videodec2DecoderConfigInfo* config,
|
|
Videodec2DecoderMemoryInfo* memory_info) {
|
|
PRINT_NAME();
|
|
|
|
if (config == nullptr || memory_info == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (config->this_size != sizeof(Videodec2DecoderConfigInfo) ||
|
|
memory_info->this_size != sizeof(Videodec2DecoderMemoryInfo)) {
|
|
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
|
}
|
|
|
|
const auto validation_result = ValidateDecoderConfig(config);
|
|
if (validation_result != OK) {
|
|
return validation_result;
|
|
}
|
|
|
|
memory_info->cpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
|
memory_info->cpu_memory = nullptr;
|
|
memory_info->gpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
|
memory_info->gpu_memory = nullptr;
|
|
memory_info->cpu_gpu_memory_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
|
memory_info->cpu_gpu_memory = nullptr;
|
|
memory_info->max_frame_buffer_size = VIDEODEC2_MIN_MEMORY_SIZE;
|
|
memory_info->frame_buffer_alignment = 0x100;
|
|
memory_info->reserved0 = 0;
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI CreateDecoder(const Videodec2DecoderConfigInfo* config,
|
|
const Videodec2DecoderMemoryInfo* memory_info,
|
|
Videodec2Decoder* decoder) {
|
|
PRINT_NAME();
|
|
|
|
if (config == nullptr || memory_info == nullptr || decoder == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (config->this_size != sizeof(Videodec2DecoderConfigInfo) ||
|
|
memory_info->this_size != sizeof(Videodec2DecoderMemoryInfo)) {
|
|
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
|
}
|
|
|
|
const auto validation_result = ValidateDecoderConfig(config);
|
|
if (validation_result != OK) {
|
|
return validation_result;
|
|
}
|
|
|
|
if (memory_info->cpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE ||
|
|
memory_info->gpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE ||
|
|
memory_info->cpu_gpu_memory_size < VIDEODEC2_MIN_MEMORY_SIZE ||
|
|
memory_info->max_frame_buffer_size < VIDEODEC2_MIN_MEMORY_SIZE) {
|
|
return VIDEODEC2_ERROR_MEMORY_SIZE;
|
|
}
|
|
|
|
if (memory_info->cpu_memory == nullptr || memory_info->gpu_memory == nullptr ||
|
|
memory_info->cpu_gpu_memory == nullptr) {
|
|
return VIDEODEC2_ERROR_MEMORY_POINTER;
|
|
}
|
|
|
|
auto* state = new DecoderState {};
|
|
state->magic = DECODER_MAGIC;
|
|
state->codec_type = config->codec_type;
|
|
|
|
{
|
|
std::scoped_lock lock(g_decoder_mutex);
|
|
g_decoders.insert(state);
|
|
}
|
|
|
|
*decoder = state;
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI DeleteDecoder(Videodec2Decoder decoder) {
|
|
PRINT_NAME();
|
|
|
|
DecoderState* state = nullptr;
|
|
{
|
|
std::scoped_lock lock(g_decoder_mutex);
|
|
auto it = g_decoders.find(decoder);
|
|
if (it == g_decoders.end()) {
|
|
return VIDEODEC2_ERROR_DECODER_INSTANCE;
|
|
}
|
|
state = static_cast<DecoderState*>(*it);
|
|
g_decoders.erase(it);
|
|
}
|
|
|
|
delete state;
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI Decode(Videodec2Decoder decoder, const Videodec2InputData* input_data,
|
|
Videodec2FrameBuffer* frame_buffer,
|
|
Videodec2OutputInfo* output_info) {
|
|
PRINT_NAME();
|
|
|
|
const auto* state = GetDecoder(decoder);
|
|
if (state == nullptr || state->magic != DECODER_MAGIC) {
|
|
return VIDEODEC2_ERROR_DECODER_INSTANCE;
|
|
}
|
|
|
|
if (input_data == nullptr || frame_buffer == nullptr || output_info == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (input_data->this_size != sizeof(Videodec2InputData) ||
|
|
frame_buffer->this_size != sizeof(Videodec2FrameBuffer) ||
|
|
!IsOutputInfoSizeValid(output_info->this_size)) {
|
|
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
|
}
|
|
|
|
if (input_data->au_size != 0 && input_data->au_data == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (frame_buffer->frame_buffer_size == 0) {
|
|
return VIDEODEC2_ERROR_FRAME_BUFFER_SIZE;
|
|
}
|
|
|
|
if (frame_buffer->frame_buffer == nullptr) {
|
|
return VIDEODEC2_ERROR_FRAME_BUFFER_POINTER;
|
|
}
|
|
|
|
frame_buffer->is_accepted = false;
|
|
FillNoPictureOutput(frame_buffer, output_info, state->codec_type);
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI Flush(Videodec2Decoder decoder, Videodec2FrameBuffer* frame_buffer,
|
|
Videodec2OutputInfo* output_info) {
|
|
PRINT_NAME();
|
|
|
|
const auto* state = GetDecoder(decoder);
|
|
if (state == nullptr || state->magic != DECODER_MAGIC) {
|
|
return VIDEODEC2_ERROR_DECODER_INSTANCE;
|
|
}
|
|
|
|
if (frame_buffer == nullptr || output_info == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (frame_buffer->this_size != sizeof(Videodec2FrameBuffer) ||
|
|
!IsOutputInfoSizeValid(output_info->this_size)) {
|
|
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
|
}
|
|
|
|
frame_buffer->is_accepted = false;
|
|
FillNoPictureOutput(frame_buffer, output_info, state->codec_type);
|
|
|
|
return OK;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI Reset(Videodec2Decoder decoder) {
|
|
PRINT_NAME();
|
|
|
|
const auto* state = GetDecoder(decoder);
|
|
return state != nullptr && state->magic == DECODER_MAGIC ? OK
|
|
: VIDEODEC2_ERROR_DECODER_INSTANCE;
|
|
}
|
|
|
|
static int32_t KYTY_SYSV_ABI GetPictureInfo(const Videodec2OutputInfo* output_info,
|
|
void* /*first_picture_info*/,
|
|
void* /*second_picture_info*/) {
|
|
PRINT_NAME();
|
|
|
|
if (output_info == nullptr) {
|
|
return VIDEODEC2_ERROR_ARGUMENT_POINTER;
|
|
}
|
|
|
|
if (!IsOutputInfoSizeValid(output_info->this_size)) {
|
|
return VIDEODEC2_ERROR_STRUCT_SIZE;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
LIB_DEFINE(InitVideoDec2_1) {
|
|
PRINT_NAME_ENABLE(true);
|
|
|
|
LIB_FUNC("RnDibcGCPKw", QueryComputeMemoryInfo);
|
|
LIB_FUNC("eD+X2SmxUt4", AllocateComputeQueue);
|
|
LIB_FUNC("UvtA3FAiF4Y", ReleaseComputeQueue);
|
|
LIB_FUNC("qqMCwlULR+E", QueryDecoderMemoryInfo);
|
|
LIB_FUNC("CNNRoRYd8XI", CreateDecoder);
|
|
LIB_FUNC("jwImxXRGSKA", DeleteDecoder);
|
|
LIB_FUNC("852F5+q6+iM", Decode);
|
|
LIB_FUNC("l1hXwscLuCY", Flush);
|
|
LIB_FUNC("wJXikG6QFN8", Reset);
|
|
LIB_FUNC("NtXRa3dRzU0", GetPictureInfo);
|
|
LIB_FUNC("kjrLbcyhEiw", GetPictureInfo);
|
|
}
|
|
|
|
} // namespace VideoDec2
|
|
|
|
} // namespace Libs
|