diff --git a/moonlight-common/src/com/limelight/nvstream/ConnectionContext.java b/moonlight-common/src/com/limelight/nvstream/ConnectionContext.java index 9ae6ad41..ac5a939a 100644 --- a/moonlight-common/src/com/limelight/nvstream/ConnectionContext.java +++ b/moonlight-common/src/com/limelight/nvstream/ConnectionContext.java @@ -5,6 +5,7 @@ import java.net.InetAddress; import javax.crypto.SecretKey; import com.limelight.nvstream.av.video.VideoDecoderRenderer; +import com.limelight.nvstream.av.video.VideoDecoderRenderer.VideoFormat; public class ConnectionContext { // Gen 3 servers are 2.1.1 - 2.2.1 @@ -21,4 +22,6 @@ public class ConnectionContext { public int riKeyId; public int serverGeneration; + + public VideoFormat negotiatedVideoFormat; } diff --git a/moonlight-common/src/com/limelight/nvstream/StreamConfiguration.java b/moonlight-common/src/com/limelight/nvstream/StreamConfiguration.java index 3ff36de1..f7fe4579 100644 --- a/moonlight-common/src/com/limelight/nvstream/StreamConfiguration.java +++ b/moonlight-common/src/com/limelight/nvstream/StreamConfiguration.java @@ -25,6 +25,7 @@ public class StreamConfiguration { private boolean remote; private int audioChannelMask; private int audioChannelCount; + private boolean supportsHevc; public static class Builder { private StreamConfiguration config = new StreamConfiguration(); @@ -91,6 +92,11 @@ public class StreamConfiguration { return this; } + public StreamConfiguration.Builder setHevcSupported(boolean supportsHevc) { + config.supportsHevc = supportsHevc; + return this; + } + public StreamConfiguration build() { return config; } @@ -108,6 +114,7 @@ public class StreamConfiguration { this.enableAdaptiveResolution = false; this.audioChannelCount = CHANNEL_COUNT_STEREO; this.audioChannelMask = CHANNEL_MASK_STEREO; + this.supportsHevc = false; } public int getWidth() { @@ -157,4 +164,8 @@ public class StreamConfiguration { public int getAudioChannelMask() { return audioChannelMask; } + + public boolean getHevcSupported() { + return supportsHevc; + } } diff --git a/moonlight-common/src/com/limelight/nvstream/av/video/VideoDecoderRenderer.java b/moonlight-common/src/com/limelight/nvstream/av/video/VideoDecoderRenderer.java index 54c33087..8fe73f22 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/video/VideoDecoderRenderer.java +++ b/moonlight-common/src/com/limelight/nvstream/av/video/VideoDecoderRenderer.java @@ -3,6 +3,11 @@ package com.limelight.nvstream.av.video; import com.limelight.nvstream.av.DecodeUnit; public abstract class VideoDecoderRenderer { + public enum VideoFormat { + H264, + H265 + }; + public static final int FLAG_PREFER_QUALITY = 0x1; public static final int FLAG_FORCE_HARDWARE_DECODING = 0x2; public static final int FLAG_FORCE_SOFTWARE_DECODING = 0x4; @@ -34,7 +39,7 @@ public abstract class VideoDecoderRenderer { throw new UnsupportedOperationException("CAPABILITY_DIRECT_SUBMIT requires overriding directSubmitDecodeUnit()"); } - public abstract boolean setup(int width, int height, int redrawRate, Object renderTarget, int drFlags); + public abstract boolean setup(VideoFormat format, int width, int height, int redrawRate, Object renderTarget, int drFlags); public abstract boolean start(VideoDepacketizer depacketizer); diff --git a/moonlight-common/src/com/limelight/nvstream/av/video/VideoStream.java b/moonlight-common/src/com/limelight/nvstream/av/video/VideoStream.java index 6a80e2c8..9d1d1743 100644 --- a/moonlight-common/src/com/limelight/nvstream/av/video/VideoStream.java +++ b/moonlight-common/src/com/limelight/nvstream/av/video/VideoStream.java @@ -122,8 +122,9 @@ public class VideoStream { if (decRend != null) { try { - if (!decRend.setup(context.streamConfig.getWidth(), context.streamConfig.getHeight(), - context.streamConfig.getRefreshRate(), renderTarget, drFlags)) { + if (!decRend.setup(context.negotiatedVideoFormat, context.streamConfig.getWidth(), + context.streamConfig.getHeight(), context.streamConfig.getRefreshRate(), + renderTarget, drFlags)) { return false; } diff --git a/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java b/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java index d6ef75bd..373b65cb 100644 --- a/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java +++ b/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java @@ -5,6 +5,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import com.limelight.nvstream.ConnectionContext; +import com.limelight.nvstream.av.video.VideoDecoderRenderer.VideoFormat; public class SdpGenerator { private static void addSessionAttribute(StringBuilder config, String attribute, String value) { @@ -53,6 +54,17 @@ public class SdpGenerator { private static void addGen4Attributes(StringBuilder config, ConnectionContext context) { addSessionAttribute(config, "x-nv-general.serverAddress", "rtsp://"+context.serverAddress.getHostAddress()+":48010"); + // If client and server are able, request HEVC + if (context.negotiatedVideoFormat == VideoFormat.H265) { + addSessionAttribute(config, "x-nv-clientSupportHevc", "1"); + addSessionAttribute(config, "x-nv-vqos[0].bitStreamFormat", "1"); + } + else { + // Otherwise, use AVC + addSessionAttribute(config, "x-nv-clientSupportHevc", "0"); + addSessionAttribute(config, "x-nv-vqos[0].bitStreamFormat", "0"); + } + addSessionAttribute(config, "x-nv-video[0].rateControlMode", "4"); // Use slicing for increased performance on some decoders