diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 01f632f3..23a77b2a 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -45,7 +45,8 @@ CONNECTION_LISTENER_CALLBACKS Session::k_ConnCallbacks = { Session::clConnectionTerminated, Session::clLogMessage, Session::clRumble, - Session::clConnectionStatusUpdate + Session::clConnectionStatusUpdate, + Session::clSetHdrMode, }; Session* Session::s_ActiveSession; @@ -175,6 +176,20 @@ void Session::clConnectionStatusUpdate(int connectionStatus) } } +void Session::clSetHdrMode(bool enabled) +{ + // If we're in the process of recreating our decoder when we get + // this callback, we'll drop it. The main thread will make the + // callback when it finishes creating the new decoder. + if (SDL_AtomicTryLock(&s_ActiveSession->m_DecoderLock)) { + IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder; + if (decoder != nullptr) { + decoder->setHdrMode(enabled); + } + SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); + } +} + bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, SDL_Window* window, int videoFormat, int width, int height, int frameRate, bool enableVsync, bool enableFramePacing, bool testOnly, IVideoDecoder*& chosenDecoder) @@ -195,6 +210,10 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, params.enableFramePacing = enableFramePacing; params.vds = vds; + memset(¶ms.hdrMetadata, 0, sizeof(params.hdrMetadata)); + params.hdrMetadata.eotf = 2; // SMPTE ST 2084 + params.hdrMetadata.staticMetadataDescriptorId = 0; // Static Metadata Type 1 + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "V-sync %s", enableVsync ? "enabled" : "disabled"); @@ -607,8 +626,6 @@ void Session::emitLaunchWarning(QString text) bool Session::validateLaunch(SDL_Window* testWindow) { - QStringList warningList; - if (!m_Computer->isSupportedServerVersion) { emit displayLaunchError(tr("The version of GeForce Experience on %1 is not supported by this build of Moonlight. You must update Moonlight to stream from %1.").arg(m_Computer->name)); return false; @@ -1640,6 +1657,10 @@ void Session::execInternal() // Request an IDR frame to complete the reset SDL_AtomicSet(&m_NeedsIdr, 1); + // Set HDR mode. We may miss the callback if we're in the middle + // of recreating our decoder at the time the HDR transition happens. + m_VideoDecoder->setHdrMode(LiGetCurrentHostDisplayHdrMode()); + SDL_AtomicUnlock(&m_DecoderLock); break; diff --git a/app/streaming/session.h b/app/streaming/session.h index 86a6fb61..71d89025 100644 --- a/app/streaming/session.h +++ b/app/streaming/session.h @@ -117,6 +117,9 @@ private: static void clConnectionStatusUpdate(int connectionStatus); + static + void clSetHdrMode(bool enabled); + static int arInit(int audioConfiguration, const POPUS_MULTISTREAM_CONFIGURATION opusConfig, diff --git a/app/streaming/video/decoder.h b/app/streaming/video/decoder.h index 30b1c7e2..8cf3d022 100644 --- a/app/streaming/video/decoder.h +++ b/app/streaming/video/decoder.h @@ -28,6 +28,23 @@ typedef struct _VIDEO_STATS { uint32_t measurementStartTimestamp; } VIDEO_STATS, *PVIDEO_STATS; +typedef struct _HDR_MASTERING_METADATA { + uint8_t eotf; + uint8_t staticMetadataDescriptorId; + struct { + uint16_t x; + uint16_t y; + } displayPrimaries[3]; + struct { + uint16_t x; + uint16_t y; + } whitePoint; + uint16_t maxDisplayMasteringLuminance; + uint16_t minDisplayMasteringLuminance; + uint16_t maxContentLightLevel; + uint16_t maxFrameAverageLightLevel; +} HDR_MASTERING_METADATA, *PHDR_MASTERING_METADATA; + typedef struct _DECODER_PARAMETERS { SDL_Window* window; StreamingPreferences::VideoDecoderSelection vds; @@ -38,6 +55,7 @@ typedef struct _DECODER_PARAMETERS { int frameRate; bool enableVsync; bool enableFramePacing; + HDR_MASTERING_METADATA hdrMetadata; } DECODER_PARAMETERS, *PDECODER_PARAMETERS; class IVideoDecoder { @@ -51,4 +69,5 @@ public: virtual QSize getDecoderMaxResolution() = 0; virtual int submitDecodeUnit(PDECODE_UNIT du) = 0; virtual void renderFrameOnMainThread() = 0; + virtual void setHdrMode(bool enabled) = 0; }; diff --git a/app/streaming/video/ffmpeg-renderers/renderer.h b/app/streaming/video/ffmpeg-renderers/renderer.h index 672f2eab..23f75c7b 100644 --- a/app/streaming/video/ffmpeg-renderers/renderer.h +++ b/app/streaming/video/ffmpeg-renderers/renderer.h @@ -150,6 +150,10 @@ public: return getPreferredPixelFormat(videoFormat) == pixelFormat; } + virtual void setHdrMode(bool) { + // Nothing + } + // IOverlayRenderer virtual void notifyOverlayUpdated(Overlay::OverlayType) override { // Nothing diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index 27d8529b..43f319c5 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -57,6 +57,11 @@ bool FFmpegVideoDecoder::isAlwaysFullScreen() return m_FrontendRenderer->getRendererAttributes() & RENDERER_ATTRIBUTE_FULLSCREEN_ONLY; } +void FFmpegVideoDecoder::setHdrMode(bool enabled) +{ + m_FrontendRenderer->setHdrMode(enabled); +} + int FFmpegVideoDecoder::getDecoderCapabilities() { int capabilities = m_BackendRenderer->getDecoderCapabilities(); diff --git a/app/streaming/video/ffmpeg.h b/app/streaming/video/ffmpeg.h index 89f19d4d..06c66a02 100644 --- a/app/streaming/video/ffmpeg.h +++ b/app/streaming/video/ffmpeg.h @@ -23,6 +23,7 @@ public: virtual QSize getDecoderMaxResolution() override; virtual int submitDecodeUnit(PDECODE_UNIT du) override; virtual void renderFrameOnMainThread() override; + virtual void setHdrMode(bool enabled) override; virtual IFFmpegRenderer* getBackendRenderer(); diff --git a/app/streaming/video/slvid.h b/app/streaming/video/slvid.h index 145b985f..b8a420c3 100644 --- a/app/streaming/video/slvid.h +++ b/app/streaming/video/slvid.h @@ -20,6 +20,9 @@ public: // Unused since rendering is done directly from the decode thread virtual void renderFrameOnMainThread() {} + // HDR is not supported by SLVideo + virtual void setHdrMode(bool) {} + private: static void slLogCallback(void* context, ESLVideoLog logLevel, const char* message); diff --git a/moonlight-common-c/moonlight-common-c b/moonlight-common-c/moonlight-common-c index cfe75eb5..abc7acb5 160000 --- a/moonlight-common-c/moonlight-common-c +++ b/moonlight-common-c/moonlight-common-c @@ -1 +1 @@ -Subproject commit cfe75eb56952718cdf0855a813b3b7d46d920ae5 +Subproject commit abc7acb5e4c219ebcb51031517b01bd266005e3a