mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-02 07:46:07 +00:00
Add additional codec negotiation improvements
- Fix picking incompatible YUV444 codec if software decoding was forced - Prefer AV1 over HEVC when using HDR with software decoding - Display software decoding warning when using an HDR codec without hardware decoding
This commit is contained in:
parent
e662e93a53
commit
876375f7e9
@ -693,33 +693,25 @@ bool Session::initialize()
|
|||||||
m_SupportedVideoFormats.append(VIDEO_FORMAT_H264_HIGH8_444);
|
m_SupportedVideoFormats.append(VIDEO_FORMAT_H264_HIGH8_444);
|
||||||
m_SupportedVideoFormats.append(VIDEO_FORMAT_H264);
|
m_SupportedVideoFormats.append(VIDEO_FORMAT_H264);
|
||||||
|
|
||||||
// Mask off 10-bit codecs right away if HDR is not enabled
|
|
||||||
if (!m_Preferences->enableHdr) {
|
|
||||||
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_10BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mask off YUV 4:4:4 codecs right away if the option is not enabled
|
|
||||||
if (!m_Preferences->enableYUV444) {
|
|
||||||
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_YUV444);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (m_Preferences->videoCodecConfig)
|
switch (m_Preferences->videoCodecConfig)
|
||||||
{
|
{
|
||||||
case StreamingPreferences::VCC_AUTO:
|
case StreamingPreferences::VCC_AUTO:
|
||||||
|
{
|
||||||
// Codecs are checked in order of ascending decode complexity to ensure
|
// Codecs are checked in order of ascending decode complexity to ensure
|
||||||
// the the deprioritized list prefers lighter codecs for software decoding
|
// the the deprioritized list prefers lighter codecs for software decoding
|
||||||
|
|
||||||
// H.264 is already the lowest priority codec, so we don't need to do
|
// H.264 is already the lowest priority codec, so we don't need to do
|
||||||
// any probing for deprioritization for it here.
|
// any probing for deprioritization for it here.
|
||||||
|
|
||||||
if (getDecoderAvailability(testWindow,
|
auto hevcDA = getDecoderAvailability(testWindow,
|
||||||
m_Preferences->videoDecoderSelection,
|
m_Preferences->videoDecoderSelection,
|
||||||
m_Preferences->enableYUV444 ?
|
m_Preferences->enableYUV444 ?
|
||||||
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_REXT10_444 : VIDEO_FORMAT_H265_REXT8_444) :
|
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_REXT10_444 : VIDEO_FORMAT_H265_REXT8_444) :
|
||||||
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_MAIN10 : VIDEO_FORMAT_H265),
|
(m_Preferences->enableHdr ? VIDEO_FORMAT_H265_MAIN10 : VIDEO_FORMAT_H265),
|
||||||
m_StreamConfig.width,
|
m_StreamConfig.width,
|
||||||
m_StreamConfig.height,
|
m_StreamConfig.height,
|
||||||
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
|
m_StreamConfig.fps);
|
||||||
|
if (hevcDA != DecoderAvailability::Hardware) {
|
||||||
// Deprioritize HEVC unless the user forced software decoding and enabled HDR.
|
// Deprioritize HEVC unless the user forced software decoding and enabled HDR.
|
||||||
// We need HEVC in that case because we cannot support 10-bit content with H.264,
|
// We need HEVC in that case because we cannot support 10-bit content with H.264,
|
||||||
// which would ordinarily be prioritized for software decoding performance.
|
// which would ordinarily be prioritized for software decoding performance.
|
||||||
@ -738,18 +730,18 @@ bool Session::initialize()
|
|||||||
m_StreamConfig.width,
|
m_StreamConfig.width,
|
||||||
m_StreamConfig.height,
|
m_StreamConfig.height,
|
||||||
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
|
m_StreamConfig.fps) != DecoderAvailability::Hardware) {
|
||||||
// Deprioritize AV1 unless the user forced software decoding and enabled HDR.
|
// Deprioritize AV1 unless we can't hardware decode HEVC and have HDR enabled.
|
||||||
// We want to keep AV1 at the top of the list for HDR with software decoding
|
// We want to keep AV1 at the top of the list for HDR with software decoding
|
||||||
// because dav1d is higher performance than FFmpeg's HEVC software decoder.
|
// because dav1d is higher performance than FFmpeg's HEVC software decoder.
|
||||||
if (m_Preferences->videoDecoderSelection != StreamingPreferences::VDS_FORCE_SOFTWARE || !m_Preferences->enableHdr) {
|
if (hevcDA == DecoderAvailability::Hardware || !m_Preferences->enableHdr) {
|
||||||
m_SupportedVideoFormats.deprioritizeByMask(VIDEO_FORMAT_MASK_AV1);
|
m_SupportedVideoFormats.deprioritizeByMask(VIDEO_FORMAT_MASK_AV1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Deprioritize AV1 unless the user forced software decoding and enabled HDR.
|
// Deprioritize AV1 unless we can't hardware decode HEVC and have HDR enabled.
|
||||||
// We want to keep AV1 at the top of the list for HDR with software decoding
|
// We want to keep AV1 at the top of the list for HDR with software decoding
|
||||||
// because dav1d is higher performance than FFmpeg's HEVC software decoder.
|
// because dav1d is higher performance than FFmpeg's HEVC software decoder.
|
||||||
if (m_Preferences->videoDecoderSelection != StreamingPreferences::VDS_FORCE_SOFTWARE || !m_Preferences->enableHdr) {
|
if (hevcDA == DecoderAvailability::Hardware || !m_Preferences->enableHdr) {
|
||||||
m_SupportedVideoFormats.deprioritizeByMask(VIDEO_FORMAT_MASK_AV1);
|
m_SupportedVideoFormats.deprioritizeByMask(VIDEO_FORMAT_MASK_AV1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -771,6 +763,7 @@ bool Session::initialize()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case StreamingPreferences::VCC_FORCE_H264:
|
case StreamingPreferences::VCC_FORCE_H264:
|
||||||
m_SupportedVideoFormats.removeByMask(~VIDEO_FORMAT_MASK_H264);
|
m_SupportedVideoFormats.removeByMask(~VIDEO_FORMAT_MASK_H264);
|
||||||
break;
|
break;
|
||||||
@ -785,6 +778,34 @@ bool Session::initialize()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB: Since deprioritization puts codecs in reverse order (at the bottom of the list),
|
||||||
|
// we want to deprioritize for the most critical attributes last to ensure they are the
|
||||||
|
// lowest priority codecs during server negotiation. Here we do that with YUV 4:4:4 and
|
||||||
|
// HDR to ensure we never pick a codec profile that doesn't meet the user's requirement
|
||||||
|
// if we can avoid it.
|
||||||
|
|
||||||
|
// Mask off YUV 4:4:4 codecs if the option is not enabled
|
||||||
|
if (!m_Preferences->enableYUV444) {
|
||||||
|
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_YUV444);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Deprioritize YUV 4:2:0 codecs if the user wants YUV 4:4:4
|
||||||
|
//
|
||||||
|
// NB: Since this happens first before deprioritizing HDR, we will
|
||||||
|
// pick a YUV 4:4:4 profile instead of a 10-bit profile if they
|
||||||
|
// aren't both available together for any codec.
|
||||||
|
m_SupportedVideoFormats.deprioritizeByMask(~VIDEO_FORMAT_MASK_YUV444);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mask off 10-bit codecs if HDR is not enabled
|
||||||
|
if (!m_Preferences->enableHdr) {
|
||||||
|
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_10BIT);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Deprioritize 8-bit codecs if HDR is enabled
|
||||||
|
m_SupportedVideoFormats.deprioritizeByMask(~VIDEO_FORMAT_MASK_10BIT);
|
||||||
|
}
|
||||||
|
|
||||||
switch (m_Preferences->windowMode)
|
switch (m_Preferences->windowMode)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
@ -966,28 +987,44 @@ bool Session::validateLaunch(SDL_Window* testWindow)
|
|||||||
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_10BIT);
|
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_10BIT);
|
||||||
}
|
}
|
||||||
else if (m_Preferences->videoCodecConfig != StreamingPreferences::VCC_AUTO) { // Auto was already checked during init
|
else if (m_Preferences->videoCodecConfig != StreamingPreferences::VCC_AUTO) { // Auto was already checked during init
|
||||||
|
bool displayedHdrSoftwareDecodeWarning = false;
|
||||||
|
|
||||||
// Check that the available HDR-capable codecs on the client and server are compatible
|
// 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 (m_SupportedVideoFormats.maskByServerCodecModes(m_Computer->serverCodecModeSupport & SCM_AV1_MAIN10)) {
|
||||||
if (getDecoderAvailability(testWindow,
|
auto da = getDecoderAvailability(testWindow,
|
||||||
m_Preferences->videoDecoderSelection,
|
m_Preferences->videoDecoderSelection,
|
||||||
VIDEO_FORMAT_AV1_MAIN10,
|
VIDEO_FORMAT_AV1_MAIN10,
|
||||||
m_StreamConfig.width,
|
m_StreamConfig.width,
|
||||||
m_StreamConfig.height,
|
m_StreamConfig.height,
|
||||||
m_StreamConfig.fps) == DecoderAvailability::None) {
|
m_StreamConfig.fps);
|
||||||
|
if (da == DecoderAvailability::None) {
|
||||||
emitLaunchWarning(tr("This PC's GPU doesn't support AV1 Main10 decoding for HDR streaming."));
|
emitLaunchWarning(tr("This PC's GPU doesn't support AV1 Main10 decoding for HDR streaming."));
|
||||||
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_AV1_MAIN10);
|
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_AV1_MAIN10);
|
||||||
}
|
}
|
||||||
|
else if (da == DecoderAvailability::Software &&
|
||||||
|
m_Preferences->videoDecoderSelection != StreamingPreferences::VDS_FORCE_SOFTWARE &&
|
||||||
|
!displayedHdrSoftwareDecodeWarning) {
|
||||||
|
emitLaunchWarning(tr("Using software decoding due to your selection to force HDR without GPU support. This may cause poor streaming performance."));
|
||||||
|
displayedHdrSoftwareDecodeWarning = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (m_SupportedVideoFormats.maskByServerCodecModes(m_Computer->serverCodecModeSupport & SCM_HEVC_MAIN10)) {
|
if (m_SupportedVideoFormats.maskByServerCodecModes(m_Computer->serverCodecModeSupport & SCM_HEVC_MAIN10)) {
|
||||||
if (getDecoderAvailability(testWindow,
|
auto da = getDecoderAvailability(testWindow,
|
||||||
m_Preferences->videoDecoderSelection,
|
m_Preferences->videoDecoderSelection,
|
||||||
VIDEO_FORMAT_H265_MAIN10,
|
VIDEO_FORMAT_H265_MAIN10,
|
||||||
m_StreamConfig.width,
|
m_StreamConfig.width,
|
||||||
m_StreamConfig.height,
|
m_StreamConfig.height,
|
||||||
m_StreamConfig.fps) == DecoderAvailability::None) {
|
m_StreamConfig.fps);
|
||||||
|
if (da == DecoderAvailability::None) {
|
||||||
emitLaunchWarning(tr("This PC's GPU doesn't support HEVC Main10 decoding for HDR streaming."));
|
emitLaunchWarning(tr("This PC's GPU doesn't support HEVC Main10 decoding for HDR streaming."));
|
||||||
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_H265_MAIN10);
|
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_H265_MAIN10);
|
||||||
}
|
}
|
||||||
|
else if (da == DecoderAvailability::Software &&
|
||||||
|
m_Preferences->videoDecoderSelection != StreamingPreferences::VDS_FORCE_SOFTWARE &&
|
||||||
|
!displayedHdrSoftwareDecodeWarning) {
|
||||||
|
emitLaunchWarning(tr("Using software decoding due to your selection to force HDR without GPU support. This may cause poor streaming performance."));
|
||||||
|
displayedHdrSoftwareDecodeWarning = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!(m_SupportedVideoFormats & VIDEO_FORMAT_MASK_10BIT)) {
|
else if (!(m_SupportedVideoFormats & VIDEO_FORMAT_MASK_10BIT)) {
|
||||||
@ -1007,14 +1044,14 @@ bool Session::validateLaunch(SDL_Window* testWindow)
|
|||||||
emitLaunchWarning(tr("Your host PC doesn't support YUV 4:4:4 streaming."));
|
emitLaunchWarning(tr("Your host PC doesn't support YUV 4:4:4 streaming."));
|
||||||
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_YUV444);
|
m_SupportedVideoFormats.removeByMask(VIDEO_FORMAT_MASK_YUV444);
|
||||||
}
|
}
|
||||||
else if (m_Preferences->videoDecoderSelection != StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
else {
|
||||||
m_SupportedVideoFormats.removeByMask(~m_SupportedVideoFormats.maskByServerCodecModes(m_Computer->serverCodecModeSupport));
|
m_SupportedVideoFormats.removeByMask(~m_SupportedVideoFormats.maskByServerCodecModes(m_Computer->serverCodecModeSupport));
|
||||||
|
|
||||||
if (!m_SupportedVideoFormats.isEmpty() &&
|
if (!m_SupportedVideoFormats.isEmpty() &&
|
||||||
!(m_SupportedVideoFormats.front() & VIDEO_FORMAT_MASK_YUV444)) {
|
!(m_SupportedVideoFormats.front() & VIDEO_FORMAT_MASK_YUV444)) {
|
||||||
emitLaunchWarning(tr("Your host PC doesn't support YUV 4:4:4 streaming for selected video codec."));
|
emitLaunchWarning(tr("Your host PC doesn't support YUV 4:4:4 streaming for selected video codec."));
|
||||||
}
|
}
|
||||||
else {
|
else if (m_Preferences->videoDecoderSelection != StreamingPreferences::VDS_FORCE_SOFTWARE) {
|
||||||
while (!m_SupportedVideoFormats.isEmpty() &&
|
while (!m_SupportedVideoFormats.isEmpty() &&
|
||||||
(m_SupportedVideoFormats.front() & VIDEO_FORMAT_MASK_YUV444) &&
|
(m_SupportedVideoFormats.front() & VIDEO_FORMAT_MASK_YUV444) &&
|
||||||
getDecoderAvailability(testWindow,
|
getDecoderAvailability(testWindow,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user