mirror of
https://github.com/skyline-emu/skyline.git
synced 2025-01-01 09:55: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);
|
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),
|
: BaseService(state, manager),
|
||||||
sampleRate(sampleRate),
|
sampleRate(sampleRate),
|
||||||
channelCount(channelCount),
|
channelCount(channelCount),
|
||||||
workBuffer(state.process->GetHandle<kernel::type::KTransferMemory>(workBufferHandle)),
|
workBuffer(state.process->GetHandle<kernel::type::KTransferMemory>(workBufferHandle)),
|
||||||
decoderOutputBufferSize(CalculateOutBufferSize(sampleRate, channelCount, MaxFrameSizeNormal)) {
|
decoderOutputBufferSize(CalculateOutBufferSize(sampleRate, channelCount, isIsLargerSize ? MaxFrameSizeEx : MaxFrameSizeNormal)) {
|
||||||
if (workBufferSize < decoderOutputBufferSize)
|
if (workBufferSize < decoderOutputBufferSize)
|
||||||
throw exception("Work Buffer doesn't have adequate space for Opus Decoder: 0x{:X} (Required: 0x{:X})", 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);
|
Result DecodeInterleavedImpl(ipc::IpcRequest &request, ipc::IpcResponse &response, bool writeDecodeTime = false);
|
||||||
|
|
||||||
public:
|
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
|
* @brief Decodes the Opus source data, returns decoded data size and decoded sample count
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
#include "IHardwareOpusDecoder.h"
|
#include "IHardwareOpusDecoder.h"
|
||||||
|
|
||||||
namespace skyline::service::codec {
|
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))};
|
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;
|
return requiredSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,4 +32,28 @@ namespace skyline::service::codec {
|
|||||||
response.Push<u32>(CalculateBufferSize(sampleRate, channelCount));
|
response.Push<u32>(CalculateBufferSize(sampleRate, channelCount));
|
||||||
return {};
|
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);
|
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(
|
SERVICE_DECL(
|
||||||
SFUNC(0x0, IHardwareOpusDecoderManager, OpenHardwareOpusDecoder),
|
SFUNC(0x0, IHardwareOpusDecoderManager, OpenHardwareOpusDecoder),
|
||||||
SFUNC(0x1, IHardwareOpusDecoderManager, GetWorkBufferSize),
|
SFUNC(0x1, IHardwareOpusDecoderManager, GetWorkBufferSize),
|
||||||
|
SFUNC(0x4, IHardwareOpusDecoderManager, OpenHardwareOpusDecoderEx),
|
||||||
|
SFUNC(0x5, IHardwareOpusDecoderManager, GetWorkBufferSizeEx),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user