Make GvrPlayerActivity call its subclass to instantiate a player

It's more explicit and simpler than having the subclass call up into
the activity.

PiperOrigin-RevId: 274881350
This commit is contained in:
olly 2019-10-15 21:57:45 +01:00 committed by Oliver Woodman
parent a2900992c3
commit 7dede17d97
2 changed files with 78 additions and 136 deletions

View File

@ -36,7 +36,6 @@ import com.google.android.exoplayer2.source.smoothstreaming.SsMediaSource;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo; import com.google.android.exoplayer2.trackselection.MappingTrackSelector.MappedTrackInfo;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray; import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory; import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory;
import com.google.android.exoplayer2.util.EventLogger; import com.google.android.exoplayer2.util.EventLogger;
@ -52,24 +51,16 @@ public class PlayerActivity extends GvrPlayerActivity {
public static final String SPHERICAL_STEREO_MODE_TOP_BOTTOM = "top_bottom"; public static final String SPHERICAL_STEREO_MODE_TOP_BOTTOM = "top_bottom";
public static final String SPHERICAL_STEREO_MODE_LEFT_RIGHT = "left_right"; public static final String SPHERICAL_STEREO_MODE_LEFT_RIGHT = "left_right";
private DataSource.Factory dataSourceFactory;
private SimpleExoPlayer player; private SimpleExoPlayer player;
private MediaSource mediaSource;
private DefaultTrackSelector trackSelector; private DefaultTrackSelector trackSelector;
private TrackGroupArray lastSeenTrackGroupArray; private TrackGroupArray lastSeenTrackGroupArray;
private boolean startAutoPlay; private boolean startAutoPlay;
private int startWindow; private int startWindow;
private long startPosition; private long startPosition;
// Activity lifecycle
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
String userAgent = Util.getUserAgent(this, "ExoPlayerDemo");
dataSourceFactory =
new DefaultDataSourceFactory(this, new DefaultHttpDataSourceFactory(userAgent));
String sphericalStereoMode = getIntent().getStringExtra(SPHERICAL_STEREO_MODE_EXTRA); String sphericalStereoMode = getIntent().getStringExtra(SPHERICAL_STEREO_MODE_EXTRA);
if (sphericalStereoMode != null) { if (sphericalStereoMode != null) {
@ -92,56 +83,34 @@ public class PlayerActivity extends GvrPlayerActivity {
} }
@Override @Override
public void onResume() { protected Player createPlayer() {
super.onResume(); Intent intent = getIntent();
if (Util.SDK_INT <= 23 || player == null) { Uri uri = intent.getData();
initializePlayer(); DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(this);
}
}
@Override trackSelector = new DefaultTrackSelector(/* context= */ this);
public void onPause() { lastSeenTrackGroupArray = null;
super.onPause();
if (Util.SDK_INT <= 23) {
releasePlayer();
}
}
// Internal methods player =
new SimpleExoPlayer.Builder(/* context= */ this, renderersFactory)
private void initializePlayer() { .setTrackSelector(trackSelector)
if (player == null) { .build();
Intent intent = getIntent(); player.addListener(new PlayerEventListener());
Uri uri = intent.getData(); player.setPlayWhenReady(startAutoPlay);
if (!Util.checkCleartextTrafficPermitted(uri)) { player.addAnalyticsListener(new EventLogger(trackSelector));
showToast(R.string.error_cleartext_not_permitted); MediaSource mediaSource = buildMediaSource(uri, intent.getStringExtra(EXTENSION_EXTRA));
return;
}
DefaultRenderersFactory renderersFactory = new DefaultRenderersFactory(this);
trackSelector = new DefaultTrackSelector(/* context= */ this);
lastSeenTrackGroupArray = null;
player =
new SimpleExoPlayer.Builder(/* context= */ this, renderersFactory)
.setTrackSelector(trackSelector)
.build();
player.addListener(new PlayerEventListener());
player.setPlayWhenReady(startAutoPlay);
player.addAnalyticsListener(new EventLogger(trackSelector));
setPlayer(player);
mediaSource = buildMediaSource(uri, intent.getStringExtra(EXTENSION_EXTRA));
}
boolean haveStartPosition = startWindow != C.INDEX_UNSET; boolean haveStartPosition = startWindow != C.INDEX_UNSET;
if (haveStartPosition) { if (haveStartPosition) {
player.seekTo(startWindow, startPosition); player.seekTo(startWindow, startPosition);
} }
player.prepare(mediaSource, !haveStartPosition, false); player.prepare(mediaSource, !haveStartPosition, false);
return player;
} }
private MediaSource buildMediaSource(Uri uri, @Nullable String overrideExtension) { private MediaSource buildMediaSource(Uri uri, @Nullable String overrideExtension) {
String userAgent = Util.getUserAgent(this, "ExoPlayerVrDemo");
DefaultDataSourceFactory dataSourceFactory =
new DefaultDataSourceFactory(this, new DefaultHttpDataSourceFactory(userAgent));
@ContentType int type = Util.inferContentType(uri, overrideExtension); @ContentType int type = Util.inferContentType(uri, overrideExtension);
switch (type) { switch (type) {
case C.TYPE_DASH: case C.TYPE_DASH:
@ -157,16 +126,6 @@ public class PlayerActivity extends GvrPlayerActivity {
} }
} }
private void releasePlayer() {
if (player != null) {
updateStartPosition();
player.release();
player = null;
mediaSource = null;
trackSelector = null;
}
}
private void updateStartPosition() { private void updateStartPosition() {
if (player != null) { if (player != null) {
startAutoPlay = player.getPlayWhenReady(); startAutoPlay = player.getPlayWhenReady();

View File

@ -34,7 +34,6 @@ import com.google.android.exoplayer2.ui.spherical.GlViewGroup;
import com.google.android.exoplayer2.ui.spherical.PointerRenderer; import com.google.android.exoplayer2.ui.spherical.PointerRenderer;
import com.google.android.exoplayer2.ui.spherical.SceneRenderer; import com.google.android.exoplayer2.ui.spherical.SceneRenderer;
import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;
import com.google.vr.ndk.base.DaydreamApi; import com.google.vr.ndk.base.DaydreamApi;
import com.google.vr.sdk.base.AndroidCompat; import com.google.vr.sdk.base.AndroidCompat;
import com.google.vr.sdk.base.Eye; import com.google.vr.sdk.base.Eye;
@ -48,10 +47,7 @@ import com.google.vr.sdk.controller.Orientation;
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLConfig;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** /** Base activity for VR 360 video playback. */
* Base activity for VR 360 video playback. Before starting the video playback a player needs to be
* set using {@link #setPlayer(Player)}.
*/
public abstract class GvrPlayerActivity extends GvrActivity { public abstract class GvrPlayerActivity extends GvrActivity {
private static final int EXIT_FROM_VR_REQUEST_CODE = 42; private static final int EXIT_FROM_VR_REQUEST_CODE = 42;
@ -63,6 +59,7 @@ public abstract class GvrPlayerActivity extends GvrActivity {
private @MonotonicNonNull SceneRenderer sceneRenderer; private @MonotonicNonNull SceneRenderer sceneRenderer;
private @MonotonicNonNull PlayerControlView playerControlView; private @MonotonicNonNull PlayerControlView playerControlView;
@CallSuper
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -103,80 +100,14 @@ public abstract class GvrPlayerActivity extends GvrActivity {
// using Daydream's exit transition. // using Daydream's exit transition.
gvrView.setOnCloseButtonListener(this::finish); gvrView.setOnCloseButtonListener(this::finish);
ControllerManager.EventListener listener = controllerManager =
new ControllerManager.EventListener() { new ControllerManager(/* context= */ this, new ControllerManagerEventListener());
@Override
public void onApiStatusChanged(int status) {
// Do nothing.
}
@Override
public void onRecentered() {
// TODO: If in cardboard mode call gvrView.recenterHeadTracker().
runOnUiThread(() -> Util.castNonNull(playerControlView).show());
}
};
controllerManager = new ControllerManager(this, listener);
Controller controller = controllerManager.getController(); Controller controller = controllerManager.getController();
ControllerEventListener controllerEventListener = ControllerEventListener controllerEventListener =
new ControllerEventListener(controller, pointerRenderer, glViewGroup); new ControllerEventListener(controller, pointerRenderer, glViewGroup);
controller.setEventListener(controllerEventListener); controller.setEventListener(controllerEventListener);
} }
/**
* Sets the {@link Player} to use.
*
* @param newPlayer The {@link Player} to use, or {@code null} to detach the current player.
*/
protected void setPlayer(@Nullable Player newPlayer) {
Assertions.checkNotNull(sceneRenderer);
if (player == newPlayer) {
return;
}
if (player != null) {
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
if (surface != null) {
videoComponent.clearVideoSurface(surface);
}
videoComponent.clearVideoFrameMetadataListener(sceneRenderer);
videoComponent.clearCameraMotionListener(sceneRenderer);
}
}
player = newPlayer;
if (player != null) {
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.setVideoFrameMetadataListener(sceneRenderer);
videoComponent.setCameraMotionListener(sceneRenderer);
videoComponent.setVideoSurface(surface);
}
}
Assertions.checkNotNull(playerControlView).setPlayer(player);
}
/**
* Sets the default stereo mode. If the played video doesn't contain a stereo mode the default one
* is used.
*
* @param stereoMode A {@link C.StereoMode} value.
*/
protected void setDefaultStereoMode(@C.StereoMode int 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 @CallSuper
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent unused) { protected void onActivityResult(int requestCode, int resultCode, Intent unused) {
@ -185,25 +116,63 @@ public abstract class GvrPlayerActivity extends GvrActivity {
} }
} }
@CallSuper
@Override @Override
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
Util.castNonNull(controllerManager).start(); player = createPlayer();
Player.VideoComponent videoComponent = player.getVideoComponent();
if (videoComponent != null) {
videoComponent.setVideoFrameMetadataListener(Assertions.checkNotNull(sceneRenderer));
videoComponent.setCameraMotionListener(sceneRenderer);
videoComponent.setVideoSurface(surface);
}
Assertions.checkNotNull(playerControlView).setPlayer(player);
Assertions.checkNotNull(controllerManager).start();
} }
@CallSuper
@Override @Override
protected void onPause() { protected void onPause() {
Util.castNonNull(controllerManager).stop(); Assertions.checkNotNull(controllerManager).stop();
Assertions.checkNotNull(playerControlView).setPlayer(null);
Assertions.checkNotNull(player).release();
player = null;
super.onPause(); super.onPause();
} }
@CallSuper
@Override @Override
protected void onDestroy() { protected void onDestroy() {
setPlayer(null);
releaseSurface(surfaceTexture, surface); releaseSurface(surfaceTexture, surface);
super.onDestroy(); super.onDestroy();
} }
/**
* Called by {@link #onCreate(Bundle)} to get the render target scale value that will be 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 value that will be passed to {@link
* GvrView#setRenderTargetScale(float)}.
*/
protected float getRenderTargetScale() {
return 0.5f;
}
/** Called by {@link #onResume()} to create a player instance for this activity to use. */
protected abstract Player createPlayer();
/**
* Sets the stereo mode that will be used for video content that does not specify its own mode.
*
* @param stereoMode The default {@link C.StereoMode}.
*/
protected void setDefaultStereoMode(@C.StereoMode int stereoMode) {
Assertions.checkNotNull(sceneRenderer).setDefaultStereoMode(stereoMode);
}
/** Tries to exit gracefully from VR using a VR transition dialog. */ /** Tries to exit gracefully from VR using a VR transition dialog. */
@SuppressWarnings("nullness:argument.type.incompatible") @SuppressWarnings("nullness:argument.type.incompatible")
protected void exit() { protected void exit() {
@ -211,7 +180,7 @@ public abstract class GvrPlayerActivity extends GvrActivity {
if (daydreamApi != null) { if (daydreamApi != null) {
// Use Daydream's exit transition to avoid disorienting the user. This will cause // Use Daydream's exit transition to avoid disorienting the user. This will cause
// onActivityResult to be called. // onActivityResult to be called.
daydreamApi.exitFromVr(/* activity= */ this, EXIT_FROM_VR_REQUEST_CODE, /* intent= */ null); daydreamApi.exitFromVr(/* activity= */ this, EXIT_FROM_VR_REQUEST_CODE, /* data= */ null);
daydreamApi.close(); daydreamApi.close();
} else { } else {
finish(); finish();
@ -356,4 +325,18 @@ public abstract class GvrPlayerActivity extends GvrActivity {
} }
} }
} }
private final class ControllerManagerEventListener implements ControllerManager.EventListener {
@Override
public void onApiStatusChanged(int status) {
// Do nothing.
}
@Override
public void onRecentered() {
// TODO: If in cardboard mode call gvrView.recenterHeadTracker().
runOnUiThread(() -> Assertions.checkNotNull(playerControlView).show());
}
}
} }