mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-19 19:13:03 +00:00
Add support for HDR streaming
This commit is contained in:
parent
e5d9da447c
commit
a989bdde80
@ -15,6 +15,7 @@ public class ConnectionContext {
|
|||||||
|
|
||||||
public int negotiatedWidth, negotiatedHeight;
|
public int negotiatedWidth, negotiatedHeight;
|
||||||
public int negotiatedFps;
|
public int negotiatedFps;
|
||||||
|
public boolean negotiatedHdr;
|
||||||
|
|
||||||
public int videoCapabilities;
|
public int videoCapabilities;
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,12 @@ public class NvConnection {
|
|||||||
return false;
|
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
|
// Decide on negotiated stream parameters now
|
||||||
//
|
//
|
||||||
@ -154,7 +160,7 @@ public class NvConnection {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return quitAndLaunch(h, app);
|
return quitAndLaunch(h, context);
|
||||||
}
|
}
|
||||||
} catch (GfeHttpResponseException e) {
|
} catch (GfeHttpResponseException e) {
|
||||||
if (e.getErrorCode() == 470) {
|
if (e.getErrorCode() == 470) {
|
||||||
@ -178,11 +184,11 @@ public class NvConnection {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
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 {
|
XmlPullParserException {
|
||||||
try {
|
try {
|
||||||
if (!h.quitApp()) {
|
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 {
|
throws IOException, XmlPullParserException {
|
||||||
// Launch the app since it's not running
|
// 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");
|
context.connListener.displayMessage("Failed to launch application");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -263,6 +269,7 @@ public class NvConnection {
|
|||||||
context.streamConfig.getMaxPacketSize(),
|
context.streamConfig.getMaxPacketSize(),
|
||||||
context.streamConfig.getRemote(), context.streamConfig.getAudioConfiguration(),
|
context.streamConfig.getRemote(), context.streamConfig.getAudioConfiguration(),
|
||||||
context.streamConfig.getHevcSupported(),
|
context.streamConfig.getHevcSupported(),
|
||||||
|
context.negotiatedHdr,
|
||||||
context.streamConfig.getHevcBitratePercentageMultiplier(),
|
context.streamConfig.getHevcBitratePercentageMultiplier(),
|
||||||
context.riKey.getEncoded(), ib.array(),
|
context.riKey.getEncoded(), ib.array(),
|
||||||
context.videoCapabilities);
|
context.videoCapabilities);
|
||||||
|
@ -26,6 +26,7 @@ public class StreamConfiguration {
|
|||||||
private int audioConfiguration;
|
private int audioConfiguration;
|
||||||
private boolean supportsHevc;
|
private boolean supportsHevc;
|
||||||
private int hevcBitratePercentageMultiplier;
|
private int hevcBitratePercentageMultiplier;
|
||||||
|
private boolean enableHdr;
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
private StreamConfiguration config = new StreamConfiguration();
|
private StreamConfiguration config = new StreamConfiguration();
|
||||||
@ -81,6 +82,11 @@ public class StreamConfiguration {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StreamConfiguration.Builder setEnableHdr(boolean enableHdr) {
|
||||||
|
config.enableHdr = enableHdr;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public StreamConfiguration.Builder setAudioConfiguration(int audioConfig) {
|
public StreamConfiguration.Builder setAudioConfiguration(int audioConfig) {
|
||||||
if (audioConfig == MoonBridge.AUDIO_CONFIGURATION_STEREO) {
|
if (audioConfig == MoonBridge.AUDIO_CONFIGURATION_STEREO) {
|
||||||
config.audioChannelCount = CHANNEL_COUNT_STEREO;
|
config.audioChannelCount = CHANNEL_COUNT_STEREO;
|
||||||
@ -122,6 +128,7 @@ public class StreamConfiguration {
|
|||||||
this.audioChannelCount = CHANNEL_COUNT_STEREO;
|
this.audioChannelCount = CHANNEL_COUNT_STEREO;
|
||||||
this.audioChannelMask = CHANNEL_MASK_STEREO;
|
this.audioChannelMask = CHANNEL_MASK_STEREO;
|
||||||
this.supportsHevc = false;
|
this.supportsHevc = false;
|
||||||
|
this.enableHdr = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWidth() {
|
public int getWidth() {
|
||||||
@ -183,4 +190,8 @@ public class StreamConfiguration {
|
|||||||
public int getHevcBitratePercentageMultiplier() {
|
public int getHevcBitratePercentageMultiplier() {
|
||||||
return hevcBitratePercentageMultiplier;
|
return hevcBitratePercentageMultiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getEnableHdr() {
|
||||||
|
return enableHdr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ public class NvApp {
|
|||||||
private String appName = "";
|
private String appName = "";
|
||||||
private int appId;
|
private int appId;
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
|
private boolean hdrSupported;
|
||||||
|
|
||||||
public NvApp() {}
|
public NvApp() {}
|
||||||
|
|
||||||
@ -13,9 +14,10 @@ public class NvApp {
|
|||||||
this.appName = appName;
|
this.appName = appName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NvApp(String appName, int appId) {
|
public NvApp(String appName, int appId, boolean hdrSupported) {
|
||||||
this.appName = appName;
|
this.appName = appName;
|
||||||
this.appId = appId;
|
this.appId = appId;
|
||||||
|
this.hdrSupported = hdrSupported;
|
||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +39,10 @@ public class NvApp {
|
|||||||
this.initialized = true;
|
this.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHdrSupported(boolean hdrSupported) {
|
||||||
|
this.hdrSupported = hdrSupported;
|
||||||
|
}
|
||||||
|
|
||||||
public String getAppName() {
|
public String getAppName() {
|
||||||
return this.appName;
|
return this.appName;
|
||||||
}
|
}
|
||||||
@ -45,6 +51,10 @@ public class NvApp {
|
|||||||
return this.appId;
|
return this.appId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHdrSupported() {
|
||||||
|
return this.hdrSupported;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isInitialized() {
|
public boolean isInitialized() {
|
||||||
return this.initialized;
|
return this.initialized;
|
||||||
}
|
}
|
||||||
|
@ -371,6 +371,27 @@ public class NvHTTP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 {
|
public String getGpuType(String serverInfo) throws XmlPullParserException, IOException {
|
||||||
return getXmlString(serverInfo, "gputype");
|
return getXmlString(serverInfo, "gputype");
|
||||||
}
|
}
|
||||||
@ -504,6 +525,8 @@ public class NvHTTP {
|
|||||||
app.setAppName(xpp.getText().trim());
|
app.setAppName(xpp.getText().trim());
|
||||||
} else if (currentTag.peek().equals("ID")) {
|
} else if (currentTag.peek().equals("ID")) {
|
||||||
app.setAppId(xpp.getText().trim());
|
app.setAppId(xpp.getText().trim());
|
||||||
|
} else if (currentTag.peek().equals("IsHdrSupported")) {
|
||||||
|
app.setHdrSupported(xpp.getText().trim().equals("1"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -601,7 +624,7 @@ public class NvHTTP {
|
|||||||
return new String(hexChars);
|
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 +
|
String xmlStr = openHttpConnectionToString(baseUrlHttps +
|
||||||
"/launch?" + buildUniqueIdUuidString() +
|
"/launch?" + buildUniqueIdUuidString() +
|
||||||
"&appid=" + appId +
|
"&appid=" + appId +
|
||||||
@ -609,6 +632,7 @@ public class NvHTTP {
|
|||||||
"&additionalStates=1&sops=" + (context.streamConfig.getSops() ? 1 : 0) +
|
"&additionalStates=1&sops=" + (context.streamConfig.getSops() ? 1 : 0) +
|
||||||
"&rikey="+bytesToHex(context.riKey.getEncoded()) +
|
"&rikey="+bytesToHex(context.riKey.getEncoded()) +
|
||||||
"&rikeyid="+context.riKeyId +
|
"&rikeyid="+context.riKeyId +
|
||||||
|
(!enableHdr ? "" : "&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0") +
|
||||||
"&localAudioPlayMode=" + (context.streamConfig.getPlayLocalAudio() ? 1 : 0) +
|
"&localAudioPlayMode=" + (context.streamConfig.getPlayLocalAudio() ? 1 : 0) +
|
||||||
"&surroundAudioInfo=" + ((context.streamConfig.getAudioChannelMask() << 16) + context.streamConfig.getAudioChannelCount()),
|
"&surroundAudioInfo=" + ((context.streamConfig.getAudioChannelMask() << 16) + context.streamConfig.getAudioChannelCount()),
|
||||||
false);
|
false);
|
||||||
|
@ -160,6 +160,7 @@ public class MoonBridge {
|
|||||||
int width, int height, int fps,
|
int width, int height, int fps,
|
||||||
int bitrate, int packetSize, boolean streamingRemotely,
|
int bitrate, int packetSize, boolean streamingRemotely,
|
||||||
int audioConfiguration, boolean supportsHevc,
|
int audioConfiguration, boolean supportsHevc,
|
||||||
|
boolean enableHdr,
|
||||||
int hevcBitratePercentageMultiplier,
|
int hevcBitratePercentageMultiplier,
|
||||||
byte[] riAesKey, byte[] riAesIv,
|
byte[] riAesKey, byte[] riAesIv,
|
||||||
int videoCapabilities);
|
int videoCapabilities);
|
||||||
|
@ -382,6 +382,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jobject
|
|||||||
jint width, jint height, jint fps,
|
jint width, jint height, jint fps,
|
||||||
jint bitrate, jint packetSize, jboolean streamingRemotely,
|
jint bitrate, jint packetSize, jboolean streamingRemotely,
|
||||||
jint audioConfiguration, jboolean supportsHevc,
|
jint audioConfiguration, jboolean supportsHevc,
|
||||||
|
jboolean enableHdr,
|
||||||
jint hevcBitratePercentageMultiplier,
|
jint hevcBitratePercentageMultiplier,
|
||||||
jbyteArray riAesKey, jbyteArray riAesIv,
|
jbyteArray riAesKey, jbyteArray riAesIv,
|
||||||
jint videoCapabilities) {
|
jint videoCapabilities) {
|
||||||
@ -399,6 +400,7 @@ Java_com_limelight_nvstream_jni_MoonBridge_startConnection(JNIEnv *env, jobject
|
|||||||
.streamingRemotely = streamingRemotely,
|
.streamingRemotely = streamingRemotely,
|
||||||
.audioConfiguration = audioConfiguration,
|
.audioConfiguration = audioConfiguration,
|
||||||
.supportsHevc = supportsHevc,
|
.supportsHevc = supportsHevc,
|
||||||
|
.enableHdr = enableHdr,
|
||||||
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
|
.hevcBitratePercentageMultiplier = hevcBitratePercentageMultiplier,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user