Automatically apply rotation for TextureView in SimpleExoPlayer.

If SimpleExoPlayer is using TextView as output, we can handle video rotation by
automatically applying a matrix transformation to the TextureView when we have
this information available from the video (from video's metadata).

GitHub: #91

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=180925571
This commit is contained in:
hoangtc 2018-01-05 07:35:28 -08:00 committed by Oliver Woodman
parent 373935aeb6
commit 5364962dca
2 changed files with 73 additions and 4 deletions

View File

@ -2,6 +2,9 @@
### dev-v2 (not yet released) ###
* SimpleExoPlayerView: Automatically apply video rotation if
`SimpleExoPlayerView` is configured to use `TextureView`
([#91](https://github.com/google/ExoPlayer/issues/91)).
* Player interface:
* Add optional parameter to `stop` to reset the player when stopping.
* Add a reason to `EventListener.onTimelineChanged` to distinguish between

View File

@ -22,6 +22,8 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
@ -224,6 +226,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
private boolean controllerAutoShow;
private boolean controllerHideDuringAds;
private boolean controllerHideOnTouch;
private int textureViewRotation;
public SimpleExoPlayerView(Context context) {
this(context, null);
@ -920,6 +923,31 @@ public final class SimpleExoPlayerView extends FrameLayout {
aspectRatioFrame.setResizeMode(resizeMode);
}
/** Applies a texture rotation to a {@link TextureView}. */
private static void applyTextureViewRotation(TextureView textureView, int textureViewRotation) {
float textureViewWidth = textureView.getWidth();
float textureViewHeight = textureView.getHeight();
if (textureViewWidth == 0 || textureViewHeight == 0 || textureViewRotation == 0) {
textureView.setTransform(null);
} else {
Matrix transformMatrix = new Matrix();
float pivotX = textureViewWidth / 2;
float pivotY = textureViewHeight / 2;
transformMatrix.postRotate(textureViewRotation, pivotX, pivotY);
// After rotation, scale the rotated texture to fit the TextureView size.
RectF originalTextureRect = new RectF(0, 0, textureViewWidth, textureViewHeight);
RectF rotatedTextureRect = new RectF();
transformMatrix.mapRect(rotatedTextureRect, originalTextureRect);
transformMatrix.postScale(
textureViewWidth / rotatedTextureRect.width(),
textureViewHeight / rotatedTextureRect.height(),
pivotX,
pivotY);
textureView.setTransform(transformMatrix);
}
}
@SuppressLint("InlinedApi")
private boolean isDpadKey(int keyCode) {
return keyCode == KeyEvent.KEYCODE_DPAD_UP
@ -934,7 +962,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
}
private final class ComponentListener extends Player.DefaultEventListener
implements TextOutput, SimpleExoPlayer.VideoListener {
implements TextOutput, SimpleExoPlayer.VideoListener, OnLayoutChangeListener {
// TextOutput implementation
@ -950,10 +978,32 @@ public final class SimpleExoPlayerView extends FrameLayout {
@Override
public void onVideoSizeChanged(
int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
if (contentFrame != null) {
float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
contentFrame.setAspectRatio(aspectRatio);
if (contentFrame == null) {
return;
}
float videoAspectRatio =
(height == 0 || width == 0) ? 1 : (width * pixelWidthHeightRatio) / height;
if (surfaceView instanceof TextureView) {
// Try to apply rotation transformation when our surface is a TextureView.
if (unappliedRotationDegrees == 90 || unappliedRotationDegrees == 270) {
// We will apply a rotation 90/270 degree to the output texture of the TextureView.
// In this case, the output video's width and height will be swapped.
videoAspectRatio = 1 / videoAspectRatio;
}
if (textureViewRotation != 0) {
surfaceView.removeOnLayoutChangeListener(this);
}
textureViewRotation = unappliedRotationDegrees;
if (textureViewRotation != 0) {
// The texture view's dimensions might be changed after layout step.
// So add an OnLayoutChangeListener to apply rotation after layout step.
surfaceView.addOnLayoutChangeListener(this);
}
applyTextureViewRotation((TextureView) surfaceView, textureViewRotation);
}
contentFrame.setAspectRatio(videoAspectRatio);
}
@Override
@ -985,5 +1035,21 @@ public final class SimpleExoPlayerView extends FrameLayout {
hideController();
}
}
// OnLayoutChangeListener implementation
@Override
public void onLayoutChange(
View view,
int left,
int top,
int right,
int bottom,
int oldLeft,
int oldTop,
int oldRight,
int oldBottom) {
applyTextureViewRotation((TextureView) view, textureViewRotation);
}
}
}