mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 14:05:29 +03:00
Implement OpenHardwareOpusDecoderEx and GetWorkBufferSizeEx
Implements these 2 functions which were introduced in HOS 12.0.0. Fixes a crash in Xenoblade Chronicles 3.
This commit is contained in:
parent
34bd16426c
commit
a1ff4e1777
@ -11,12 +11,12 @@ namespace skyline::service::codec {
|
||||
return util::AlignUp(static_cast<u32>(frameSize * channelCount / (OpusFullbandSampleRate / sampleRate)), 0x40);
|
||||
}
|
||||
|
||||
IHardwareOpusDecoder::IHardwareOpusDecoder(const DeviceState &state, ServiceManager &manager, i32 sampleRate, i32 channelCount, u32 workBufferSize, KHandle workBufferHandle)
|
||||
IHardwareOpusDecoder::IHardwareOpusDecoder(const DeviceState &state, ServiceManager &manager, i32 sampleRate, i32 channelCount, u32 workBufferSize, KHandle workBufferHandle, bool isIsLargerSize)
|
||||
: BaseService(state, manager),
|
||||
sampleRate(sampleRate),
|
||||
channelCount(channelCount),
|
||||
workBuffer(state.process->GetHandle<kernel::type::KTransferMemory>(workBufferHandle)),
|
||||
decoderOutputBufferSize(CalculateOutBufferSize(sampleRate, channelCount, MaxFrameSizeNormal)) {
|
||||
decoderOutputBufferSize(CalculateOutBufferSize(sampleRate, channelCount, isIsLargerSize ? MaxFrameSizeEx : MaxFrameSizeNormal)) {
|
||||
if (workBufferSize < decoderOutputBufferSize)
|
||||
throw exception("Work Buffer doesn't have adequate space for Opus Decoder: 0x{:X} (Required: 0x{:X})", workBufferSize, decoderOutputBufferSize);
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace skyline::service::codec {
|
||||
Result DecodeInterleavedImpl(ipc::IpcRequest &request, ipc::IpcResponse &response, bool writeDecodeTime = false);
|
||||
|
||||
public:
|
||||
IHardwareOpusDecoder(const DeviceState &state, ServiceManager &manager, i32 sampleRate, i32 channelCount, u32 workBufferSize, KHandle workBufferHandle);
|
||||
IHardwareOpusDecoder(const DeviceState &state, ServiceManager &manager, i32 sampleRate, i32 channelCount, u32 workBufferSize, KHandle workBufferHandle, bool isIsLargerSize = false);
|
||||
|
||||
/**
|
||||
* @brief Decodes the Opus source data, returns decoded data size and decoded sample count
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include "IHardwareOpusDecoder.h"
|
||||
|
||||
namespace skyline::service::codec {
|
||||
static u32 CalculateBufferSize(i32 sampleRate, i32 channelCount) {
|
||||
static u32 CalculateBufferSize(i32 sampleRate, i32 channelCount, i32 useLargerFrameSize = 0) {
|
||||
u32 requiredSize{static_cast<u32>(opus_decoder_get_size(channelCount))};
|
||||
requiredSize += MaxInputBufferSize + CalculateOutBufferSize(sampleRate, channelCount, MaxFrameSizeNormal);
|
||||
requiredSize += MaxInputBufferSize + CalculateOutBufferSize(sampleRate, channelCount, useLargerFrameSize ? MaxFrameSizeEx : MaxFrameSizeNormal);
|
||||
return requiredSize;
|
||||
}
|
||||
|
||||
@ -32,4 +32,28 @@ namespace skyline::service::codec {
|
||||
response.Push<u32>(CalculateBufferSize(sampleRate, channelCount));
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IHardwareOpusDecoderManager::OpenHardwareOpusDecoderEx(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
i32 sampleRate{request.Pop<i32>()};
|
||||
i32 channelCount{request.Pop<i32>()};
|
||||
i32 useLargerFrameSize{request.Pop<i32>()};
|
||||
request.Pop<i32>(); // Just padding
|
||||
u32 workBufferSize{request.Pop<u32>()};
|
||||
KHandle workBuffer{request.copyHandles.at(0)};
|
||||
|
||||
Logger::Debug("Creating Opus decoder: Sample rate: {}, Channel count: {}, Work buffer handle: 0x{:X} (Size: 0x{:X})", sampleRate, channelCount, workBuffer, workBufferSize);
|
||||
|
||||
manager.RegisterService(std::make_shared<IHardwareOpusDecoder>(state, manager, sampleRate, channelCount, workBufferSize, workBuffer, useLargerFrameSize), session, response);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result IHardwareOpusDecoderManager::GetWorkBufferSizeEx(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||
i32 sampleRate{request.Pop<i32>()};
|
||||
i32 channelCount{request.Pop<i32>()};
|
||||
i32 useLargerFrameSize{request.Pop<i32>()};
|
||||
request.Pop<i32>(); // Just padding
|
||||
|
||||
response.Push<u32>(CalculateBufferSize(sampleRate, channelCount, useLargerFrameSize));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
@ -39,9 +39,23 @@ namespace skyline::service::codec {
|
||||
*/
|
||||
Result GetWorkBufferSize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Returns an IHardwareOpusDecoder object [12.0.0+]
|
||||
* @url https://switchbrew.org/wiki/Audio_services#OpenHardwareOpusDecoder
|
||||
*/
|
||||
Result OpenHardwareOpusDecoderEx(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
/**
|
||||
* @brief Returns the required size for the decoder's work buffer [12.0.0+]
|
||||
* @url https://switchbrew.org/wiki/Audio_services#GetWorkBufferSizeEx
|
||||
*/
|
||||
Result GetWorkBufferSizeEx(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||
|
||||
SERVICE_DECL(
|
||||
SFUNC(0x0, IHardwareOpusDecoderManager, OpenHardwareOpusDecoder),
|
||||
SFUNC(0x1, IHardwareOpusDecoderManager, GetWorkBufferSize),
|
||||
SFUNC(0x4, IHardwareOpusDecoderManager, OpenHardwareOpusDecoderEx),
|
||||
SFUNC(0x5, IHardwareOpusDecoderManager, GetWorkBufferSizeEx),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user