mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-22 21:02:39 +02:00
Added support for hwopus multistream. Minor adjustments in hwopus.h.
This commit is contained in:
parent
c99518643c
commit
6a8dba4eb4
@ -15,15 +15,28 @@ typedef struct {
|
|||||||
bool multistream;
|
bool multistream;
|
||||||
} HwopusDecoder;
|
} HwopusDecoder;
|
||||||
|
|
||||||
///< This structure is the start of opusin for \ref hwopusDecodeInterleaved, with the actual opus packet following this.
|
/// This structure is the start of opusin for \ref hwopusDecodeInterleaved, with the actual opus packet following this.
|
||||||
///< These fields are big-endian.
|
/// These fields are big-endian.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 size; ///< Size of the packet following this header.
|
u32 size; ///< Size of the packet following this header.
|
||||||
u32 unk; ///< Unknown, can be left at zero.
|
u32 unk; ///< Unknown, can be left at zero.
|
||||||
} HwopusHeader;
|
} HwopusHeader;
|
||||||
|
|
||||||
|
/// Used internally.
|
||||||
|
typedef struct {
|
||||||
|
s32 SampleRate;
|
||||||
|
s32 ChannelCount;
|
||||||
|
s32 TotalStreamCount;
|
||||||
|
s32 StereoStreamCount;
|
||||||
|
u8 channel_mapping[256];
|
||||||
|
} HwopusMultistreamState;
|
||||||
|
|
||||||
Result hwopusDecoderInitialize(HwopusDecoder* decoder, s32 SampleRate, s32 ChannelCount);
|
Result hwopusDecoderInitialize(HwopusDecoder* decoder, s32 SampleRate, s32 ChannelCount);
|
||||||
void hwopusDecoderExit(HwopusDecoder* decoder);
|
void hwopusDecoderExit(HwopusDecoder* decoder);
|
||||||
|
|
||||||
|
/// Only available on 3.0.0+.
|
||||||
|
/// See libopus multistream docs.
|
||||||
|
Result hwopusDecoderMultistreamInitialize(HwopusDecoder* decoder, s32 SampleRate, s32 ChannelCount, s32 TotalStreamCount, s32 StereoStreamCount, u8 *channel_mapping);
|
||||||
|
|
||||||
Result hwopusDecodeInterleaved(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size);
|
Result hwopusDecodeInterleaved(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size);
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <string.h>
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "result.h"
|
#include "result.h"
|
||||||
#include "arm/atomics.h"
|
#include "arm/atomics.h"
|
||||||
@ -9,6 +10,8 @@
|
|||||||
|
|
||||||
static Result _hwopusInitialize(Service* srv, Service* out_srv, TransferMemory *tmem, s32 SampleRate, s32 ChannelCount);
|
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 _hwopusGetWorkBufferSize(Service* srv, u32 *size, s32 SampleRate, s32 ChannelCount);
|
||||||
|
static Result _hwopusOpenHardwareOpusDecoderForMultiStream(Service* srv, Service* out_srv, TransferMemory *tmem, HwopusMultistreamState *state);
|
||||||
|
static Result _hwopusGetWorkBufferSizeForMultiStream(Service* srv, u32 *size, HwopusMultistreamState *state);
|
||||||
|
|
||||||
static Result _hwopusDecodeInterleavedWithPerfOld(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, u64 *perf, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size);
|
static Result _hwopusDecodeInterleavedWithPerfOld(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, u64 *perf, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size);
|
||||||
|
|
||||||
@ -40,6 +43,49 @@ Result hwopusDecoderInitialize(HwopusDecoder* decoder, s32 SampleRate, s32 Chann
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result hwopusDecoderMultistreamInitialize(HwopusDecoder* decoder, s32 SampleRate, s32 ChannelCount, s32 TotalStreamCount, s32 StereoStreamCount, u8 *channel_mapping) {
|
||||||
|
Result rc=0;
|
||||||
|
u32 size=0;
|
||||||
|
HwopusMultistreamState state;
|
||||||
|
|
||||||
|
if (serviceIsActive(&decoder->s))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!kernelAbove300())
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
|
||||||
|
if (ChannelCount < 0 || ChannelCount > sizeof(state.channel_mapping))
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
|
|
||||||
|
decoder->multistream = true;
|
||||||
|
|
||||||
|
memset(&state, 0, sizeof(HwopusMultistreamState));
|
||||||
|
state.SampleRate = SampleRate;
|
||||||
|
state.ChannelCount = ChannelCount;
|
||||||
|
state.TotalStreamCount = TotalStreamCount;
|
||||||
|
state.StereoStreamCount = StereoStreamCount;
|
||||||
|
|
||||||
|
Service hwopusMgrSrv;
|
||||||
|
rc = smGetService(&hwopusMgrSrv, "hwopus");
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
rc = _hwopusGetWorkBufferSizeForMultiStream(&hwopusMgrSrv, &size, &state);
|
||||||
|
if (R_SUCCEEDED(rc)) size = (size + 0xfff) & ~0xfff;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) rc = tmemCreate(&decoder->tmem, size, Perm_None);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
memcpy(state.channel_mapping, channel_mapping, ChannelCount);
|
||||||
|
|
||||||
|
rc = _hwopusOpenHardwareOpusDecoderForMultiStream(&hwopusMgrSrv, &decoder->s, &decoder->tmem, &state);
|
||||||
|
if (R_FAILED(rc)) tmemClose(&decoder->tmem);
|
||||||
|
}
|
||||||
|
|
||||||
|
serviceClose(&hwopusMgrSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
void hwopusDecoderExit(HwopusDecoder* decoder) {
|
void hwopusDecoderExit(HwopusDecoder* decoder) {
|
||||||
serviceClose(&decoder->s);
|
serviceClose(&decoder->s);
|
||||||
tmemClose(&decoder->tmem);
|
tmemClose(&decoder->tmem);
|
||||||
@ -124,6 +170,84 @@ static Result _hwopusGetWorkBufferSize(Service* srv, u32 *size, s32 SampleRate,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Result _hwopusOpenHardwareOpusDecoderForMultiStream(Service* srv, Service* out_srv, TransferMemory *tmem, HwopusMultistreamState *state) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
ipcSendHandleCopy(&c, tmem->handle);
|
||||||
|
ipcAddSendStatic(&c, state, sizeof(HwopusMultistreamState), 0);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u32 size;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 2;
|
||||||
|
raw->size = tmem->size;
|
||||||
|
|
||||||
|
Result rc = serviceIpcDispatch(srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
} *resp;
|
||||||
|
|
||||||
|
serviceIpcParse(srv, &r, sizeof(*resp));
|
||||||
|
resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
serviceCreateSubservice(out_srv, srv, &r, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result _hwopusGetWorkBufferSizeForMultiStream(Service* srv, u32 *size, HwopusMultistreamState *state) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
ipcAddSendStatic(&c, state, sizeof(HwopusMultistreamState), 0);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 3;
|
||||||
|
|
||||||
|
Result rc = serviceIpcDispatch(srv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u32 size;
|
||||||
|
} *resp;
|
||||||
|
|
||||||
|
serviceIpcParse(srv, &r, sizeof(*resp));
|
||||||
|
resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && size) *size = resp->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
Result hwopusDecodeInterleaved(HwopusDecoder* decoder, s32 *DecodedDataSize, s32 *DecodedSampleCount, const void* opusin, size_t opusin_size, s16 *pcmbuf, size_t pcmbuf_size) {
|
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);
|
if (kernelAbove400()) return _hwopusDecodeInterleavedWithPerfOld(decoder, DecodedDataSize, DecodedSampleCount, NULL, opusin, opusin_size, pcmbuf, pcmbuf_size);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user