From 5e538a2a28a43df077993be438f4a0c06de7ee3a Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 15 Oct 2019 19:09:09 +0100 Subject: [PATCH] Clean up GvrPlayerActivity PiperOrigin-RevId: 274845045 --- .../exoplayer2/ext/gvr/GvrPlayerActivity.java | 159 +++++++++--------- .../styles.xml => layout/exo_vr_ui.xml} | 8 +- extensions/gvr/src/main/res/layout/vr_ui.xml | 28 --- extensions/gvr/src/main/res/values/styles.xml | 2 +- .../ui/spherical/CanvasRenderer.java | 1 - .../exoplayer2/ui/spherical/GlViewGroup.java | 1 - .../ui/spherical/PointerRenderer.java | 3 +- .../ui/spherical/SphericalSurfaceView.java | 4 +- 8 files changed, 89 insertions(+), 117 deletions(-) rename extensions/gvr/src/main/res/{values-v21/styles.xml => layout/exo_vr_ui.xml} (74%) delete mode 100644 extensions/gvr/src/main/res/layout/vr_ui.xml diff --git a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrPlayerActivity.java b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrPlayerActivity.java index 06b9fac487..5d465b494d 100644 --- a/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrPlayerActivity.java +++ b/extensions/gvr/src/main/java/com/google/android/exoplayer2/ext/gvr/GvrPlayerActivity.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.google.android.exoplayer2.ext.gvr; import android.content.Context; @@ -21,8 +20,6 @@ import android.content.Intent; import android.graphics.SurfaceTexture; import android.opengl.Matrix; import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; import android.view.ContextThemeWrapper; import android.view.MotionEvent; import android.view.Surface; @@ -47,6 +44,7 @@ import com.google.vr.sdk.base.HeadTransform; import com.google.vr.sdk.base.Viewport; import com.google.vr.sdk.controller.Controller; import com.google.vr.sdk.controller.ControllerManager; +import com.google.vr.sdk.controller.Orientation; import javax.microedition.khronos.egl.EGLConfig; import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @@ -58,46 +56,36 @@ public abstract class GvrPlayerActivity extends GvrActivity { private static final int EXIT_FROM_VR_REQUEST_CODE = 42; - private final Handler mainHandler; - @Nullable private Player player; - private @MonotonicNonNull GlViewGroup glView; private @MonotonicNonNull ControllerManager controllerManager; private @MonotonicNonNull SurfaceTexture surfaceTexture; private @MonotonicNonNull Surface surface; - private @MonotonicNonNull SceneRenderer scene; - private @MonotonicNonNull PlayerControlView playerControl; - - public GvrPlayerActivity() { - mainHandler = new Handler(Looper.getMainLooper()); - } + private @MonotonicNonNull SceneRenderer sceneRenderer; + private @MonotonicNonNull PlayerControlView playerControlView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setScreenAlwaysOn(true); - GvrView gvrView = new GvrView(this); - // Since videos typically have fewer pixels per degree than the phones, reducing the render - // target scaling factor reduces the work required to render the scene. - gvrView.setRenderTargetScale(.5f); + GvrView gvrView = new GvrView(/* context= */ this); + gvrView.setRenderTargetScale(getRenderTargetScale()); // If a custom theme isn't specified, the Context's theme is used. For VR Activities, this is // the old Android default theme rather than a modern theme. Override this with a custom theme. - Context theme = new ContextThemeWrapper(this, R.style.VrTheme); - glView = new GlViewGroup(theme, R.layout.vr_ui); + Context theme = new ContextThemeWrapper(this, R.style.ExoVrTheme); + GlViewGroup glViewGroup = new GlViewGroup(theme, R.layout.exo_vr_ui); - playerControl = Assertions.checkNotNull(glView.findViewById(R.id.controller)); - playerControl.setShowVrButton(true); - playerControl.setVrButtonListener(v -> exit()); + playerControlView = Assertions.checkNotNull(glViewGroup.findViewById(R.id.controller)); + playerControlView.setShowVrButton(true); + playerControlView.setVrButtonListener(v -> exit()); + sceneRenderer = new SceneRenderer(); PointerRenderer pointerRenderer = new PointerRenderer(); - scene = new SceneRenderer(); - Renderer renderer = new Renderer(scene, glView, pointerRenderer); - - // Attach glView to gvrView in order to properly handle UI events. - gvrView.addView(glView, 0); + Renderer renderer = new Renderer(sceneRenderer, pointerRenderer, glViewGroup); + // Attach glViewGroup to gvrView in order to properly handle UI events. + gvrView.addView(glViewGroup); // Standard GvrView configuration gvrView.setEGLConfigChooser( 8, 8, 8, 8, // RGBA bits. @@ -106,15 +94,13 @@ public abstract class GvrPlayerActivity extends GvrActivity { gvrView.setRenderer(renderer); setContentView(gvrView); - // Most Daydream phones can render a 4k video at 60fps in sustained performance mode. These - // options can be tweaked along with the render target scale. if (gvrView.setAsyncReprojectionEnabled(true)) { - AndroidCompat.setSustainedPerformanceMode(this, true); + AndroidCompat.setSustainedPerformanceMode(/* activity= */ this, true); } // Handle the user clicking on the 'X' in the top left corner. Since this is done when the user // has taken the headset out of VR, it should launch the app's exit flow directly rather than - // using the transition flow. + // using Daydream's exit transition. gvrView.setOnCloseButtonListener(this::finish); ControllerManager.EventListener listener = @@ -126,15 +112,14 @@ public abstract class GvrPlayerActivity extends GvrActivity { @Override public void onRecentered() { - // TODO if in cardboard mode call gvrView.recenterHeadTracker(); - glView.post(() -> Util.castNonNull(playerControl).show()); + // TODO: If in cardboard mode call gvrView.recenterHeadTracker(). + runOnUiThread(() -> Util.castNonNull(playerControlView).show()); } }; controllerManager = new ControllerManager(this, listener); - Controller controller = controllerManager.getController(); ControllerEventListener controllerEventListener = - new ControllerEventListener(controller, pointerRenderer, glView); + new ControllerEventListener(controller, pointerRenderer, glViewGroup); controller.setEventListener(controllerEventListener); } @@ -144,7 +129,7 @@ public abstract class GvrPlayerActivity extends GvrActivity { * @param newPlayer The {@link Player} to use, or {@code null} to detach the current player. */ protected void setPlayer(@Nullable Player newPlayer) { - Assertions.checkNotNull(scene); + Assertions.checkNotNull(sceneRenderer); if (player == newPlayer) { return; } @@ -154,20 +139,20 @@ public abstract class GvrPlayerActivity extends GvrActivity { if (surface != null) { videoComponent.clearVideoSurface(surface); } - videoComponent.clearVideoFrameMetadataListener(scene); - videoComponent.clearCameraMotionListener(scene); + videoComponent.clearVideoFrameMetadataListener(sceneRenderer); + videoComponent.clearCameraMotionListener(sceneRenderer); } } player = newPlayer; if (player != null) { Player.VideoComponent videoComponent = player.getVideoComponent(); if (videoComponent != null) { - videoComponent.setVideoFrameMetadataListener(scene); - videoComponent.setCameraMotionListener(scene); + videoComponent.setVideoFrameMetadataListener(sceneRenderer); + videoComponent.setCameraMotionListener(sceneRenderer); videoComponent.setVideoSurface(surface); } } - Assertions.checkNotNull(playerControl).setPlayer(player); + Assertions.checkNotNull(playerControlView).setPlayer(player); } /** @@ -177,7 +162,19 @@ public abstract class GvrPlayerActivity extends GvrActivity { * @param stereoMode A {@link C.StereoMode} value. */ protected void setDefaultStereoMode(@C.StereoMode int stereoMode) { - Assertions.checkNotNull(scene).setDefaultStereoMode(stereoMode); + Assertions.checkNotNull(sceneRenderer).setDefaultStereoMode(stereoMode); + } + + /** + * Returns the render target scale passed to {@link GvrView#setRenderTargetScale(float)}. Since + * videos typically have fewer pixels per degree than the phone displays, the target can normally + * be lower than 1 to reduce the amount of work required to render the scene. The default value is + * 0.5. + * + * @return The render target scale passed to {@link GvrView#setRenderTargetScale(float)}. + */ + protected float getRenderTargetScale() { + return 0.5f; } @CallSuper @@ -210,12 +207,12 @@ public abstract class GvrPlayerActivity extends GvrActivity { /** Tries to exit gracefully from VR using a VR transition dialog. */ @SuppressWarnings("nullness:argument.type.incompatible") protected void exit() { - // This needs to use GVR's exit transition to avoid disorienting the user. - DaydreamApi api = DaydreamApi.create(this); - if (api != null) { - api.exitFromVr(this, EXIT_FROM_VR_REQUEST_CODE, null); - // Eventually, the Activity's onActivityResult will be called. - api.close(); + DaydreamApi daydreamApi = DaydreamApi.create(this); + if (daydreamApi != null) { + // Use Daydream's exit transition to avoid disorienting the user. This will cause + // onActivityResult to be called. + daydreamApi.exitFromVr(/* activity= */ this, EXIT_FROM_VR_REQUEST_CODE, /* intent= */ null); + daydreamApi.close(); } else { finish(); } @@ -224,16 +221,16 @@ public abstract class GvrPlayerActivity extends GvrActivity { /** Toggles PlayerControl visibility. */ @UiThread protected void togglePlayerControlVisibility() { - if (Assertions.checkNotNull(playerControl).isVisible()) { - playerControl.hide(); + if (Assertions.checkNotNull(playerControlView).isVisible()) { + playerControlView.hide(); } else { - playerControl.show(); + playerControlView.show(); } } - // Called on GL thread. private void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture) { - mainHandler.post( + // Called on the GL thread. Post to the main thread. + runOnUiThread( () -> { SurfaceTexture oldSurfaceTexture = this.surfaceTexture; Surface oldSurface = this.surface; @@ -260,18 +257,20 @@ public abstract class GvrPlayerActivity extends GvrActivity { } private class Renderer implements GvrView.StereoRenderer { - private static final float Z_NEAR = .1f; + private static final float Z_NEAR = 0.1f; private static final float Z_FAR = 100; - private final float[] viewProjectionMatrix = new float[16]; - private final SceneRenderer scene; - private final GlViewGroup glView; + private final SceneRenderer sceneRenderer; private final PointerRenderer pointerRenderer; + private final GlViewGroup glViewGroup; + private final float[] viewProjectionMatrix; - public Renderer(SceneRenderer scene, GlViewGroup glView, PointerRenderer pointerRenderer) { - this.scene = scene; - this.glView = glView; + public Renderer( + SceneRenderer sceneRenderer, PointerRenderer pointerRenderer, GlViewGroup glViewGroup) { + this.sceneRenderer = sceneRenderer; this.pointerRenderer = pointerRenderer; + this.glViewGroup = glViewGroup; + viewProjectionMatrix = new float[16]; } @Override @@ -281,9 +280,9 @@ public abstract class GvrPlayerActivity extends GvrActivity { public void onDrawEye(Eye eye) { Matrix.multiplyMM( viewProjectionMatrix, 0, eye.getPerspective(Z_NEAR, Z_FAR), 0, eye.getEyeView(), 0); - scene.drawFrame(viewProjectionMatrix, eye.getType() == Eye.Type.RIGHT); - if (glView.isVisible()) { - glView.getRenderer().draw(viewProjectionMatrix); + sceneRenderer.drawFrame(viewProjectionMatrix, eye.getType() == Eye.Type.RIGHT); + if (glViewGroup.isVisible()) { + glViewGroup.getRenderer().draw(viewProjectionMatrix); pointerRenderer.draw(viewProjectionMatrix); } } @@ -293,8 +292,8 @@ public abstract class GvrPlayerActivity extends GvrActivity { @Override public void onSurfaceCreated(EGLConfig config) { - onSurfaceTextureAvailable(scene.init()); - glView.getRenderer().init(); + onSurfaceTextureAvailable(sceneRenderer.init()); + glViewGroup.getRenderer().init(); pointerRenderer.init(); } @@ -303,9 +302,9 @@ public abstract class GvrPlayerActivity extends GvrActivity { @Override public void onRendererShutdown() { - glView.getRenderer().shutdown(); + glViewGroup.getRenderer().shutdown(); pointerRenderer.shutdown(); - scene.shutdown(); + sceneRenderer.shutdown(); } } @@ -313,16 +312,16 @@ public abstract class GvrPlayerActivity extends GvrActivity { private final Controller controller; private final PointerRenderer pointerRenderer; - private final GlViewGroup glView; + private final GlViewGroup glViewGroup; private final float[] controllerOrientationMatrix; private boolean clickButtonDown; private boolean appButtonDown; public ControllerEventListener( - Controller controller, PointerRenderer pointerRenderer, GlViewGroup glView) { + Controller controller, PointerRenderer pointerRenderer, GlViewGroup glViewGroup) { this.controller = controller; this.pointerRenderer = pointerRenderer; - this.glView = glView; + this.glViewGroup = glViewGroup; controllerOrientationMatrix = new float[16]; } @@ -330,7 +329,8 @@ public abstract class GvrPlayerActivity extends GvrActivity { @BinderThread public void onUpdate() { controller.update(); - controller.orientation.toRotationMatrix(controllerOrientationMatrix); + Orientation orientation = controller.orientation; + orientation.toRotationMatrix(controllerOrientationMatrix); pointerRenderer.setControllerOrientation(controllerOrientationMatrix); if (clickButtonDown || controller.clickButtonState) { @@ -341,18 +341,19 @@ public abstract class GvrPlayerActivity extends GvrActivity { } else { action = MotionEvent.ACTION_MOVE; } - glView.post( - () -> { - float[] angles = controller.orientation.toYawPitchRollRadians(new float[3]); - boolean clickedOnView = glView.simulateClick(action, angles[0], angles[1]); - if (action == MotionEvent.ACTION_DOWN && !clickedOnView) { - togglePlayerControlVisibility(); - } - }); + float[] yawPitchRoll = orientation.toYawPitchRollRadians(new float[3]); + runOnUiThread(() -> dispatchClick(action, yawPitchRoll[0], yawPitchRoll[1])); } else if (!appButtonDown && controller.appButtonState) { - glView.post(GvrPlayerActivity.this::togglePlayerControlVisibility); + runOnUiThread(GvrPlayerActivity.this::togglePlayerControlVisibility); } appButtonDown = controller.appButtonState; } + + private void dispatchClick(int action, float yaw, float pitch) { + boolean clickedOnView = glViewGroup.simulateClick(action, yaw, pitch); + if (action == MotionEvent.ACTION_DOWN && !clickedOnView) { + togglePlayerControlVisibility(); + } + } } } diff --git a/extensions/gvr/src/main/res/values-v21/styles.xml b/extensions/gvr/src/main/res/layout/exo_vr_ui.xml similarity index 74% rename from extensions/gvr/src/main/res/values-v21/styles.xml rename to extensions/gvr/src/main/res/layout/exo_vr_ui.xml index 276db1b42d..6863da9578 100644 --- a/extensions/gvr/src/main/res/values-v21/styles.xml +++ b/extensions/gvr/src/main/res/layout/exo_vr_ui.xml @@ -13,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - -