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:
Sami Kalliomäki
2017-06-27 17:00:21 +02:00
committed by Commit Bot
parent 3aa3ea7913
commit 372e587ea8
2 changed files with 27 additions and 14 deletions

View File

@ -61,13 +61,7 @@ public class VideoRenderer {
// 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
// matrix.
// clang-format off
samplingMatrix = new float[] {
1, 0, 0, 0,
0, -1, 0, 0,
0, 0, 1, 0,
0, 1, 0, 1};
// clang-format on
samplingMatrix = RendererCommon.verticalFlipMatrix();
}
/**
@ -100,11 +94,11 @@ public class VideoRenderer {
if (rotationDegree % 90 != 0) {
throw new IllegalArgumentException("Rotation degree not multiple of 90: " + rotationDegree);
}
this.samplingMatrix = samplingMatrix;
if (buffer instanceof VideoFrame.TextureBuffer) {
VideoFrame.TextureBuffer textureBuffer = (VideoFrame.TextureBuffer) buffer;
this.yuvFrame = false;
this.textureId = textureBuffer.getTextureId();
this.samplingMatrix = samplingMatrix;
this.yuvStrides = null;
this.yuvPlanes = null;
@ -115,6 +109,12 @@ public class VideoRenderer {
new int[] {i420Buffer.getStrideY(), i420Buffer.getStrideU(), i420Buffer.getStrideV()};
this.yuvPlanes =
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;
}

View File

@ -43,12 +43,25 @@ Matrix Matrix::fromAndroidGraphicsMatrix(JNIEnv* jni, jobject j_matrix) {
jfloat* array_3x3_ptr = jni->GetFloatArrayElements(array_3x3, nullptr);
Matrix matrix;
memset(matrix.elem_, 0, sizeof(matrix.elem_));
for (int y = 0; y < 3; ++y) {
for (int x = 0; x < 3; ++x) {
matrix.elem_[y * 4 + x] = array_3x3_ptr[x + y * 3];
}
}
matrix.elem_[3 + 3 * 3] = 1; // Bottom-right corner should be 1.
// The android.graphics.Matrix looks like this:
// [x1 y1 w1]
// [x2 y2 w2]
// [x3 y3 w3]
// We want to contruct a matrix that looks like this:
// [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;
}