Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matrix scale video on TextureView Android

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

like image 893
oleg.semen Avatar asked Jul 22 '15 15:07

oleg.semen


1 Answers

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 ?

like image 76
oleg.semen Avatar answered Oct 10 '22 08:10

oleg.semen