Add option to stream at device native resolution

Fixes #155
This commit is contained in:
Cameron Gutman
2020-12-23 16:17:06 -06:00
parent 7cc7953879
commit b392d7f8e3
6 changed files with 77 additions and 3 deletions

View File

@@ -110,8 +110,10 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
if (!MediaCodecHelper.decoderIsWhitelistedForHevc(decoderInfo.getName(), meteredNetwork)) {
LimeLog.info("Found HEVC decoder, but it's not whitelisted - "+decoderInfo.getName());
// HDR implies HEVC forced on, since HEVCMain10HDR10 is required for HDR
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_ON || requestedHdr) {
// HDR implies HEVC forced on, since HEVCMain10HDR10 is required for HDR.
// > 4K streaming also requires HEVC, so force it on there too.
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_ON || requestedHdr ||
prefs.width > 4096 || prefs.height > 4096) {
LimeLog.info("Forcing H265 enabled despite non-whitelisted decoder");
}
else {
@@ -250,6 +252,11 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
return -1;
}
if (width > 4096 || height > 4096) {
LimeLog.severe("> 4K streaming only supported on HEVC");
return -1;
}
// These fixups only apply to H264 decoders
needsSpsBitstreamFixup = MediaCodecHelper.decoderNeedsSpsBitstreamRestrictions(selectedDecoderName);
needsBaselineSpsHack = MediaCodecHelper.decoderNeedsBaselineSpsHack(selectedDecoderName);

View File

@@ -115,7 +115,17 @@ public class NvConnection {
//
// Check for a supported stream resolution
if (context.streamConfig.getHeight() >= 2160 && !h.supports4K(serverInfo)) {
if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
(h.getServerCodecModeSupport(serverInfo) & 0x200) == 0) {
context.connListener.displayMessage("Your host PC does not support streaming at resolutions above 4K.");
return false;
}
else if ((context.streamConfig.getWidth() > 4096 || context.streamConfig.getHeight() > 4096) &&
!context.streamConfig.getHevcSupported()) {
context.connListener.displayMessage("Your streaming device must support H.265 to stream at resolutions above 4K.");
return false;
}
else if (context.streamConfig.getHeight() >= 2160 && !h.supports4K(serverInfo)) {
// Client wants 4K but the server can't do it
context.connListener.displayTransientMessage("You must update GeForce Experience to stream in 4K. The stream will be 1080p.");

View File

@@ -83,6 +83,7 @@ public class PreferenceConfiguration {
public static final String RES_1080P = "1920x1080";
public static final String RES_1440P = "2560x1440";
public static final String RES_4K = "3840x2160";
public static final String RES_NATIVE = "Native";
public int width, height, fps;
public int bitrate;

View File

@@ -25,6 +25,7 @@ import com.limelight.LimeLog;
import com.limelight.PcView;
import com.limelight.R;
import com.limelight.binding.video.MediaCodecHelper;
import com.limelight.utils.Dialog;
import com.limelight.utils.UiHelper;
public class StreamSettings extends Activity {
@@ -72,6 +73,23 @@ public class StreamSettings extends Activity {
pref.setValue(value);
}
private void updateNativeResolutionEntry(int nativeWidth, int nativeHeight) {
ListPreference pref = (ListPreference) findPreference(PreferenceConfiguration.RESOLUTION_PREF_STRING);
String nameSuffix = " ("+nativeWidth+"x"+nativeHeight+")";
String newValue = nativeWidth+"x"+nativeHeight;
CharSequence[] entries = pref.getEntries();
CharSequence[] values = pref.getEntryValues();
// Add the name suffix to the native option
entries[entries.length - 1] = entries[entries.length - 1].toString() + nameSuffix;
values[values.length - 1] = newValue;
pref.setEntries(entries);
pref.setEntryValues(values);
}
private void removeValue(String preferenceKey, String value, Runnable onMatched) {
int matchingCount = 0;
@@ -192,6 +210,7 @@ public class StreamSettings extends Activity {
// HEVC Decoder: OMX.amlogic.hevc.decoder.awesome
// AVC supported width range: 64 - 384
// HEVC supported width range: 64 - 544
int nativeWidth = 0, nativeHeight = 0;
for (Display.Mode candidate : display.getSupportedModes()) {
// Some devices report their dimensions in the portrait orientation
// where height > width. Normalize these to the conventional width > height
@@ -200,6 +219,13 @@ public class StreamSettings extends Activity {
int width = Math.max(candidate.getPhysicalWidth(), candidate.getPhysicalHeight());
int height = Math.min(candidate.getPhysicalWidth(), candidate.getPhysicalHeight());
if (width > nativeWidth) {
nativeWidth = width;
}
if (height > nativeHeight) {
nativeHeight = height;
}
if ((width >= 3840 || height >= 2160) && maxSupportedResW < 3840) {
maxSupportedResW = 3840;
}
@@ -215,6 +241,8 @@ public class StreamSettings extends Activity {
}
}
updateNativeResolutionEntry(nativeWidth, nativeHeight);
// This must be called to do runtime initialization before calling functions that evaluate
// decoder lists.
MediaCodecHelper.initialize(getContext(), GlPreferences.readPreferences(getContext()).glRenderer);
@@ -299,6 +327,11 @@ public class StreamSettings extends Activity {
// Never remove 720p
}
}
else {
updateNativeResolutionEntry(
getActivity().getWindowManager().getDefaultDisplay().getWidth(),
getActivity().getWindowManager().getDefaultDisplay().getHeight());
}
if (!PreferenceConfiguration.readPreferences(this.getActivity()).unlockFps) {
// We give some extra room in case the FPS is rounded down
@@ -408,6 +441,25 @@ public class StreamSettings extends Activity {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SettingsFragment.this.getActivity());
String valueStr = (String) newValue;
// Detect if this value is the native resolution option
CharSequence[] values = ((ListPreference)preference).getEntryValues();
boolean isNativeRes = true;
for (int i = 0; i < values.length; i++) {
// If get a match prior to the end, it's not native res
if (valueStr.equals(values[i].toString()) && i < values.length - 1) {
isNativeRes = false;
break;
}
}
// If this is native resolution, show the warning dialog
if (isNativeRes) {
Dialog.displayDialog(getActivity(),
getResources().getString(R.string.title_native_res_dialog),
getResources().getString(R.string.text_native_res_dialog),
false);
}
// Write the new bitrate value
resetBitrateToDefault(prefs, valueStr, null);