mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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:
parent
373935aeb6
commit
5364962dca
2 changed files with 73 additions and 4 deletions
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
### dev-v2 (not yet released) ###
|
### 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:
|
* Player interface:
|
||||||
* Add optional parameter to `stop` to reset the player when stopping.
|
* Add optional parameter to `stop` to reset the player when stopping.
|
||||||
* Add a reason to `EventListener.onTimelineChanged` to distinguish between
|
* Add a reason to `EventListener.onTimelineChanged` to distinguish between
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.Matrix;
|
||||||
|
import android.graphics.RectF;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
@ -224,6 +226,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||||
private boolean controllerAutoShow;
|
private boolean controllerAutoShow;
|
||||||
private boolean controllerHideDuringAds;
|
private boolean controllerHideDuringAds;
|
||||||
private boolean controllerHideOnTouch;
|
private boolean controllerHideOnTouch;
|
||||||
|
private int textureViewRotation;
|
||||||
|
|
||||||
public SimpleExoPlayerView(Context context) {
|
public SimpleExoPlayerView(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
|
|
@ -920,6 +923,31 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||||
aspectRatioFrame.setResizeMode(resizeMode);
|
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")
|
@SuppressLint("InlinedApi")
|
||||||
private boolean isDpadKey(int keyCode) {
|
private boolean isDpadKey(int keyCode) {
|
||||||
return keyCode == KeyEvent.KEYCODE_DPAD_UP
|
return keyCode == KeyEvent.KEYCODE_DPAD_UP
|
||||||
|
|
@ -934,7 +962,7 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class ComponentListener extends Player.DefaultEventListener
|
private final class ComponentListener extends Player.DefaultEventListener
|
||||||
implements TextOutput, SimpleExoPlayer.VideoListener {
|
implements TextOutput, SimpleExoPlayer.VideoListener, OnLayoutChangeListener {
|
||||||
|
|
||||||
// TextOutput implementation
|
// TextOutput implementation
|
||||||
|
|
||||||
|
|
@ -950,10 +978,32 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||||
@Override
|
@Override
|
||||||
public void onVideoSizeChanged(
|
public void onVideoSizeChanged(
|
||||||
int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
||||||
if (contentFrame != null) {
|
if (contentFrame == null) {
|
||||||
float aspectRatio = height == 0 ? 1 : (width * pixelWidthHeightRatio) / height;
|
return;
|
||||||
contentFrame.setAspectRatio(aspectRatio);
|
|
||||||
}
|
}
|
||||||
|
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
|
@Override
|
||||||
|
|
@ -985,5 +1035,21 @@ public final class SimpleExoPlayerView extends FrameLayout {
|
||||||
hideController();
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue