From 466463ebc30dc8c2b8ced0a16a1b6c6fa0f1b69d Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 25 Jan 2015 18:12:25 -0500 Subject: [PATCH] Add SDP backwards compatibility --- .../limelight/nvstream/rtsp/SdpGenerator.java | 78 ++++++++++++++++--- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java b/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java index c65cbdcc..63c3f0b1 100644 --- a/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java +++ b/moonlight-common/src/com/limelight/nvstream/rtsp/SdpGenerator.java @@ -1,6 +1,8 @@ package com.limelight.nvstream.rtsp; import java.net.Inet6Address; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import com.limelight.nvstream.ConnectionContext; @@ -9,6 +11,53 @@ public class SdpGenerator { config.append("a="+attribute+":"+value+" \r\n"); } + private static void addSessionAttributeBytes(StringBuilder config, String attribute, byte[] value) { + char str[] = new char[value.length]; + + for (int i = 0; i < value.length; i++) { + str[i] = (char)value[i]; + } + + addSessionAttribute(config, attribute, new String(str)); + } + + private static void addSessionAttributeInt(StringBuilder config, String attribute, int value) { + ByteBuffer b = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); + b.putInt(value); + addSessionAttributeBytes(config, attribute, b.array()); + } + + private static void addGen3Attributes(StringBuilder config, ConnectionContext context) { + addSessionAttribute(config, "x-nv-general.serverAddress", context.serverAddress.getHostAddress()); + + addSessionAttributeInt(config, "x-nv-general.featureFlags", 0x42774141); + + addSessionAttributeInt(config, "x-nv-video[0].transferProtocol", 0x41514141); + addSessionAttributeInt(config, "x-nv-video[1].transferProtocol", 0x41514141); + addSessionAttributeInt(config, "x-nv-video[2].transferProtocol", 0x41514141); + addSessionAttributeInt(config, "x-nv-video[3].transferProtocol", 0x41514141); + + addSessionAttributeInt(config, "x-nv-video[0].rateControlMode", 0x42414141); + addSessionAttributeInt(config, "x-nv-video[1].rateControlMode", 0x42514141); + addSessionAttributeInt(config, "x-nv-video[2].rateControlMode", 0x42514141); + addSessionAttributeInt(config, "x-nv-video[3].rateControlMode", 0x42514141); + + addSessionAttribute(config, "x-nv-vqos[0].bw.flags", "14083"); + + addSessionAttribute(config, "x-nv-vqos[0].videoQosMaxConsecutiveDrops", "0"); + addSessionAttribute(config, "x-nv-vqos[1].videoQosMaxConsecutiveDrops", "0"); + addSessionAttribute(config, "x-nv-vqos[2].videoQosMaxConsecutiveDrops", "0"); + addSessionAttribute(config, "x-nv-vqos[3].videoQosMaxConsecutiveDrops", "0"); + } + + private static void addGen4Attributes(StringBuilder config, ConnectionContext context) { + addSessionAttribute(config, "x-nv-general.serverAddress", "rtsp://"+context.serverAddress.getHostAddress()+":48010"); + + addSessionAttribute(config, "x-nv-video[0].rateControlMode", "4"); + + addSessionAttribute(config, "x-nv-vqos[0].bw.flags", "51"); + } + public static String generateSdpFromContext(ConnectionContext context) { StringBuilder config = new StringBuilder(); config.append("v=0").append("\r\n"); // SDP Version 0 @@ -22,16 +71,12 @@ public class SdpGenerator { config.append(context.serverAddress.getHostAddress()); config.append("\r\n"); config.append("s=NVIDIA Streaming Client").append("\r\n"); - - addSessionAttribute(config, "x-nv-general.serverAddress", "rtsp://"+context.serverAddress.getHostAddress()+":48010"); - + addSessionAttribute(config, "x-nv-video[0].clientViewportWd", ""+context.streamConfig.getWidth()); addSessionAttribute(config, "x-nv-video[0].clientViewportHt", ""+context.streamConfig.getHeight()); addSessionAttribute(config, "x-nv-video[0].maxFPS", ""+context.streamConfig.getRefreshRate()); addSessionAttribute(config, "x-nv-video[0].packetSize", ""+context.streamConfig.getMaxPacketSize()); - - addSessionAttribute(config, "x-nv-video[0].rateControlMode", "4"); if (context.streamConfig.getRemote()) { addSessionAttribute(config, "x-nv-video[0].averageBitrate", "4"); @@ -44,9 +89,7 @@ public class SdpGenerator { addSessionAttribute(config, "x-nv-video[0].timeoutLengthMs", "7000"); addSessionAttribute(config, "x-nv-video[0].framesWithInvalidRefThreshold", "0"); - - addSessionAttribute(config, "x-nv-vqos[0].bw.flags", "51"); - + // Lock the bitrate if we're not scaling resolution so the picture doesn't get too bad if (context.streamConfig.getHeight() >= 1080 && context.streamConfig.getRefreshRate() >= 60) { if (context.streamConfig.getBitrate() < 10000) { @@ -96,10 +139,27 @@ public class SdpGenerator { else { addSessionAttribute(config, "x-nv-aqos.qosTrafficType", "4"); } + + // Add generation-specific attributes + switch (context.serverGeneration) { + case ConnectionContext.SERVER_GENERATION_3: + addGen3Attributes(config, context); + break; + + case ConnectionContext.SERVER_GENERATION_4: + default: + addGen4Attributes(config, context); + break; + } config.append("t=0 0").append("\r\n"); - config.append("m=video 47998 ").append("\r\n"); + if (context.serverGeneration == ConnectionContext.SERVER_GENERATION_3) { + config.append("m=video 47996 ").append("\r\n"); + } + else { + config.append("m=video 47998 ").append("\r\n"); + } return config.toString(); }