Use DummySurface on S8 where possible

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=158838707
This commit is contained in:
olly 2017-06-13 06:34:02 -07:00 committed by Oliver Woodman
parent fb12a659a2
commit f3e9166a4e
2 changed files with 52 additions and 32 deletions

View File

@ -41,6 +41,8 @@ import static android.opengl.GLES20.glDeleteTextures;
import static android.opengl.GLES20.glGenTextures; import static android.opengl.GLES20.glGenTextures;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.graphics.SurfaceTexture.OnFrameAvailableListener; import android.graphics.SurfaceTexture.OnFrameAvailableListener;
import android.opengl.EGL14; import android.opengl.EGL14;
@ -68,19 +70,8 @@ public final class DummySurface extends Surface {
private static final int EGL_PROTECTED_CONTENT_EXT = 0x32C0; private static final int EGL_PROTECTED_CONTENT_EXT = 0x32C0;
/** private static boolean secureSupported;
* Whether the device supports secure dummy surfaces. private static boolean secureSupportedInitialized;
*/
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;
}
}
/** /**
* Whether the surface is secure. * Whether the surface is secure.
@ -90,18 +81,40 @@ public final class DummySurface extends Surface {
private final DummySurfaceThread thread; private final DummySurfaceThread thread;
private boolean threadReleased; 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} * Returns a newly created dummy surface. The surface must be released by calling {@link #release}
* when it's no longer required. * when it's no longer required.
* <p> * <p>
* Must only be called if {@link Util#SDK_INT} is 17 or higher. * 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 * @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(); assertApiLevel17OrHigher();
Assertions.checkState(!secure || SECURE_SUPPORTED); Assertions.checkState(!secure || isSecureSupported(context));
DummySurfaceThread thread = new DummySurfaceThread(); DummySurfaceThread thread = new DummySurfaceThread();
return thread.init(secure); 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, private static class DummySurfaceThread extends HandlerThread implements OnFrameAvailableListener,
Callback { Callback {

View File

@ -67,6 +67,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
// pending output streams that have fewer frames than the codec latency. // pending output streams that have fewer frames than the codec latency.
private static final int MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT = 10; private static final int MAX_PENDING_OUTPUT_STREAM_OFFSET_COUNT = 10;
private final Context context;
private final VideoFrameReleaseTimeHelper frameReleaseTimeHelper; private final VideoFrameReleaseTimeHelper frameReleaseTimeHelper;
private final EventDispatcher eventDispatcher; private final EventDispatcher eventDispatcher;
private final long allowedJoiningTimeMs; private final long allowedJoiningTimeMs;
@ -167,6 +168,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys); super(C.TRACK_TYPE_VIDEO, mediaCodecSelector, drmSessionManager, playClearSamplesWithoutKeys);
this.allowedJoiningTimeMs = allowedJoiningTimeMs; this.allowedJoiningTimeMs = allowedJoiningTimeMs;
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify; this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
this.context = context.getApplicationContext();
frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context); frameReleaseTimeHelper = new VideoFrameReleaseTimeHelper(context);
eventDispatcher = new EventDispatcher(eventHandler, eventListener); eventDispatcher = new EventDispatcher(eventHandler, eventListener);
deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround(); deviceNeedsAutoFrcWorkaround = deviceNeedsAutoFrcWorkaround();
@ -341,7 +343,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} else { } else {
MediaCodecInfo codecInfo = getCodecInfo(); MediaCodecInfo codecInfo = getCodecInfo();
if (codecInfo != null && shouldUseDummySurface(codecInfo.secure)) { if (codecInfo != null && shouldUseDummySurface(codecInfo.secure)) {
dummySurface = DummySurface.newInstanceV17(codecInfo.secure); dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
surface = dummySurface; surface = dummySurface;
} }
} }
@ -394,7 +396,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
if (surface == null) { if (surface == null) {
Assertions.checkState(shouldUseDummySurface(codecInfo.secure)); Assertions.checkState(shouldUseDummySurface(codecInfo.secure));
if (dummySurface == null) { if (dummySurface == null) {
dummySurface = DummySurface.newInstanceV17(codecInfo.secure); dummySurface = DummySurface.newInstanceV17(context, codecInfo.secure);
} }
surface = dummySurface; surface = dummySurface;
} }
@ -653,8 +655,8 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
} }
private boolean shouldUseDummySurface(boolean codecIsSecure) { private boolean shouldUseDummySurface(boolean codecIsSecure) {
return Util.SDK_INT >= 23 && !tunneling && (!codecIsSecure return Util.SDK_INT >= 23 && !tunneling
|| (DummySurface.SECURE_SUPPORTED && !deviceNeedsSecureDummySurfaceWorkaround())); && (!codecIsSecure || DummySurface.isSecureSupported(context));
} }
private void setJoiningDeadlineMs() { private void setJoiningDeadlineMs() {
@ -921,18 +923,6 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer {
codec.setVideoScalingMode(scalingMode); codec.setVideoScalingMode(scalingMode);
} }
/**
* Returns whether the device is known to fail outputting from a secure decoder to a secure
* surface texture.
* <p>
* 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 * Returns whether the device is known to enable frame-rate conversion logic that negatively
* impacts ExoPlayer. * impacts ExoPlayer.