Fix samplingMatrix for I420Frames converted from VideoFrame.
The conversion code was wrong because it assumed the 3x3 matrix is a XYZ-matrix when it really is XYW-matrix. We have to override the matrix for I420 frames to flip the vertically before rendering. R=magjed@webrtc.org Bug: webrtc:7760 Change-Id: I1f08c1a929bf5721706e2a902701100cf7a9c31d Reviewed-on: https://chromium-review.googlesource.com/541346 Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Cr-Commit-Position: refs/heads/master@{#18801}
This commit is contained in:
committed by
Commit Bot
parent
3aa3ea7913
commit
372e587ea8
@ -61,13 +61,7 @@ public class VideoRenderer {
|
|||||||
// top-left corner of the image, but in glTexImage2D() the first element corresponds to the
|
// top-left corner of the image, but in glTexImage2D() the first element corresponds to the
|
||||||
// bottom-left corner. This discrepancy is corrected by setting a vertical flip as sampling
|
// bottom-left corner. This discrepancy is corrected by setting a vertical flip as sampling
|
||||||
// matrix.
|
// matrix.
|
||||||
// clang-format off
|
samplingMatrix = RendererCommon.verticalFlipMatrix();
|
||||||
samplingMatrix = new float[] {
|
|
||||||
1, 0, 0, 0,
|
|
||||||
0, -1, 0, 0,
|
|
||||||
0, 0, 1, 0,
|
|
||||||
0, 1, 0, 1};
|
|
||||||
// clang-format on
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,11 +94,11 @@ public class VideoRenderer {
|
|||||||
if (rotationDegree % 90 != 0) {
|
if (rotationDegree % 90 != 0) {
|
||||||
throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree);
|
throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree);
|
||||||
}
|
}
|
||||||
this.samplingMatrix = samplingMatrix;
|
|
||||||
if (buffer instanceof VideoFrame.TextureBuffer) {
|
if (buffer instanceof VideoFrame.TextureBuffer) {
|
||||||
VideoFrame.TextureBuffer textureBuffer = (VideoFrame.TextureBuffer) buffer;
|
VideoFrame.TextureBuffer textureBuffer = (VideoFrame.TextureBuffer) buffer;
|
||||||
this.yuvFrame = false;
|
this.yuvFrame = false;
|
||||||
this.textureId = textureBuffer.getTextureId();
|
this.textureId = textureBuffer.getTextureId();
|
||||||
|
this.samplingMatrix = samplingMatrix;
|
||||||
|
|
||||||
this.yuvStrides = null;
|
this.yuvStrides = null;
|
||||||
this.yuvPlanes = null;
|
this.yuvPlanes = null;
|
||||||
@ -115,6 +109,12 @@ public class VideoRenderer {
|
|||||||
new int[] {i420Buffer.getStrideY(), i420Buffer.getStrideU(), i420Buffer.getStrideV()};
|
new int[] {i420Buffer.getStrideY(), i420Buffer.getStrideU(), i420Buffer.getStrideV()};
|
||||||
this.yuvPlanes =
|
this.yuvPlanes =
|
||||||
new ByteBuffer[] {i420Buffer.getDataY(), i420Buffer.getDataU(), i420Buffer.getDataV()};
|
new ByteBuffer[] {i420Buffer.getDataY(), i420Buffer.getDataU(), i420Buffer.getDataV()};
|
||||||
|
// The convention in WebRTC is that the first element in a ByteBuffer corresponds to the
|
||||||
|
// top-left corner of the image, but in glTexImage2D() the first element corresponds to the
|
||||||
|
// bottom-left corner. This discrepancy is corrected by multiplying the sampling matrix with
|
||||||
|
// a vertical flip matrix.
|
||||||
|
this.samplingMatrix =
|
||||||
|
RendererCommon.multiplyMatrices(samplingMatrix, RendererCommon.verticalFlipMatrix());
|
||||||
|
|
||||||
this.textureId = 0;
|
this.textureId = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,12 +43,25 @@ Matrix Matrix::fromAndroidGraphicsMatrix(JNIEnv* jni, jobject j_matrix) {
|
|||||||
jfloat* array_3x3_ptr = jni->GetFloatArrayElements(array_3x3, nullptr);
|
jfloat* array_3x3_ptr = jni->GetFloatArrayElements(array_3x3, nullptr);
|
||||||
Matrix matrix;
|
Matrix matrix;
|
||||||
memset(matrix.elem_, 0, sizeof(matrix.elem_));
|
memset(matrix.elem_, 0, sizeof(matrix.elem_));
|
||||||
for (int y = 0; y < 3; ++y) {
|
// The android.graphics.Matrix looks like this:
|
||||||
for (int x = 0; x < 3; ++x) {
|
// [x1 y1 w1]
|
||||||
matrix.elem_[y * 4 + x] = array_3x3_ptr[x + y * 3];
|
// [x2 y2 w2]
|
||||||
}
|
// [x3 y3 w3]
|
||||||
}
|
// We want to contruct a matrix that looks like this:
|
||||||
matrix.elem_[3 + 3 * 3] = 1; // Bottom-right corner should be 1.
|
// [x1 y1 0 w1]
|
||||||
|
// [x2 y2 0 w2]
|
||||||
|
// [ 0 0 1 0]
|
||||||
|
// [x3 y3 0 w3]
|
||||||
|
matrix.elem_[0 * 4 + 0] = array_3x3_ptr[0 * 3 + 0];
|
||||||
|
matrix.elem_[0 * 4 + 1] = array_3x3_ptr[0 * 3 + 1];
|
||||||
|
matrix.elem_[0 * 4 + 3] = array_3x3_ptr[0 * 3 + 2];
|
||||||
|
matrix.elem_[1 * 4 + 0] = array_3x3_ptr[1 * 3 + 0];
|
||||||
|
matrix.elem_[1 * 4 + 1] = array_3x3_ptr[1 * 3 + 1];
|
||||||
|
matrix.elem_[1 * 4 + 3] = array_3x3_ptr[1 * 3 + 2];
|
||||||
|
matrix.elem_[2 * 4 + 2] = 1; // Z-scale should be 1.
|
||||||
|
matrix.elem_[3 * 4 + 0] = array_3x3_ptr[2 * 3 + 0];
|
||||||
|
matrix.elem_[3 * 4 + 1] = array_3x3_ptr[2 * 3 + 1];
|
||||||
|
matrix.elem_[3 * 4 + 3] = array_3x3_ptr[2 * 3 + 2];
|
||||||
return matrix;
|
return matrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user