mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2026-04-22 08:20:12 +00:00
Don't use reference picture invalidation on low-end Snapdragon SoCs
This commit is contained in:
@@ -44,6 +44,7 @@ import android.hardware.input.InputManager;
|
|||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
|
import android.opengl.GLSurfaceView;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -65,6 +66,9 @@ import android.widget.FrameLayout;
|
|||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import javax.microedition.khronos.egl.EGLConfig;
|
||||||
|
import javax.microedition.khronos.opengles.GL10;
|
||||||
|
|
||||||
|
|
||||||
public class Game extends Activity implements SurfaceHolder.Callback,
|
public class Game extends Activity implements SurfaceHolder.Callback,
|
||||||
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
OnGenericMotionListener, OnTouchListener, NvConnectionListener, EvdevListener,
|
||||||
@@ -104,6 +108,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
private ShortcutHelper shortcutHelper;
|
private ShortcutHelper shortcutHelper;
|
||||||
|
|
||||||
private MediaCodecDecoderRenderer decoderRenderer;
|
private MediaCodecDecoderRenderer decoderRenderer;
|
||||||
|
private String glRenderer;
|
||||||
|
|
||||||
private WifiManager.WifiLock wifiLock;
|
private WifiManager.WifiLock wifiLock;
|
||||||
|
|
||||||
@@ -135,8 +140,6 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
shortcutHelper = new ShortcutHelper(this);
|
|
||||||
|
|
||||||
UiHelper.setLocale(this);
|
UiHelper.setLocale(this);
|
||||||
|
|
||||||
// We don't want a title bar
|
// We don't want a title bar
|
||||||
@@ -164,6 +167,33 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
// Change volume button behavior
|
// Change volume button behavior
|
||||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||||
|
|
||||||
|
// We first construct a GLSurfaceView to probe for GL
|
||||||
|
// properties to pass to MediaCodecHelper. After this completes,
|
||||||
|
// we'll construct the activity like normal.
|
||||||
|
GLSurfaceView surfaceView = new GLSurfaceView(this);
|
||||||
|
surfaceView.setRenderer(new GLSurfaceView.Renderer() {
|
||||||
|
@Override
|
||||||
|
public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
|
||||||
|
glRenderer = gl10.glGetString(GL10.GL_RENDERER);
|
||||||
|
LimeLog.info("GL Renderer: "+glRenderer);
|
||||||
|
runOnUiThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
completeOnCreate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceChanged(GL10 gl10, int i, int i1) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawFrame(GL10 gl10) {}
|
||||||
|
});
|
||||||
|
setContentView(surfaceView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void completeOnCreate() {
|
||||||
// Inflate the content
|
// Inflate the content
|
||||||
setContentView(R.layout.activity_game);
|
setContentView(R.layout.activity_game);
|
||||||
|
|
||||||
@@ -222,11 +252,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a launcher shortcut for this PC (forced, since this is user interaction)
|
// Add a launcher shortcut for this PC (forced, since this is user interaction)
|
||||||
|
shortcutHelper = new ShortcutHelper(this);
|
||||||
shortcutHelper.createAppViewShortcut(uuid, pcName, uuid, true);
|
shortcutHelper.createAppViewShortcut(uuid, pcName, uuid, true);
|
||||||
shortcutHelper.reportShortcutUsed(uuid);
|
shortcutHelper.reportShortcutUsed(uuid);
|
||||||
|
|
||||||
// Initialize the MediaCodec helper before creating the decoder
|
// Initialize the MediaCodec helper before creating the decoder
|
||||||
MediaCodecHelper.initializeWithContext(this);
|
MediaCodecHelper.initialize(this, glRenderer);
|
||||||
|
|
||||||
// Check if the user has enabled HDR
|
// Check if the user has enabled HDR
|
||||||
if (prefConfig.enableHdr) {
|
if (prefConfig.enableHdr) {
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ public class MediaCodecDecoderRenderer extends VideoDecoderRenderer {
|
|||||||
if (avcDecoder != null) {
|
if (avcDecoder != null) {
|
||||||
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
directSubmit = MediaCodecHelper.decoderCanDirectSubmit(avcDecoder.getName());
|
||||||
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder);
|
adaptivePlayback = MediaCodecHelper.decoderSupportsAdaptivePlayback(avcDecoder);
|
||||||
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName());
|
refFrameInvalidationAvc = MediaCodecHelper.decoderSupportsRefFrameInvalidationAvc(avcDecoder.getName(), prefs.height);
|
||||||
refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName());
|
refFrameInvalidationHevc = MediaCodecHelper.decoderSupportsRefFrameInvalidationHevc(avcDecoder.getName());
|
||||||
|
|
||||||
if (directSubmit) {
|
if (directSubmit) {
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import java.util.Collections;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ConfigurationInfo;
|
import android.content.pm.ConfigurationInfo;
|
||||||
@@ -36,6 +37,8 @@ public class MediaCodecHelper {
|
|||||||
private static final List<String> refFrameInvalidationAvcPrefixes;
|
private static final List<String> refFrameInvalidationAvcPrefixes;
|
||||||
private static final List<String> refFrameInvalidationHevcPrefixes;
|
private static final List<String> refFrameInvalidationHevcPrefixes;
|
||||||
|
|
||||||
|
private static boolean isLowEndSnapdragon = false;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
directSubmitPrefixes = new LinkedList<>();
|
directSubmitPrefixes = new LinkedList<>();
|
||||||
|
|
||||||
@@ -146,20 +149,43 @@ public class MediaCodecHelper {
|
|||||||
// Qualcomm is currently the only decoders in this group.
|
// Qualcomm is currently the only decoders in this group.
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initializeWithContext(Context context) {
|
private static boolean isLowEndSnapdragonRenderer(String glRenderer) {
|
||||||
|
glRenderer = glRenderer.toLowerCase().trim();
|
||||||
|
|
||||||
|
if (!glRenderer.contains("adreno")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pattern modelNumberPattern = Pattern.compile("(.*)([0-9]{3})(.*)");
|
||||||
|
|
||||||
|
Matcher matcher = modelNumberPattern.matcher(glRenderer);
|
||||||
|
if (!matcher.matches()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String modelNumber = matcher.group(2);
|
||||||
|
LimeLog.info("Found Adreno GPU: "+modelNumber);
|
||||||
|
|
||||||
|
// The current logic is to identify low-end SoCs based on a zero in the x0x place.
|
||||||
|
return modelNumber.charAt(1) == '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initialize(Context context, String glRenderer) {
|
||||||
ActivityManager activityManager =
|
ActivityManager activityManager =
|
||||||
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||||
ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
|
ConfigurationInfo configInfo = activityManager.getDeviceConfigurationInfo();
|
||||||
if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
|
if (configInfo.reqGlEsVersion != ConfigurationInfo.GL_ES_VERSION_UNDEFINED) {
|
||||||
LimeLog.info("OpenGL ES version: "+configInfo.reqGlEsVersion);
|
LimeLog.info("OpenGL ES version: "+configInfo.reqGlEsVersion);
|
||||||
|
|
||||||
|
isLowEndSnapdragon = isLowEndSnapdragonRenderer(glRenderer);
|
||||||
|
|
||||||
// Tegra K1 and later can do reference frame invalidation properly
|
// Tegra K1 and later can do reference frame invalidation properly
|
||||||
if (configInfo.reqGlEsVersion >= 0x30000) {
|
if (configInfo.reqGlEsVersion >= 0x30000) {
|
||||||
LimeLog.info("Added omx.nvidia to AVC reference frame invalidation support list");
|
LimeLog.info("Added omx.nvidia to AVC reference frame invalidation support list");
|
||||||
refFrameInvalidationAvcPrefixes.add("omx.nvidia");
|
refFrameInvalidationAvcPrefixes.add("omx.nvidia");
|
||||||
|
|
||||||
LimeLog.info("Added omx.qcom to AVC reference frame invalidation support list");
|
LimeLog.info("Added omx.qcom to AVC reference frame invalidation support list");
|
||||||
refFrameInvalidationAvcPrefixes.add("omx.qcom");
|
refFrameInvalidationAvcPrefixes.add("omx.qcom");
|
||||||
|
|
||||||
// Prior to M, we were tricking the decoder into using baseline profile, which
|
// Prior to M, we were tricking the decoder into using baseline profile, which
|
||||||
// won't support RFI properly.
|
// won't support RFI properly.
|
||||||
@@ -247,7 +273,11 @@ public class MediaCodecHelper {
|
|||||||
return isDecoderInList(baselineProfileHackPrefixes, decoderName);
|
return isDecoderInList(baselineProfileHackPrefixes, decoderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean decoderSupportsRefFrameInvalidationAvc(String decoderName) {
|
public static boolean decoderSupportsRefFrameInvalidationAvc(String decoderName, int videoHeight) {
|
||||||
|
// Reference frame invalidation is broken on low-end Snapdragon SoCs at 1080p.
|
||||||
|
if (videoHeight > 720 && isLowEndSnapdragon) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return isDecoderInList(refFrameInvalidationAvcPrefixes, decoderName);
|
return isDecoderInList(refFrameInvalidationAvcPrefixes, decoderName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,4 +28,7 @@ This file serves to document some of the decoder errata when using MediaCodec ha
|
|||||||
- Affected decoders: Intel decoder in Nexus Player (after Android 6.0)
|
- Affected decoders: Intel decoder in Nexus Player (after Android 6.0)
|
||||||
|
|
||||||
10. Some decoders actually suffer increased latency when max_dec_frame_buffering=1
|
10. Some decoders actually suffer increased latency when max_dec_frame_buffering=1
|
||||||
- Affected decoders: MediaTek decoder in Fire TV 2015
|
- Affected decoders: MediaTek decoder in Fire TV 2015
|
||||||
|
|
||||||
|
11. Attempting to use reference picture invalidation at 1080p causes the decoder to crash on low-end Snapdragon SoCs. 720p is unaffected.
|
||||||
|
- Affected decoders: Snapdragon 200, 410, 415, 430, 435, 616
|
||||||
|
|||||||
Reference in New Issue
Block a user