Search code examples
androidvideoscaleexoplayer

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


Solution

  • check updateTextureViewSize :

    /**
     * Set the display options
     *
     * @param layout <ul>
     *               <li>{@link #VIDEO_LAYOUT_ORIGIN}
     *               <li>{@link #VIDEO_LAYOUT_SCALE}
     *               <li>{@link #VIDEO_LAYOUT_STRETCH}
     *               <li>{@link #VIDEO_LAYOUT_ZOOM}
     *               </ul>
     */
    public void updateTextureViewSize(int layout,float videoWidth, float videoHeight) {
        RelativeLayout.LayoutParams lp = (android.widget.RelativeLayout.LayoutParams) getLayoutParams();
        DisplayMetrics disp = m_Context.getResources().getDisplayMetrics();
        int windowWidth = disp.widthPixels, windowHeight = disp.heightPixels;
        float windowRatio = windowWidth / (float) windowHeight;
        float videoRatio = (float) videoWidth / (float) videoHeight;
        m_iSurfaceHeight = videoHeight;
        m_iSurfaceWidth = videoWidth;
        if (VIDEO_LAYOUT_ORIGIN == layout && m_iSurfaceWidth < windowWidth && m_iSurfaceHeight < windowHeight) {
            lp.width = (int) (m_iSurfaceHeight * videoRatio);
            lp.height = m_iSurfaceHeight;
        } else if (layout == VIDEO_LAYOUT_ZOOM) {
            lp.width = windowRatio > videoRatio ? windowWidth : (int) (videoRatio * windowHeight);
            lp.height = windowRatio < videoRatio ? windowHeight : (int) (windowWidth / videoRatio);
        } else {
            boolean full = layout == VIDEO_LAYOUT_STRETCH;
            lp.width = (full || windowRatio < videoRatio) ? windowWidth : (int) (videoRatio * windowHeight);
            lp.height = (full || windowRatio > videoRatio) ? windowHeight : (int) (windowWidth / videoRatio);
            lp.leftMargin = (disp.widthPixels - lp.width) / 2;
            lp.topMargin = (disp.heightPixels - lp.height) / 2;
        }
    
        lp.leftMargin = (disp.widthPixels - lp.width) / 2;
        lp.topMargin = (disp.heightPixels - lp.height) / 2;
    
        getHolder().setFixedSize(m_iSurfaceWidth, m_iSurfaceHeight);
    
        setLayoutParams(lp);
    
        m_iVideoLayout = layout;
    }