Display the HDR option if the platform has a decoder that supports it

This commit is contained in:
Cameron Gutman 2022-01-29 00:59:04 -06:00
parent e0fd84d6f5
commit 1cbdd0e675
10 changed files with 77 additions and 46 deletions

View File

@ -64,16 +64,6 @@ SystemProperties::SystemProperties()
hasDiscordIntegration = false; hasDiscordIntegration = false;
#endif #endif
// TODO: Do something smarter than this. We should be able to query
// this from the decoder (or just try VIDEO_FORMAT_H265_MAIN10 and
// fail if we don't get a hardware accelerated decoder).
#ifdef Q_OS_DARWIN
// HDR is supported by the VideoToolbox renderer
supportsHdr = true;
#else
supportsHdr = false;
#endif
unmappedGamepads = SdlInputHandler::getUnmappedGamepads(); unmappedGamepads = SdlInputHandler::getUnmappedGamepads();
// Populate data that requires talking to SDL. We do it all in one shot // Populate data that requires talking to SDL. We do it all in one shot
@ -158,7 +148,7 @@ void SystemProperties::querySdlVideoInfoInternal()
} }
} }
Session::getDecoderInfo(testWindow, hasHardwareAcceleration, rendererAlwaysFullScreen, maximumResolution); Session::getDecoderInfo(testWindow, hasHardwareAcceleration, rendererAlwaysFullScreen, supportsHdr, maximumResolution);
SDL_DestroyWindow(testWindow); SDL_DestroyWindow(testWindow);

View File

@ -308,39 +308,55 @@ int Session::drSubmitDecodeUnit(PDECODE_UNIT du)
} }
void Session::getDecoderInfo(SDL_Window* window, void Session::getDecoderInfo(SDL_Window* window,
bool& isHardwareAccelerated, bool& isFullScreenOnly, QSize& maxResolution) bool& isHardwareAccelerated, bool& isFullScreenOnly,
bool& isHdrSupported, QSize& maxResolution)
{ {
IVideoDecoder* decoder; IVideoDecoder* decoder;
if (!chooseDecoder(StreamingPreferences::VDS_AUTO, // Try an HEVC Main10 decoder first to see if we have HDR support
window, VIDEO_FORMAT_H264, 1920, 1080, 60, if (chooseDecoder(StreamingPreferences::VDS_FORCE_HARDWARE,
false, false, true, decoder)) { window, VIDEO_FORMAT_H265_MAIN10, 1920, 1080, 60,
isHardwareAccelerated = isFullScreenOnly = false; false, false, true, decoder)) {
isHardwareAccelerated = decoder->isHardwareAccelerated();
isFullScreenOnly = decoder->isAlwaysFullScreen();
isHdrSupported = decoder->isHdrSupported();
maxResolution = decoder->getDecoderMaxResolution();
delete decoder;
return; return;
} }
isHardwareAccelerated = decoder->isHardwareAccelerated(); // HDR can only be supported by a hardware codec that can handle HEVC Main10.
isFullScreenOnly = decoder->isAlwaysFullScreen(); // If we made it this far, we don't have one, so HDR will not be available.
maxResolution = decoder->getDecoderMaxResolution(); isHdrSupported = false;
delete decoder; // Try a regular hardware accelerated HEVC decoder now
if (chooseDecoder(StreamingPreferences::VDS_FORCE_HARDWARE,
window, VIDEO_FORMAT_H265, 1920, 1080, 60,
false, false, true, decoder)) {
isHardwareAccelerated = decoder->isHardwareAccelerated();
isFullScreenOnly = decoder->isAlwaysFullScreen();
maxResolution = decoder->getDecoderMaxResolution();
delete decoder;
// If we don't get back a hardware H.264 decoder, see if we have a hardware return;
// HEVC decoder. This can be the case on the Raspberry Pi with Full KMS
// when not running in X11. Everything since Maxwell in 2014 can encode HEVC,
// so we probably don't need to be concerned about a lack of fast H.264
// decoding enough to bug the user about it every launch.
if (!isHardwareAccelerated) {
if (chooseDecoder(StreamingPreferences::VDS_FORCE_HARDWARE,
window, VIDEO_FORMAT_H265, 1920, 1080, 60,
false, false, true, decoder)) {
isHardwareAccelerated = decoder->isHardwareAccelerated();
isFullScreenOnly = decoder->isAlwaysFullScreen();
maxResolution = decoder->getDecoderMaxResolution();
delete decoder;
}
} }
// If we still didn't find a hardware decoder, try H.264 now.
// This will fall back to software decoding, so it should always work.
if (chooseDecoder(StreamingPreferences::VDS_AUTO,
window, VIDEO_FORMAT_H264, 1920, 1080, 60,
false, false, true, decoder)) {
isHardwareAccelerated = decoder->isHardwareAccelerated();
isFullScreenOnly = decoder->isAlwaysFullScreen();
maxResolution = decoder->getDecoderMaxResolution();
delete decoder;
return;
}
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to find ANY working H.264 or HEVC decoder!");
} }
bool Session::isHardwareDecodeAvailable(SDL_Window* window, bool Session::isHardwareDecodeAvailable(SDL_Window* window,

View File

@ -28,7 +28,8 @@ public:
static static
void getDecoderInfo(SDL_Window* window, void getDecoderInfo(SDL_Window* window,
bool& isHardwareAccelerated, bool& isFullScreenOnly, QSize& maxResolution); bool& isHardwareAccelerated, bool& isFullScreenOnly,
bool& isHdrSupported, QSize& maxResolution);
static Session* get() static Session* get()
{ {

View File

@ -64,6 +64,7 @@ public:
virtual bool initialize(PDECODER_PARAMETERS params) = 0; virtual bool initialize(PDECODER_PARAMETERS params) = 0;
virtual bool isHardwareAccelerated() = 0; virtual bool isHardwareAccelerated() = 0;
virtual bool isAlwaysFullScreen() = 0; virtual bool isAlwaysFullScreen() = 0;
virtual bool isHdrSupported() = 0;
virtual int getDecoderCapabilities() = 0; virtual int getDecoderCapabilities() = 0;
virtual int getDecoderColorspace() = 0; virtual int getDecoderColorspace() = 0;
virtual QSize getDecoderMaxResolution() = 0; virtual QSize getDecoderMaxResolution() = 0;

View File

@ -410,8 +410,15 @@ enum AVPixelFormat DrmRenderer::getPreferredPixelFormat(int)
int DrmRenderer::getRendererAttributes() int DrmRenderer::getRendererAttributes()
{ {
int attributes = 0;
// This renderer can only draw in full-screen // This renderer can only draw in full-screen
return RENDERER_ATTRIBUTE_FULLSCREEN_ONLY; attributes |= RENDERER_ATTRIBUTE_FULLSCREEN_ONLY;
// This renderer supports HDR
attributes |= RENDERER_ATTRIBUTE_HDR_SUPPORT;
return attributes;
} }
void DrmRenderer::setHdrMode(bool enabled) void DrmRenderer::setHdrMode(bool enabled)

View File

@ -90,6 +90,7 @@ private:
#define RENDERER_ATTRIBUTE_FULLSCREEN_ONLY 0x01 #define RENDERER_ATTRIBUTE_FULLSCREEN_ONLY 0x01
#define RENDERER_ATTRIBUTE_1080P_MAX 0x02 #define RENDERER_ATTRIBUTE_1080P_MAX 0x02
#define RENDERER_ATTRIBUTE_HDR_SUPPORT 0x04
class IFFmpegRenderer : public Overlay::IOverlayRenderer { class IFFmpegRenderer : public Overlay::IOverlayRenderer {
public: public:

View File

@ -505,6 +505,12 @@ public:
return COLORSPACE_REC_601; return COLORSPACE_REC_601;
} }
int getRendererAttributes() override
{
// AVSampleBufferDisplayLayer supports HDR output
return RENDERER_ATTRIBUTE_HDR_SUPPORT;
}
private: private:
AVBufferRef* m_HwContext; AVBufferRef* m_HwContext;
AVSampleBufferDisplayLayer* m_DisplayLayer; AVSampleBufferDisplayLayer* m_DisplayLayer;

View File

@ -57,6 +57,11 @@ bool FFmpegVideoDecoder::isAlwaysFullScreen()
return m_FrontendRenderer->getRendererAttributes() & RENDERER_ATTRIBUTE_FULLSCREEN_ONLY; return m_FrontendRenderer->getRendererAttributes() & RENDERER_ATTRIBUTE_FULLSCREEN_ONLY;
} }
bool FFmpegVideoDecoder::isHdrSupported()
{
return m_FrontendRenderer->getRendererAttributes() & RENDERER_ATTRIBUTE_HDR_SUPPORT;
}
void FFmpegVideoDecoder::setHdrMode(bool enabled) void FFmpegVideoDecoder::setHdrMode(bool enabled)
{ {
m_FrontendRenderer->setHdrMode(enabled); m_FrontendRenderer->setHdrMode(enabled);

View File

@ -18,6 +18,7 @@ public:
virtual bool initialize(PDECODER_PARAMETERS params) override; virtual bool initialize(PDECODER_PARAMETERS params) override;
virtual bool isHardwareAccelerated() override; virtual bool isHardwareAccelerated() override;
virtual bool isAlwaysFullScreen() override; virtual bool isAlwaysFullScreen() override;
virtual bool isHdrSupported() override;
virtual int getDecoderCapabilities() override; virtual int getDecoderCapabilities() override;
virtual int getDecoderColorspace() override; virtual int getDecoderColorspace() override;
virtual QSize getDecoderMaxResolution() override; virtual QSize getDecoderMaxResolution() override;

View File

@ -9,19 +9,22 @@ class SLVideoDecoder : public IVideoDecoder
public: public:
SLVideoDecoder(bool testOnly); SLVideoDecoder(bool testOnly);
virtual ~SLVideoDecoder(); virtual ~SLVideoDecoder();
virtual bool initialize(PDECODER_PARAMETERS params); virtual bool initialize(PDECODER_PARAMETERS params) override;
virtual bool isHardwareAccelerated(); virtual bool isHardwareAccelerated() override;
virtual bool isAlwaysFullScreen(); virtual bool isAlwaysFullScreen() override;
virtual int getDecoderCapabilities(); virtual int getDecoderCapabilities() override;
virtual int getDecoderColorspace(); virtual int getDecoderColorspace() override;
virtual QSize getDecoderMaxResolution(); virtual QSize getDecoderMaxResolution() override;
virtual int submitDecodeUnit(PDECODE_UNIT du); virtual int submitDecodeUnit(PDECODE_UNIT du) override;
// Unused since rendering is done directly from the decode thread // Unused since rendering is done directly from the decode thread
virtual void renderFrameOnMainThread() {} virtual void renderFrameOnMainThread() override {}
// HDR is not supported by SLVideo // HDR is not supported by SLVideo
virtual void setHdrMode(bool) {} virtual void setHdrMode(bool) override {}
virtual bool isHdrSupported() override {
return false;
}
private: private:
static void slLogCallback(void* context, ESLVideoLog logLevel, const char* message); static void slLogCallback(void* context, ESLVideoLog logLevel, const char* message);