Android – Matrix scale video on TextureView Android

androidexoplayerscalevideo

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 ?

UPD: Here are screenshots:
enter image description here

Best Answer

I fixed this issue next by multiplying or dividing scale factors by viewRatio (width / height):

    if (viewRatio > videoRatio) {
        // video is higher than view
        scaleY = videoHeight / videoWidth * viewRatio;
    } else {
        //video is wider than view
        scaleX = videoWidth / videoHeight / viewRatio;
    }

But I did not get why it works like this. According to my calculations if I have, for instance, view 1080x480 and video 360x640 video should be scaled to have width x' = 1080 and height proportional. So height should be y' = 640*1080/360 (videoHeight * viewHeight / videoWidth) and x' = 1080

According to this image: enter image description here

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 ?