mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-01 23:35:28 +00:00
Plumb AV1 preference and rework HEVC preference to match
This commit is contained in:
parent
3a78095574
commit
458460515d
@ -411,11 +411,14 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
||||
}
|
||||
|
||||
// Display a message to the user if HEVC was forced on but we still didn't find a decoder
|
||||
if (prefConfig.videoFormat == PreferenceConfiguration.FORCE_H265_ON && !decoderRenderer.isHevcSupported()) {
|
||||
Toast.makeText(this, "No HEVC decoder found.\nFalling back to H.264.", Toast.LENGTH_LONG).show();
|
||||
if (prefConfig.hevcFormat == PreferenceConfiguration.FormatOption.FORCE_ON && !decoderRenderer.isHevcSupported()) {
|
||||
Toast.makeText(this, "No HEVC decoder found", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
// TODO: Display a message to the user if HEVC was forced on but we still didn't find a decoder
|
||||
// Display a message to the user if AV1 was forced on but we still didn't find a decoder
|
||||
if (prefConfig.av1Format == PreferenceConfiguration.FormatOption.FORCE_ON && !decoderRenderer.isAv1Supported()) {
|
||||
Toast.makeText(this, "No AV1 decoder found", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
// H.264 is always supported
|
||||
int supportedVideoFormats = MoonBridge.VIDEO_FORMAT_H264;
|
||||
|
@ -193,7 +193,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
|
||||
private MediaCodecInfo findHevcDecoder(PreferenceConfiguration prefs, boolean meteredNetwork, boolean requestedHdr) {
|
||||
// Don't return anything if HEVC is forced off
|
||||
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_OFF) {
|
||||
if (prefs.hevcFormat == PreferenceConfiguration.FormatOption.FORCE_OFF) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
LimeLog.info("Found HEVC decoder, but it's not whitelisted - "+hevcDecoderInfo.getName());
|
||||
|
||||
// Force HEVC enabled if the user asked for it
|
||||
if (prefs.videoFormat == PreferenceConfiguration.FORCE_H265_ON) {
|
||||
if (prefs.hevcFormat == PreferenceConfiguration.FormatOption.FORCE_ON) {
|
||||
LimeLog.info("Forcing HEVC enabled despite non-whitelisted decoder");
|
||||
}
|
||||
// HDR implies HEVC forced on, since HEVCMain10HDR10 is required for HDR.
|
||||
@ -233,7 +233,27 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer implements C
|
||||
}
|
||||
|
||||
private MediaCodecInfo findAv1Decoder(PreferenceConfiguration prefs) {
|
||||
return MediaCodecHelper.findProbableSafeDecoder("video/av01", -1);
|
||||
// Don't return anything if AV1 is forced off
|
||||
if (prefs.av1Format == PreferenceConfiguration.FormatOption.FORCE_OFF) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MediaCodecInfo decoderInfo = MediaCodecHelper.findProbableSafeDecoder("video/av01", -1);
|
||||
if (decoderInfo != null) {
|
||||
if (!MediaCodecHelper.isDecoderWhitelistedForAv1(decoderInfo)) {
|
||||
LimeLog.info("Found AV1 decoder, but it's not whitelisted - "+decoderInfo.getName());
|
||||
|
||||
// Force HEVC enabled if the user asked for it
|
||||
if (prefs.av1Format == PreferenceConfiguration.FormatOption.FORCE_ON) {
|
||||
LimeLog.info("Forcing AV1 enabled despite non-whitelisted decoder");
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return decoderInfo;
|
||||
}
|
||||
|
||||
public void setRenderTarget(SurfaceHolder renderTarget) {
|
||||
|
@ -747,7 +747,33 @@ public class MediaCodecHelper {
|
||||
// Otherwise, we use our list of known working HEVC decoders
|
||||
return isDecoderInList(whitelistedHevcDecoders, decoderInfo.getName());
|
||||
}
|
||||
|
||||
|
||||
public static boolean isDecoderWhitelistedForAv1(MediaCodecInfo decoderInfo) {
|
||||
// Google didn't have official support for AV1 (or more importantly, a CTS test) until
|
||||
// Android 10, so don't use any decoder before then.
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Software decoders are terrible and we never want to use them.
|
||||
// We want to catch decoders like:
|
||||
// OMX.qcom.video.decoder.hevcswvdec
|
||||
// OMX.SEC.hevc.sw.dec
|
||||
//
|
||||
if (decoderInfo.getName().contains("sw")) {
|
||||
LimeLog.info("Disallowing AV1 on software decoder: " + decoderInfo.getName());
|
||||
return false;
|
||||
}
|
||||
else if (!decoderInfo.isHardwareAccelerated() || decoderInfo.isSoftwareOnly()) {
|
||||
LimeLog.info("Disallowing AV1 on software decoder: " + decoderInfo.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Test some AV1 decoders
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@SuppressLint("NewApi")
|
||||
private static LinkedList<MediaCodecInfo> getMediaCodecList() {
|
||||
|
@ -10,6 +10,12 @@ import android.view.Display;
|
||||
import com.limelight.nvstream.jni.MoonBridge;
|
||||
|
||||
public class PreferenceConfiguration {
|
||||
public enum FormatOption {
|
||||
AUTO,
|
||||
FORCE_ON,
|
||||
FORCE_OFF
|
||||
};
|
||||
|
||||
private static final String LEGACY_RES_FPS_PREF_STRING = "list_resolution_fps";
|
||||
private static final String LEGACY_ENABLE_51_SURROUND_PREF_STRING = "checkbox_51_surround";
|
||||
|
||||
@ -28,7 +34,8 @@ public class PreferenceConfiguration {
|
||||
private static final String MULTI_CONTROLLER_PREF_STRING = "checkbox_multi_controller";
|
||||
static final String AUDIO_CONFIG_PREF_STRING = "list_audio_config";
|
||||
private static final String USB_DRIVER_PREF_SRING = "checkbox_usb_driver";
|
||||
private static final String VIDEO_FORMAT_PREF_STRING = "video_format";
|
||||
private static final String HEVC_FORMAT_PREF_STRING = "video_format";
|
||||
private static final String AV1_FORMAT_PREF_STRING = "av1_format";
|
||||
private static final String ONSCREEN_CONTROLLER_PREF_STRING = "checkbox_show_onscreen_controls";
|
||||
private static final String ONLY_L3_R3_PREF_STRING = "checkbox_only_show_L3R3";
|
||||
private static final String LEGACY_DISABLE_FRAME_DROP_PREF_STRING = "checkbox_disable_frame_drop";
|
||||
@ -61,7 +68,9 @@ public class PreferenceConfiguration {
|
||||
public static final String DEFAULT_LANGUAGE = "default";
|
||||
private static final boolean DEFAULT_MULTI_CONTROLLER = true;
|
||||
private static final boolean DEFAULT_USB_DRIVER = true;
|
||||
private static final String DEFAULT_VIDEO_FORMAT = "auto";
|
||||
private static final String DEFAULT_HEVC_FORMAT = "auto";
|
||||
private static final String DEFAULT_AV1_FORMAT = "never";
|
||||
|
||||
private static final boolean ONSCREEN_CONTROLLER_DEFAULT = false;
|
||||
private static final boolean ONLY_L3_R3_DEFAULT = false;
|
||||
private static final boolean DEFAULT_ENABLE_HDR = false;
|
||||
@ -83,10 +92,6 @@ public class PreferenceConfiguration {
|
||||
private static final boolean DEFAULT_REDUCE_REFRESH_RATE = false;
|
||||
private static final boolean DEFAULT_FULL_RANGE = false;
|
||||
|
||||
public static final int FORCE_H265_ON = -1;
|
||||
public static final int AUTOSELECT_H265 = 0;
|
||||
public static final int FORCE_H265_OFF = 1;
|
||||
|
||||
public static final int FRAME_PACING_MIN_LATENCY = 0;
|
||||
public static final int FRAME_PACING_BALANCED = 1;
|
||||
public static final int FRAME_PACING_CAP_FPS = 2;
|
||||
@ -102,7 +107,8 @@ public class PreferenceConfiguration {
|
||||
|
||||
public int width, height, fps;
|
||||
public int bitrate;
|
||||
public int videoFormat;
|
||||
public FormatOption hevcFormat;
|
||||
public FormatOption av1Format;
|
||||
public int deadzonePercentage;
|
||||
public int oscOpacity;
|
||||
public boolean stretchVideo, enableSops, playHostAudio, disableWarnings;
|
||||
@ -289,22 +295,41 @@ public class PreferenceConfiguration {
|
||||
prefs.getString(FPS_PREF_STRING, DEFAULT_FPS));
|
||||
}
|
||||
|
||||
private static int getVideoFormatValue(Context context) {
|
||||
private static FormatOption getHevcFormatValue(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
String str = prefs.getString(VIDEO_FORMAT_PREF_STRING, DEFAULT_VIDEO_FORMAT);
|
||||
String str = prefs.getString(HEVC_FORMAT_PREF_STRING, DEFAULT_HEVC_FORMAT);
|
||||
if (str.equals("auto")) {
|
||||
return AUTOSELECT_H265;
|
||||
return FormatOption.AUTO;
|
||||
}
|
||||
else if (str.equals("forceh265")) {
|
||||
return FORCE_H265_ON;
|
||||
return FormatOption.FORCE_ON;
|
||||
}
|
||||
else if (str.equals("neverh265")) {
|
||||
return FORCE_H265_OFF;
|
||||
return FormatOption.FORCE_OFF;
|
||||
}
|
||||
else {
|
||||
// Should never get here
|
||||
return AUTOSELECT_H265;
|
||||
return FormatOption.AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
private static FormatOption getAV1FormatValue(Context context) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
String str = prefs.getString(AV1_FORMAT_PREF_STRING, DEFAULT_AV1_FORMAT);
|
||||
if (str.equals("auto")) {
|
||||
return FormatOption.AUTO;
|
||||
}
|
||||
else if (str.equals("force")) {
|
||||
return FormatOption.FORCE_ON;
|
||||
}
|
||||
else if (str.equals("never")) {
|
||||
return FormatOption.FORCE_OFF;
|
||||
}
|
||||
else {
|
||||
// Should never get here
|
||||
return FormatOption.AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,7 +373,8 @@ public class PreferenceConfiguration {
|
||||
.remove(LEGACY_RES_FPS_PREF_STRING)
|
||||
.remove(RESOLUTION_PREF_STRING)
|
||||
.remove(FPS_PREF_STRING)
|
||||
.remove(VIDEO_FORMAT_PREF_STRING)
|
||||
.remove(HEVC_FORMAT_PREF_STRING)
|
||||
.remove(AV1_FORMAT_PREF_STRING)
|
||||
.remove(ENABLE_HDR_PREF_STRING)
|
||||
.remove(UNLOCK_FPS_STRING)
|
||||
.remove(FULL_RANGE_PREF_STRING)
|
||||
@ -475,7 +501,8 @@ public class PreferenceConfiguration {
|
||||
config.audioConfiguration = MoonBridge.AUDIO_CONFIGURATION_STEREO;
|
||||
}
|
||||
|
||||
config.videoFormat = getVideoFormatValue(context);
|
||||
config.hevcFormat = getHevcFormatValue(context);
|
||||
config.av1Format = getAV1FormatValue(context);
|
||||
config.framePacing = getFramePacingValue(context);
|
||||
|
||||
config.deadzonePercentage = prefs.getInt(DEADZONE_PREF_STRING, DEFAULT_DEADZONE);
|
||||
|
@ -100,6 +100,17 @@
|
||||
<item>neverh265</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="av1_format_names">
|
||||
<item>@string/av1_format_auto</item>
|
||||
<item>@string/av1_format_always</item>
|
||||
<item>@string/av1_format_never</item>
|
||||
</string-array>
|
||||
<string-array name="av1_format_values" translatable="false">
|
||||
<item>auto</item>
|
||||
<item>force</item>
|
||||
<item>never</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="video_frame_pacing_names">
|
||||
<item>@string/pacing_latency</item>
|
||||
<item>@string/pacing_balanced</item>
|
||||
|
@ -232,6 +232,8 @@
|
||||
<string name="summary_disable_frame_drop">May reduce micro-stuttering on some devices, but can increase latency</string>
|
||||
<string name="title_video_format">Change HEVC settings</string>
|
||||
<string name="summary_video_format">HEVC lowers video bandwidth requirements but requires a newer device</string>
|
||||
<string name="title_av1_format">Change AV1 settings (Experimental)</string>
|
||||
<string name="summary_av1_format">AV1 lowers video bandwidth requirements more than HEVC, but is currently experimental.</string>
|
||||
<string name="title_enable_hdr">Enable HDR (Experimental)</string>
|
||||
<string name="summary_enable_hdr">Stream HDR when the game and PC GPU support it. HDR requires a GPU with HEVC Main 10 encoding support.</string>
|
||||
<string name="title_full_range">Force full range video (Experimental)</string>
|
||||
@ -270,6 +272,10 @@
|
||||
<string name="videoformat_hevcalways">Prefer HEVC</string>
|
||||
<string name="videoformat_hevcnever">Never use HEVC</string>
|
||||
|
||||
<string name="av1_format_auto">Automatic (Recommended)</string>
|
||||
<string name="av1_format_always">Prefer AV1</string>
|
||||
<string name="av1_format_never">Never use AV1</string>
|
||||
|
||||
<string name="title_frame_pacing">Video frame pacing</string>
|
||||
<string name="summary_frame_pacing">Specify how to balance video latency and smoothness</string>
|
||||
<string name="pacing_latency">Prefer lowest latency</string>
|
||||
|
@ -206,6 +206,13 @@
|
||||
android:entryValues="@array/video_format_values"
|
||||
android:summary="@string/summary_video_format"
|
||||
android:defaultValue="auto" />
|
||||
<ListPreference
|
||||
android:key="av1_format"
|
||||
android:title="@string/title_av1_format"
|
||||
android:entries="@array/av1_format_names"
|
||||
android:entryValues="@array/av1_format_values"
|
||||
android:summary="@string/summary_av1_format"
|
||||
android:defaultValue="auto" />
|
||||
<CheckBoxPreference
|
||||
android:key="checkbox_enable_hdr"
|
||||
android:title="@string/title_enable_hdr"
|
||||
|
Loading…
x
Reference in New Issue
Block a user