I'm trying to play video with ExoPlaye
on TextureView
. In order to scale and crop video to fit view I use matrix. My custom view extends `TextureView' Here is my code:
@Override
public void onVideoSizeChanged(int width, int height, float pixelWidthHeightRatio) {
updateTextureViewSize(width, height);
Log.v("EXO", "onVideoSizeChanged() " + width + "x" + height);
}
private void updateTextureViewSize(float videoWidth, float videoHeight) {
float viewWidth = getWidth();
float viewHeight = getHeight();
float scaleX = 1.0f;
float scaleY = 1.0f;
float viewRatio = viewWidth / viewHeight;
float videoRatio = videoWidth / videoHeight;
if (viewRatio > videoRatio) {
// video is higher than view
scaleY = videoHeight / videoWidth;
} else {
//video is wider than view
scaleX = videoWidth / videoHeight;
}
Matrix matrix = new Matrix();
matrix.setScale(scaleX, scaleY, viewWidth / 2, viewHeight / 2);
setTransform(matrix);
}
I had a rectangular views and it worked perfectly. But now views have 2 states: expanded (the old ones that are still rectangular) and collapsed (have smaller height.
So now video is stretched vertically in those collapsed views.
For instance I have view 1080x480
and video 360x640
but it looks like video is scaled and cropped to 1080x1080
and than stretched to 1080x480
.
What am I doing wrong here ?
Best Answer
I fixed this issue next by multiplying or dividing scale factors by
viewRatio
(width / height
):But I did not get why it works like this. According to my calculations if I have, for instance, view
1080x480
and video360x640
video should be scaled to have widthx' = 1080
and height proportional. So height should bey' = 640*1080/360
(videoHeight * viewHeight / videoWidth
) andx' = 1080
According to this image:
sx * 360 = 1080
=>sx = 1080 / 360
sy * 640 = 640*1080/360
=>sy = 1080 / 360
Looks like it makes sense. If we need save proportions width and height should be multiplied by the same factor. But it does not work this way. Where is a mistake ? Is there any good doc on this ?