Add option for sensor rotation in 360 playbacks

Issue: #6761
PiperOrigin-RevId: 300715682
This commit is contained in:
andrewlewis 2020-03-13 09:04:00 +00:00 committed by Oliver Woodman
parent b2849fde3d
commit 4750785f5a
4 changed files with 59 additions and 8 deletions

View File

@ -5,6 +5,9 @@
* Text: Catch-and-log all fatal exceptions in `TextRenderer` instead of
re-throwing, allowing playback to continue even if subtitles fail
([#6885](https://github.com/google/ExoPlayer/issues/6885)).
* UI: Add an option to set whether to use the orientation sensor for rotation
in spherical playbacks
([#6761](https://github.com/google/ExoPlayer/issues/6761)).
* DASH:
* Update the manifest URI to avoid repeated HTTP redirects
([#6907](https://github.com/google/ExoPlayer/issues/6907)).

View File

@ -143,6 +143,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* <li>Corresponding method: None
* <li>Default: {@code surface_view}
* </ul>
* <li><b>{@code use_sensor_rotation}</b> - Whether to use the orientation sensor for rotation
* during spherical playbacks (if available).
* <ul>
* <li>Corresponding method: {@link #setUseSensorRotation(boolean)}
* <li>Default: {@code true}
* </ul>
* <li><b>{@code shutter_background_color}</b> - The background color of the {@code exo_shutter}
* view.
* <ul>
@ -308,6 +314,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
@Nullable private Drawable defaultArtwork;
private @ShowBuffering int showBuffering;
private boolean keepContentOnPlayerReset;
private boolean useSensorRotation;
@Nullable private ErrorMessageProvider<? super ExoPlaybackException> errorMessageProvider;
@Nullable private CharSequence customErrorMessage;
private int controllerShowTimeoutMs;
@ -367,6 +374,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
boolean controllerAutoShow = true;
boolean controllerHideDuringAds = true;
int showBuffering = SHOW_BUFFERING_NEVER;
useSensorRotation = true;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PlayerView, 0, 0);
try {
@ -390,6 +398,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
R.styleable.PlayerView_keep_content_on_player_reset, keepContentOnPlayerReset);
controllerHideDuringAds =
a.getBoolean(R.styleable.PlayerView_hide_during_ads, controllerHideDuringAds);
useSensorRotation =
a.getBoolean(R.styleable.PlayerView_use_sensor_rotation, useSensorRotation);
} finally {
a.recycle();
}
@ -422,6 +432,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
case SURFACE_TYPE_SPHERICAL_GL_SURFACE_VIEW:
SphericalGLSurfaceView sphericalGLSurfaceView = new SphericalGLSurfaceView(context);
sphericalGLSurfaceView.setSingleTapListener(componentListener);
sphericalGLSurfaceView.setUseSensorRotation(useSensorRotation);
surfaceView = sphericalGLSurfaceView;
break;
case SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW:
@ -746,6 +757,22 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
}
}
/**
* Sets whether to use the orientation sensor for rotation during spherical playbacks (if
* available)
*
* @param useSensorRotation Whether to use the orientation sensor for rotation during spherical
* playbacks.
*/
public void setUseSensorRotation(boolean useSensorRotation) {
if (this.useSensorRotation != useSensorRotation) {
this.useSensorRotation = useSensorRotation;
if (surfaceView instanceof SphericalGLSurfaceView) {
((SphericalGLSurfaceView) surfaceView).setUseSensorRotation(useSensorRotation);
}
}
}
/**
* Sets whether a buffering spinner is displayed when the player is in the buffering state. The
* buffering spinner is not displayed by default.

View File

@ -72,6 +72,9 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
@Nullable private SurfaceTexture surfaceTexture;
@Nullable private Surface surface;
@Nullable private Player.VideoComponent videoComponent;
private boolean useSensorRotation;
private boolean isStarted;
private boolean isOrientationListenerRegistered;
public SphericalGLSurfaceView(Context context) {
this(context, null);
@ -104,6 +107,7 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = Assertions.checkNotNull(windowManager).getDefaultDisplay();
orientationListener = new OrientationListener(display, touchTracker, renderer);
useSensorRotation = true;
setEGLContextClientVersion(2);
setRenderer(renderer);
@ -145,20 +149,23 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
touchTracker.setSingleTapListener(listener);
}
/** Sets whether to use the orientation sensor for rotation (if available). */
public void setUseSensorRotation(boolean useSensorRotation) {
this.useSensorRotation = useSensorRotation;
updateOrientationListenerRegistration();
}
@Override
public void onResume() {
super.onResume();
if (orientationSensor != null) {
sensorManager.registerListener(
orientationListener, orientationSensor, SensorManager.SENSOR_DELAY_FASTEST);
}
isStarted = true;
updateOrientationListenerRegistration();
}
@Override
public void onPause() {
if (orientationSensor != null) {
sensorManager.unregisterListener(orientationListener);
}
isStarted = false;
updateOrientationListenerRegistration();
super.onPause();
}
@ -181,6 +188,20 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
});
}
private void updateOrientationListenerRegistration() {
boolean enabled = useSensorRotation && isStarted;
if (orientationSensor == null || enabled == isOrientationListenerRegistered) {
return;
}
if (enabled) {
sensorManager.registerListener(
orientationListener, orientationSensor, SensorManager.SENSOR_DELAY_FASTEST);
} else {
sensorManager.unregisterListener(orientationListener);
}
isOrientationListenerRegistered = enabled;
}
// Called on GL thread.
private void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture) {
mainHandler.post(

View File

@ -77,8 +77,8 @@
<enum name="always" value="2"/>
</attr>
<attr name="keep_content_on_player_reset" format="boolean"/>
<attr name="use_sensor_rotation" format="boolean"/>
<attr name="player_layout_id" format="reference"/>
<attr name="surface_type"/>
<!-- AspectRatioFrameLayout attributes -->
<attr name="resize_mode"/>