Add HDR support with software decoding using libplacebo

Not supported on macOS yet.
This commit is contained in:
Cameron Gutman 2024-08-20 01:28:00 -05:00
parent 416003248b
commit 7c6954b5f6
3 changed files with 81 additions and 96 deletions

View File

@ -1498,7 +1498,6 @@ Flickable {
id: decoderComboBox
textRole: "text"
enabled: !enableHdr.checked
model: ListModel {
id: decoderListModel
ListElement {
@ -1520,21 +1519,6 @@ Flickable {
StreamingPreferences.videoDecoderSelection = decoderListModel.get(currentIndex).val
}
}
// This handles the state of the enableHdr checkbox changing
onEnabledChanged: {
if (enabled) {
StreamingPreferences.videoDecoderSelection = decoderListModel.get(currentIndex).val
}
else {
StreamingPreferences.videoDecoderSelection = StreamingPreferences.VDS_AUTO
}
}
ToolTip.delay: 1000
ToolTip.timeout: 5000
ToolTip.visible: hovered && !enabled
ToolTip.text: qsTr("Enabling HDR overrides manual decoder selections.")
}
Label {

View File

@ -450,21 +450,22 @@ void Session::getDecoderInfo(SDL_Window* window,
"Failed to find ANY working H.264 or HEVC decoder!");
}
bool Session::isHardwareDecodeAvailable(SDL_Window* window,
StreamingPreferences::VideoDecoderSelection vds,
int videoFormat, int width, int height, int frameRate)
Session::DecoderAvailability
Session::getDecoderAvailability(SDL_Window* window,
StreamingPreferences::VideoDecoderSelection vds,
int videoFormat, int width, int height, int frameRate)
{
IVideoDecoder* decoder;
if (!chooseDecoder(vds, window, videoFormat, width, height, frameRate, false, false, true, decoder)) {
return false;
return DecoderAvailability::None;
}
bool ret = decoder->isHardwareAccelerated();
bool hw = decoder->isHardwareAccelerated();
delete decoder;
return ret;
return hw ? DecoderAvailability::Hardware : DecoderAvailability::Software;
}
bool Session::populateDecoderProperties(SDL_Window* window)
@ -711,27 +712,27 @@ bool Session::initialize()
// H.264 is already the lowest priority codec, so we don't need to do
// any probing for deprioritization for it here.
if (!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
m_Preferences->enableYUV444 ?
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_REXT10_444 : VIDEO_FORMAT_H265_REXT8_444) :
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_MAIN10 : VIDEO_FORMAT_H265),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
if (getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
m_Preferences->enableYUV444 ?
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_REXT10_444 : VIDEO_FORMAT_H265_REXT8_444) :
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_MAIN10 : VIDEO_FORMAT_H265),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
m_SupportedVideoFormats.deprioritizeByMask(VIDEO_FORMAT_MASK_H265);
}
#if 0
// TODO: Determine if AV1 is better depending on the decoder
if (!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
m_Preferences->enableYUV444 ?
(m_Preferences->enableHdr ? VIDEO_FORMAT_AV1_HIGH10_444 : VIDEO_FORMAT_AV1_HIGH8_444) :
(m_Preferences->enableHdr ? VIDEO_FORMAT_AV1_MAIN10 : VIDEO_FORMAT_AV1_MAIN8),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
if (getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
m_Preferences->enableYUV444 ?
(m_Preferences->enableHdr ? VIDEO_FORMAT_AV1_HIGH10_444 : VIDEO_FORMAT_AV1_HIGH8_444) :
(m_Preferences->enableHdr ? VIDEO_FORMAT_AV1_MAIN10 : VIDEO_FORMAT_AV1_MAIN8),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
m_SupportedVideoFormats.deprioritizeByMask(VIDEO_FORMAT_MASK_AV1 & VIDEO_FORMAT_MASK_YUV444);
}
#else
@ -861,13 +862,7 @@ bool Session::validateLaunch(SDL_Window* testWindow)
}
if (m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_FORCE_SOFTWARE) {
if (m_Preferences->enableHdr) {
emitLaunchWarning(tr("HDR is not supported with software decoding."));
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_10BIT);
}
else {
emitLaunchWarning(tr("Your settings selection to force software decoding may cause poor streaming performance."));
}
emitLaunchWarning(tr("Your settings selection to force software decoding may cause poor streaming performance."));
}
if (m_SupportedVideoFormats & VIDEO_FORMAT_MASK_AV1) {
@ -884,12 +879,12 @@ bool Session::validateLaunch(SDL_Window* testWindow)
else if (!m_Preferences->enableHdr && // HDR is checked below
m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_AUTO && // Force hardware decoding checked below
m_Preferences->videoCodecConfig != StreamingPreferences::VCC_AUTO && // Auto VCC is already checked in initialize()
!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_AV1_MAIN8,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_AV1_MAIN8,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
emitLaunchWarning(tr("Using software decoding due to your selection to force AV1 without GPU support. This may cause poor streaming performance."));
}
}
@ -908,36 +903,36 @@ bool Session::validateLaunch(SDL_Window* testWindow)
else if (!m_Preferences->enableHdr && // HDR is checked below
m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_AUTO && // Force hardware decoding checked below
m_Preferences->videoCodecConfig != StreamingPreferences::VCC_AUTO && // Auto VCC is already checked in initialize()
!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H265,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H265,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
emitLaunchWarning(tr("Using software decoding due to your selection to force HEVC without GPU support. This may cause poor streaming performance."));
}
}
if (!(m_SupportedVideoFormats & VIDEO_FORMAT_MASK_H265) &&
m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_AUTO &&
!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H264,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H264,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
if (m_Preferences->videoCodecConfig == StreamingPreferences::VCC_FORCE_H264) {
emitLaunchWarning(tr("Using software decoding due to your selection to force H.264 without GPU support. This may cause poor streaming performance."));
}
else {
if (m_Computer->maxLumaPixelsHEVC == 0 &&
isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H265,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H265,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) == DecoderAvailability::Hardware) {
emitLaunchWarning(tr("Your host PC and client PC don't support the same video codecs. This may cause poor streaming performance."));
}
else {
@ -959,23 +954,23 @@ bool Session::validateLaunch(SDL_Window* testWindow)
else if (m_Preferences->videoCodecConfig != StreamingPreferences::VCC_AUTO) { // Auto was already checked during init
// Check that the available HDR-capable codecs on the client and server are compatible
if (m_SupportedVideoFormats.maskByServerCodecModes(m_Computer->serverCodecModeSupport & SCM_AV1_MAIN10)) {
if (!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_AV1_MAIN10,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
if (getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_AV1_MAIN10,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) == DecoderAvailability::None) {
emitLaunchWarning(tr("This PC's GPU doesn't support AV1 Main10 decoding for HDR streaming."));
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_AV1_MAIN10);
}
}
if (m_SupportedVideoFormats.maskByServerCodecModes(m_Computer->serverCodecModeSupport & SCM_HEVC_MAIN10)) {
if (!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H265_MAIN10,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
if (getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
VIDEO_FORMAT_H265_MAIN10,
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) == DecoderAvailability::None) {
emitLaunchWarning(tr("This PC's GPU doesn't support HEVC Main10 decoding for HDR streaming."));
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_H265_MAIN10);
}
@ -1008,12 +1003,12 @@ bool Session::validateLaunch(SDL_Window* testWindow)
else {
while (!m_SupportedVideoFormats.isEmpty() &&
(m_SupportedVideoFormats.front() & VIDEO_FORMAT_MASK_YUV444) &&
!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
m_SupportedVideoFormats.front(),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
m_SupportedVideoFormats.front(),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
if (m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_FORCE_HARDWARE) {
m_SupportedVideoFormats.removeFirst();
}
@ -1088,12 +1083,12 @@ bool Session::validateLaunch(SDL_Window* testWindow)
if (m_Preferences->videoDecoderSelection == StreamingPreferences::VDS_FORCE_HARDWARE &&
!(m_SupportedVideoFormats & VIDEO_FORMAT_MASK_10BIT) && // HDR was already checked for hardware decode support above
!isHardwareDecodeAvailable(testWindow,
m_Preferences->videoDecoderSelection,
m_SupportedVideoFormats.front(),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps)) {
getDecoderAvailability(testWindow,
m_Preferences->videoDecoderSelection,
m_SupportedVideoFormats.front(),
m_StreamConfig.width,
m_StreamConfig.height,
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
if (m_Preferences->videoCodecConfig == StreamingPreferences::VCC_AUTO) {
emit displayLaunchError(tr("Your selection to force hardware decoding cannot be satisfied due to missing hardware decoding support on this PC's GPU."));
}

View File

@ -172,10 +172,16 @@ private:
void updateOptimalWindowDisplayMode();
enum class DecoderAvailability {
None,
Software,
Hardware
};
static
bool isHardwareDecodeAvailable(SDL_Window* window,
StreamingPreferences::VideoDecoderSelection vds,
int videoFormat, int width, int height, int frameRate);
DecoderAvailability getDecoderAvailability(SDL_Window* window,
StreamingPreferences::VideoDecoderSelection vds,
int videoFormat, int width, int height, int frameRate);
static
bool chooseDecoder(StreamingPreferences::VideoDecoderSelection vds,