7

我正在尝试使用ExoPlayeon播放视频TextureView。为了缩放和裁剪视频以适合视图,我使用矩阵。我的自定义视图扩展了“TextureView”这是我的代码:

@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);
}

我有一个矩形视图,效果很好。但是现在视图有两种状态:展开(仍然是矩形的旧视图)和折叠(高度更小。

所以现在视频在那些折叠的视图中垂直拉伸。

例如,我有视图1080x480和视频360x640,但看起来视频被缩放并裁剪到1080x1080而不是拉伸到1080x480.

我在这里做错了什么?

UPD:这里是截图: 在此处输入图像描述

4

2 回答 2

9

接下来我通过将比例因子乘以或除以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;
    }

但我不明白为什么它会这样工作。根据我的计算,如果我有,例如,视图1080x480和视频360x640视频应该缩放为宽度x' = 1080和高度成比例。所以高度应该是y' = 640*1080/360( videoHeight * viewHeight / videoWidth) 并且x' = 1080

根据这张图片: 在此处输入图像描述

sx * 360 = 1080=>sx = 1080 / 360

sy * 640 = 640*1080/360=>sy = 1080 / 360

看起来很有道理。如果我们需要保存比例宽度和高度应该乘以相同的因子。但它不是这样工作的。哪里出错了?这有什么好的文档吗?

于 2015-07-23T08:39:36.570 回答
2

检查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;
}
于 2015-08-19T10:40:54.647 回答