mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
Added support for grcd.
This commit is contained in:
parent
c8b9120ba4
commit
5e535bc2eb
@ -23,6 +23,14 @@ typedef struct {
|
|||||||
u8 reserved[0x28]; ///< Unused, always zero.
|
u8 reserved[0x28]; ///< Unused, always zero.
|
||||||
} GrcGameMovieId;
|
} GrcGameMovieId;
|
||||||
|
|
||||||
|
/// Stream type values for \ref grcdRead.
|
||||||
|
typedef enum {
|
||||||
|
GrcStream_Video = 0, ///< Video stream with H.264 NAL units. Official sw uses buffer size 0x32000.
|
||||||
|
GrcStream_Audio = 1, ///< Audio stream with PcmFormat_Int16, 2 channels, and samplerate = 48000Hz. Official sw uses buffer size 0x1000.
|
||||||
|
} GrcStream;
|
||||||
|
|
||||||
|
// Trimming
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a \ref GrcGameMovieTrimmer using \ref appletCreateGameMovieTrimmer, uses the cmds from it to trim the specified video, then closes it.
|
* @brief Creates a \ref GrcGameMovieTrimmer using \ref appletCreateGameMovieTrimmer, uses the cmds from it to trim the specified video, then closes it.
|
||||||
* @note See \ref appletCreateGameMovieTrimmer for the requirements for using this.
|
* @note See \ref appletCreateGameMovieTrimmer for the requirements for using this.
|
||||||
@ -36,3 +44,29 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
Result grcTrimGameMovie(GrcGameMovieId *dst_movieid, const GrcGameMovieId *src_movieid, size_t tmem_size, const void* thumbnail, s32 start, s32 end);
|
Result grcTrimGameMovie(GrcGameMovieId *dst_movieid, const GrcGameMovieId *src_movieid, size_t tmem_size, const void* thumbnail, s32 start, s32 end);
|
||||||
|
|
||||||
|
// grc:d
|
||||||
|
|
||||||
|
/// Initialize grc:d.
|
||||||
|
Result grcdInitialize(void);
|
||||||
|
|
||||||
|
/// Exit grc:d.
|
||||||
|
void grcdExit(void);
|
||||||
|
|
||||||
|
/// Gets the Service for grc:d.
|
||||||
|
Service* grcdGetServiceSession(void);
|
||||||
|
|
||||||
|
/// Begins streaming. This must not be called more than once, even from a different service session: otherwise the sysmodule will assert.
|
||||||
|
Result grcdBegin(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a stream, from the video recording being done of the currently running game title.
|
||||||
|
* @note This will block until data is available. This will hang if there is no game title running which has video capture enabled.
|
||||||
|
* @param[in] stream \ref GrcStream
|
||||||
|
* @param[out] buffer Output buffer.
|
||||||
|
* @param[in] size Max size of the output buffer.
|
||||||
|
* @param[out] unk Unknown.
|
||||||
|
* @param[out] data_size Actual output data size.
|
||||||
|
* @param[out] timestamp Timestamp?
|
||||||
|
*/
|
||||||
|
Result grcdRead(GrcStream stream, void* buffer, size_t size, u32 *unk, u32 *data_size, u64 *timestamp);
|
||||||
|
|
||||||
|
@ -12,6 +12,38 @@
|
|||||||
|
|
||||||
static void _grcGameMovieTrimmerClose(GrcGameMovieTrimmer *t);
|
static void _grcGameMovieTrimmerClose(GrcGameMovieTrimmer *t);
|
||||||
|
|
||||||
|
static Result _grcCmdNoIO(Service* srv, u64 cmd_id) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = cmd_id;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static Result _grcGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool autoclear) {
|
static Result _grcGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool autoclear) {
|
||||||
IpcCommand c;
|
IpcCommand c;
|
||||||
ipcInitialize(&c);
|
ipcInitialize(&c);
|
||||||
@ -228,3 +260,79 @@ Result grcTrimGameMovie(GrcGameMovieId *dst_movieid, const GrcGameMovieId *src_m
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// grc:d
|
||||||
|
|
||||||
|
static Service g_grcdSrv;
|
||||||
|
static u64 g_grcdRefCnt;
|
||||||
|
|
||||||
|
Result grcdInitialize(void) {
|
||||||
|
atomicIncrement64(&g_grcdRefCnt);
|
||||||
|
|
||||||
|
if (serviceIsActive(&g_grcdSrv))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Result rc = smGetService(&g_grcdSrv, "grc:d");
|
||||||
|
|
||||||
|
if (R_FAILED(rc)) grcdExit();
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void grcdExit(void) {
|
||||||
|
if (atomicDecrement64(&g_grcdRefCnt) == 0)
|
||||||
|
serviceClose(&g_grcdSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* grcdGetServiceSession(void) {
|
||||||
|
return &g_grcdSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result grcdBegin(void) {
|
||||||
|
return _grcCmdNoIO(&g_grcdSrv, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result grcdRead(GrcStream stream, void* buffer, size_t size, u32 *unk, u32 *data_size, u64 *timestamp) {
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
|
||||||
|
ipcAddRecvBuffer(&c, buffer, size, BufferType_Normal);
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u32 stream;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = serviceIpcPrepareHeader(&g_grcdSrv, &c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 2;
|
||||||
|
raw->stream = stream;
|
||||||
|
|
||||||
|
Result rc = serviceIpcDispatch(&g_grcdSrv);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
struct {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u32 unk;
|
||||||
|
u32 data_size;
|
||||||
|
u64 timestamp;
|
||||||
|
} *resp;
|
||||||
|
|
||||||
|
serviceIpcParse(&g_grcdSrv, &r, sizeof(*resp));
|
||||||
|
resp = r.Raw;
|
||||||
|
|
||||||
|
rc = resp->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
if (unk) *unk = resp->unk;
|
||||||
|
if (data_size) *data_size = resp->data_size;
|
||||||
|
if (timestamp) *timestamp = resp->timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user