TextureView 上的矩阵比例视频 Android
Matrix scale video on TextureView Android
我正尝试在 TextureView
上使用 ExoPlaye
播放视频。为了缩放和裁剪视频以适合视图,我使用矩阵。我的自定义视图扩展了“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:以下是屏幕截图:
接下来我通过将比例因子乘以或除以 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
看起来很有道理。如果我们需要保存比例,宽度和高度应该乘以相同的因子。但它不是这样工作的。哪里出错了?有什么好的文档吗?
检查 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;
}
我正尝试在 TextureView
上使用 ExoPlaye
播放视频。为了缩放和裁剪视频以适合视图,我使用矩阵。我的自定义视图扩展了“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:以下是屏幕截图:
接下来我通过将比例因子乘以或除以 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
看起来很有道理。如果我们需要保存比例,宽度和高度应该乘以相同的因子。但它不是这样工作的。哪里出错了?有什么好的文档吗?
检查 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;
}