diff --git a/nx/include/switch/services/hwopus.h b/nx/include/switch/services/hwopus.h index 1d6c54c3..4e6abfa3 100644 --- a/nx/include/switch/services/hwopus.h +++ b/nx/include/switch/services/hwopus.h @@ -12,6 +12,7 @@ typedef struct { Service s; TransferMemory tmem; + bool multistream; } HwopusDecoder; ///< This structure is the start of opusin for \ref hwopusDecodeInterleaved, with the actual opus packet following this. diff --git a/nx/source/services/hwopus.c b/nx/source/services/hwopus.c index 1b55ad94..88cb9098 100644 --- a/nx/source/services/hwopus.c +++ b/nx/source/services/hwopus.c @@ -10,6 +10,8 @@ static Result _hwopusInitialize(Service* srv, Service* out_srv, TransferMemory *tmem, s32 SampleRate, s32 ChannelCount); static Result _hwopusGetWorkBufferSize(Service* srv, u32 *size, s32 SampleRate, s32 ChannelCount); +static Result _hwopusDecodeInterleavedWithPerfOld(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, u64 *perf, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size); + Result hwopusDecoderInitialize(HwopusDecoder* decoder, s32 SampleRate, s32 ChannelCount) { Result rc=0; u32 size=0; @@ -17,6 +19,8 @@ Result hwopusDecoderInitialize(HwopusDecoder* decoder, s32 SampleRate, s32 Chann if (serviceIsActive(&decoder->s)) return 0; + decoder->multistream = false; + Service hwopusMgrSrv; rc = smGetService(&hwopusMgrSrv, "hwopus"); if (R_SUCCEEDED(rc)) { @@ -121,6 +125,8 @@ static Result _hwopusGetWorkBufferSize(Service* srv, u32 *size, s32 SampleRate, } Result hwopusDecodeInterleaved(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size) { + if (kernelAbove400()) return _hwopusDecodeInterleavedWithPerfOld(decoder, DecodedDataSize, DecodedSampleCount, NULL, opusin, opusin_size, pcmbuf, pcmbuf_size); + IpcCommand c; ipcInitialize(&c); @@ -135,7 +141,7 @@ Result hwopusDecodeInterleaved(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 raw = serviceIpcPrepareHeader(&decoder->s, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; + raw->cmd_id = decoder->multistream==0 ? 0 : 2; Result rc = serviceIpcDispatch(&decoder->s); @@ -159,3 +165,45 @@ Result hwopusDecodeInterleaved(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 return rc; } + +static Result _hwopusDecodeInterleavedWithPerfOld(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, u64 *perf, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size) { + IpcCommand c; + ipcInitialize(&c); + + ipcAddSendBuffer(&c, opusin, opusin_size, BufferType_Normal); + ipcAddRecvBuffer(&c, pcmbuf, pcmbuf_size, BufferType_Type1); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&decoder->s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = decoder->multistream==0 ? 4 : 5; + + Result rc = serviceIpcDispatch(&decoder->s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + s32 DecodedDataSize; + s32 DecodedSampleCount; + u64 perf; + } *resp; + + serviceIpcParse(&decoder->s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && DecodedSampleCount) *DecodedSampleCount = resp->DecodedSampleCount; + if (R_SUCCEEDED(rc) && DecodedDataSize) *DecodedDataSize = resp->DecodedDataSize; + if (R_SUCCEEDED(rc) && perf) *perf = resp->perf; + } + + return rc; +}