mirror of
https://github.com/moonlight-stream/moonlight-common-c.git
synced 2025-07-01 23:35:58 +00:00
Add Sunshine protocol extension for passing HDR metadata
This commit is contained in:
parent
c9a5cea93e
commit
79b5ef0e1e
@ -50,6 +50,7 @@ static bool stopping;
|
||||
static bool disconnectPending;
|
||||
static bool encryptedControlStream;
|
||||
static bool hdrEnabled;
|
||||
static SS_HDR_METADATA hdrMetadata;
|
||||
|
||||
static int intervalGoodFrameCount;
|
||||
static int intervalTotalFrameCount;
|
||||
@ -275,6 +276,7 @@ int initializeControlStream(void) {
|
||||
encryptionCtx = PltCreateCryptoContext();
|
||||
decryptionCtx = PltCreateCryptoContext();
|
||||
hdrEnabled = false;
|
||||
memset(&hdrMetadata, 0, sizeof(hdrMetadata));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -813,9 +815,24 @@ static void controlReceiveThreadFunc(void* context) {
|
||||
|
||||
BbInitializeWrappedBuffer(&bb, (char*)ctlHdr, sizeof(*ctlHdr), packetLength - sizeof(*ctlHdr), BYTE_ORDER_LITTLE);
|
||||
|
||||
// FIXME: There are 7 additional bytes that appear to always be all zeros. What do they mean?
|
||||
// Is there some way that GFE tells us the HDR mastering metadata (NV_HDR_COLOR_DATA) set by the game?
|
||||
BbGet8(&bb, &enableByte);
|
||||
if (IS_SUNSHINE()) {
|
||||
// Zero the metadata buffer to properly handle older servers if we have to add new fields
|
||||
memset(&hdrMetadata, 0, sizeof(hdrMetadata));
|
||||
|
||||
// Sunshine sends HDR metadata in this message too
|
||||
for (int i = 0; i < 3; i++) {
|
||||
BbGet16(&bb, &hdrMetadata.displayPrimaries[i].x);
|
||||
BbGet16(&bb, &hdrMetadata.displayPrimaries[i].y);
|
||||
}
|
||||
BbGet16(&bb, &hdrMetadata.whitePoint.x);
|
||||
BbGet16(&bb, &hdrMetadata.whitePoint.y);
|
||||
BbGet16(&bb, &hdrMetadata.maxDisplayLuminance);
|
||||
BbGet16(&bb, &hdrMetadata.minDisplayLuminance);
|
||||
BbGet16(&bb, &hdrMetadata.maxContentLightLevel);
|
||||
BbGet16(&bb, &hdrMetadata.maxFrameAverageLightLevel);
|
||||
BbGet16(&bb, &hdrMetadata.maxFullFrameLuminance);
|
||||
}
|
||||
|
||||
hdrEnabled = (enableByte != 0);
|
||||
ListenerCallbacks.setHdrMode(hdrEnabled);
|
||||
@ -1447,3 +1464,12 @@ int startControlStream(void) {
|
||||
bool LiGetCurrentHostDisplayHdrMode(void) {
|
||||
return hdrEnabled;
|
||||
}
|
||||
|
||||
bool LiGetHdrMetadata(PSS_HDR_METADATA metadata) {
|
||||
if (!IS_SUNSHINE() || !hdrEnabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*metadata = hdrMetadata;
|
||||
return true;
|
||||
}
|
||||
|
@ -705,6 +705,34 @@ void LiCompleteVideoFrame(VIDEO_FRAME_HANDLE handle, int drStatus);
|
||||
// See ConnListenerSetHdrMode() for more details.
|
||||
bool LiGetCurrentHostDisplayHdrMode(void);
|
||||
|
||||
typedef struct _SS_HDR_METADATA {
|
||||
// RGB order
|
||||
struct {
|
||||
uint16_t x; // Normalized to 50,000
|
||||
uint16_t y; // Normalized to 50,000
|
||||
} displayPrimaries[3];
|
||||
|
||||
struct {
|
||||
uint16_t x; // Normalized to 50,000
|
||||
uint16_t y; // Normalized to 50,000
|
||||
} whitePoint;
|
||||
|
||||
uint16_t maxDisplayLuminance; // Nits
|
||||
uint16_t minDisplayLuminance; // 1/10000th of a nit
|
||||
|
||||
// These are content-specific values which may not be available for all hosts.
|
||||
uint16_t maxContentLightLevel; // Nits
|
||||
uint16_t maxFrameAverageLightLevel; // Nits
|
||||
|
||||
// These are display-specific values which may not be available for all hosts.
|
||||
uint16_t maxFullFrameLuminance; // Nits
|
||||
} SS_HDR_METADATA, *PSS_HDR_METADATA;
|
||||
|
||||
// This function populates the provided mastering metadata struct with the HDR metadata
|
||||
// from the host PC's monitor and content (if available). It is only valid to call this
|
||||
// function when HDR mode is active on the host. This is a Sunshine protocol extension.
|
||||
bool LiGetHdrMetadata(PSS_HDR_METADATA metadata);
|
||||
|
||||
// This function requests an IDR frame from the host. Typically this is done using DR_NEED_IDR, but clients
|
||||
// processing frames asynchronously may need to reset their decoder state even after returning DR_OK for
|
||||
// the prior frame. Rather than wait for a new frame and return DR_NEED_IDR for that one, they can just
|
||||
|
Loading…
x
Reference in New Issue
Block a user