Add support for HDR streaming

This commit is contained in:
Cameron Gutman 2017-11-05 19:23:15 -08:00
parent e5d9da447c
commit a989bdde80
7 changed files with 64 additions and 8 deletions

View File

@ -15,6 +15,7 @@ public class ConnectionContext {
public int negotiatedWidth, negotiatedHeight;
public int negotiatedFps;
public boolean negotiatedHdr;
public int videoCapabilities;
}

View File

@ -99,6 +99,12 @@ public class NvConnection {
context.connListener.displayMessage("Device not paired with computer");
return false;
}
context.negotiatedHdr = context.streamConfig.getEnableHdr();
if ((h.getServerCodecModeSupport(serverInfo) & 0x200) == 0 && context.negotiatedHdr) {
context.connListener.displayTransientMessage("Your GPU does not support streaming HDR. The stream will be SDR.");
context.negotiatedHdr = false;
}
//
// Decide on negotiated stream parameters now
@ -154,7 +160,7 @@ public class NvConnection {
return false;
}
} else {
return quitAndLaunch(h, app);
return quitAndLaunch(h, context);
}
} catch (GfeHttpResponseException e) {
if (e.getErrorCode() == 470) {
@ -178,11 +184,11 @@ public class NvConnection {
return true;
}
else {
return launchNotRunningApp(h, app);
return launchNotRunningApp(h, context);
}
}
protected boolean quitAndLaunch(NvHTTP h, NvApp app) throws IOException,
protected boolean quitAndLaunch(NvHTTP h, ConnectionContext context) throws IOException,
XmlPullParserException {
try {
if (!h.quitApp()) {
@ -201,13 +207,13 @@ public class NvConnection {
}
}
return launchNotRunningApp(h, app);
return launchNotRunningApp(h, context);
}
private boolean launchNotRunningApp(NvHTTP h, NvApp app)
private boolean launchNotRunningApp(NvHTTP h, ConnectionContext context)
throws IOException, XmlPullParserException {
// Launch the app since it's not running
if (!h.launchApp(context, app.getAppId())) {
if (!h.launchApp(context, context.streamConfig.getApp().getAppId(), context.negotiatedHdr)) {
context.connListener.displayMessage("Failed to launch application");
return false;
}
@ -263,6 +269,7 @@ public class NvConnection {
context.streamConfig.getMaxPacketSize(),
context.streamConfig.getRemote(), context.streamConfig.getAudioConfiguration(),
context.streamConfig.getHevcSupported(),
context.negotiatedHdr,
context.streamConfig.getHevcBitratePercentageMultiplier(),
context.riKey.getEncoded(), ib.array(),
context.videoCapabilities);

View File

@ -26,6 +26,7 @@ public class StreamConfiguration {
private int audioConfiguration;
private boolean supportsHevc;
private int hevcBitratePercentageMultiplier;
private boolean enableHdr;
public static class Builder {
private StreamConfiguration config = new StreamConfiguration();
@ -80,6 +81,11 @@ public class StreamConfiguration {
config.hevcBitratePercentageMultiplier = multiplier;
return this;
}
public StreamConfiguration.Builder setEnableHdr(boolean enableHdr) {
config.enableHdr = enableHdr;
return this;
}
public StreamConfiguration.Builder setAudioConfiguration(int audioConfig) {
if (audioConfig == MoonBridge.AUDIO_CONFIGURATION_STEREO) {
@ -122,6 +128,7 @@ public class StreamConfiguration {
this.audioChannelCount = CHANNEL_COUNT_STEREO;
this.audioChannelMask = CHANNEL_MASK_STEREO;
this.supportsHevc = false;
this.enableHdr = false;
}
public int getWidth() {
@ -183,4 +190,8 @@ public class StreamConfiguration {
public int getHevcBitratePercentageMultiplier() {
return hevcBitratePercentageMultiplier;
}
public boolean getEnableHdr() {
return enableHdr;
}
}

View File

@ -6,6 +6,7 @@ public class NvApp {
private String appName = "";
private int appId;
private boolean initialized;
private boolean hdrSupported;
public NvApp() {}
@ -13,9 +14,10 @@ public class NvApp {
this.appName = appName;
}
public NvApp(String appName, int appId) {
public NvApp(String appName, int appId, boolean hdrSupported) {
this.appName = appName;
this.appId = appId;
this.hdrSupported = hdrSupported;
this.initialized = true;
}
@ -36,6 +38,10 @@ public class NvApp {
this.appId = appId;
this.initialized = true;
}
public void setHdrSupported(boolean hdrSupported) {
this.hdrSupported = hdrSupported;
}
public String getAppName() {
return this.appName;
@ -44,6 +50,10 @@ public class NvApp {
public int getAppId() {
return this.appId;
}
public boolean isHdrSupported() {
return this.hdrSupported;
}
public boolean isInitialized() {
return this.initialized;

View File

@ -370,6 +370,27 @@ public class NvHTTP {
return 0;
}
}
// Possible meaning of bits
// Bit 0: H.264 Baseline
// Bit 1: H.264 High
// ----
// Bit 8: HEVC Main
// Bit 9: HEVC Main10
// Bit 10: HEVC Main10 4:4:4
// Bit 11: ???
public long getServerCodecModeSupport(String serverInfo) throws XmlPullParserException, IOException {
String str = getXmlString(serverInfo, "ServerCodecModeSupport");
if (str != null) {
try {
return Long.parseLong(str);
} catch (NumberFormatException e) {
return 0;
}
} else {
return 0;
}
}
public String getGpuType(String serverInfo) throws XmlPullParserException, IOException {
return getXmlString(serverInfo, "gputype");
@ -504,6 +525,8 @@ public class NvHTTP {
app.setAppName(xpp.getText().trim());
} else if (currentTag.peek().equals("ID")) {
app.setAppId(xpp.getText().trim());
} else if (currentTag.peek().equals("IsHdrSupported")) {
app.setHdrSupported(xpp.getText().trim().equals("1"));
}
break;
}
@ -601,7 +624,7 @@ public class NvHTTP {
return new String(hexChars);
}
public boolean launchApp(ConnectionContext context, int appId) throws IOException, XmlPullParserException {
public boolean launchApp(ConnectionContext context, int appId, boolean enableHdr) throws IOException, XmlPullParserException {
String xmlStr = openHttpConnectionToString(baseUrlHttps +
"/launch?" + buildUniqueIdUuidString() +
"&appid=" + appId +
@ -609,6 +632,7 @@ public class NvHTTP {
"&additionalStates=1&sops=" + (context.streamConfig.getSops() ? 1 : 0) +
"&rikey="+bytesToHex(context.riKey.getEncoded()) +
"&rikeyid="+context.riKeyId +
(!enableHdr ? "" : "&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0") +
"&localAudioPlayMode=" + (context.streamConfig.getPlayLocalAudio() ? 1 : 0) +
"&surroundAudioInfo=" + ((context.streamConfig.getAudioChannelMask() << 16) + context.streamConfig.getAudioChannelCount()),
false);

View File

@ -160,6 +160,7 @@ public class MoonBridge {
int width, int height, int fps,
int bitrate, int packetSize, boolean streamingRemotely,
int audioConfiguration, boolean supportsHevc,
boolean enableHdr,
int hevcBitratePercentageMultiplier,
byte[] riAesKey, byte[] riAesIv,
int videoCapabilities);

View File

@ -382,6 +382,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jobject
jint width, jint height, jint fps,
jint bitrate, jint packetSize, jboolean streamingRemotely,
jint audioConfiguration, jboolean supportsHevc,
jboolean enableHdr,
jint hevcBitratePercentageMultiplier,
jbyteArray riAesKey, jbyteArray riAesIv,
jint videoCapabilities) {
@ -399,6 +400,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jobject
.streamingRemotely = streamingRemotely,
.audioConfiguration = audioConfiguration,
.supportsHevc = supportsHevc,
.enableHdr = enableHdr,
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
};