From f3e9166a4eabeb7b2ec8cffedf7c4914a91f48d5 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 13 Jun 2017 06:34:02 -0700 Subject: [PATCH] Use DummySurface on S8 where possible ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=158838707 --- .../exoplayer2/video/DummySurface.java | 62 ++++++++++++++----- .../video/MediaCodecVideoRenderer.java | 22 ++----- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java b/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java index e998eceaaf..e32f23fed7 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/DummySurface.java @@ -41,6 +41,8 @@ import static android.opengl.GLES20.glDeleteTextures; import static android.opengl.GLES20.glGenTextures; import android.annotation.TargetApi; +import android.content.Context; +import android.content.pm.PackageManager; import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture.OnFrameAvailableListener; import android.opengl.EGL14; @@ -68,19 +70,8 @@ public final class DummySurface extends Surface { private static final int EGL_PROTECTED_CONTENT_EXT = 0x32C0; - /** - * Whether the device supports secure dummy surfaces. - */ - public static final boolean SECURE_SUPPORTED; - static { - if (Util.SDK_INT >= 17) { - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - String extensions = EGL14.eglQueryString(display, EGL10.EGL_EXTENSIONS); - SECURE_SUPPORTED = extensions != null && extensions.contains("EGL_EXT_protected_content"); - } else { - SECURE_SUPPORTED = false; - } - } + private static boolean secureSupported; + private static boolean secureSupportedInitialized; /** * Whether the surface is secure. @@ -90,18 +81,40 @@ public final class DummySurface extends Surface { private final DummySurfaceThread thread; private boolean threadReleased; + /** + * Returns whether the device supports secure dummy surfaces. + * + * @param context Any {@link Context}. + * @return Whether the device supports secure dummy surfaces. + */ + public static synchronized boolean isSecureSupported(Context context) { + if (!secureSupportedInitialized) { + if (Util.SDK_INT >= 17) { + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + String extensions = EGL14.eglQueryString(display, EGL10.EGL_EXTENSIONS); + secureSupported = extensions != null && extensions.contains("EGL_EXT_protected_content") + && !deviceNeedsSecureDummySurfaceWorkaround(context); + } + secureSupportedInitialized = true; + } + return secureSupported; + } + /** * Returns a newly created dummy surface. The surface must be released by calling {@link #release} * when it's no longer required. *

* Must only be called if {@link Util#SDK_INT} is 17 or higher. * + * @param context Any {@link Context}. * @param secure Whether a secure surface is required. Must only be requested if - * {@link #SECURE_SUPPORTED} is {@code true}. + * {@link #isSecureSupported(Context)} returns {@code true}. + * @throws IllegalStateException If a secure surface is requested on a device for which + * {@link #isSecureSupported(Context)} returns {@code false}. */ - public static DummySurface newInstanceV17(boolean secure) { + public static DummySurface newInstanceV17(Context context, boolean secure) { assertApiLevel17OrHigher(); - Assertions.checkState(!secure || SECURE_SUPPORTED); + Assertions.checkState(!secure || isSecureSupported(context)); DummySurfaceThread thread = new DummySurfaceThread(); return thread.init(secure); } @@ -133,6 +146,23 @@ public final class DummySurface extends Surface { } } + /** + * Returns whether the device is known to advertise secure surface textures but not implement them + * correctly. + * + * @param context Any {@link Context}. + */ + private static boolean deviceNeedsSecureDummySurfaceWorkaround(Context context) { + return Util.SDK_INT == 24 + && (Util.MODEL.startsWith("SM-G950") || Util.MODEL.startsWith("SM-G955")) + && !hasVrModeHighPerformanceSystemFeatureV24(context.getPackageManager()); + } + + @TargetApi(24) + private static boolean hasVrModeHighPerformanceSystemFeatureV24(PackageManager packageManager) { + return packageManager.hasSystemFeature(PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE); + } + private static class DummySurfaceThread extends HandlerThread implements OnFrameAvailableListener, Callback { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java index 7610bb1a55..75e10f05ff 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/video/MediaCodecVideoRenderer.java @@ -67,6 +67,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { // pending output streams that have fewer frames than the codec latency. private static final int MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT = 10; + private final Context context; private final VideoFrameReleaseTimeHelper frameReleaseTimeHelper; private final EventDispatcher eventDispatcher; private final long allowedJoiningTimeMs; @@ -167,6 +168,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; + this.context = context.getApplicationContext(); frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context); eventDispatcher = new EventDispatcher(eventHandler, eventListener); deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround(); @@ -341,7 +343,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { } else { MediaCodecInfo codecInfo = getCodecInfo(); if (codecInfo != null && shouldUseDummySurface(codecInfo.secure)) { - dummySurface = DummySurface.newInstanceV17(codecInfo.secure); + dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure); surface = dummySurface; } } @@ -394,7 +396,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { if (surface == null) { Assertions.checkState(shouldUseDummySurface(codecInfo.secure)); if (dummySurface == null) { - dummySurface = DummySurface.newInstanceV17(codecInfo.secure); + dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure); } surface = dummySurface; } @@ -653,8 +655,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { } private boolean shouldUseDummySurface(boolean codecIsSecure) { - return Util.SDK_INT >= 23 && !tunneling && (!codecIsSecure - || (DummySurface.SECURE_SUPPORTED && !deviceNeedsSecureDummySurfaceWorkaround())); + return Util.SDK_INT >= 23 && !tunneling + && (!codecIsSecure || DummySurface.isSecureSupported(context)); } private void setJoiningDeadlineMs() { @@ -921,18 +923,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer { codec.setVideoScalingMode(scalingMode); } - /** - * Returns whether the device is known to fail outputting from a secure decoder to a secure - * surface texture. - *

- * If true is returned then use of {@link DummySurface} is disabled for secure playbacks. - */ - private static boolean deviceNeedsSecureDummySurfaceWorkaround() { - // See [Internal: b/37197802]. - return Util.SDK_INT == 24 - && (Util.MODEL.startsWith("SM-G950") || Util.MODEL.startsWith("SM-G955")); - } - /** * Returns whether the device is known to enable frame-rate conversion logic that negatively * impacts ExoPlayer.