From 372e587ea8886c2f1c386d620d32e58e356ed6fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sami=20Kalliom=C3=A4ki?= Date: Tue, 27 Jun 2017 17:00:21 +0200 Subject: [PATCH] Fix samplingMatrix for I420Frames converted from VideoFrame. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Commit-Queue: Sami Kalliomäki Cr-Commit-Position: refs/heads/master@{#18801} --- .../android/api/org/webrtc/VideoRenderer.java | 16 ++++++------ .../sdk/android/src/jni/native_handle_impl.cc | 25 ++++++++++++++----- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/webrtc/sdk/android/api/org/webrtc/VideoRenderer.java b/webrtc/sdk/android/api/org/webrtc/VideoRenderer.java index 9dde095242..0825b7408b 100644 --- a/webrtc/sdk/android/api/org/webrtc/VideoRenderer.java +++ b/webrtc/sdk/android/api/org/webrtc/VideoRenderer.java @@ -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; } diff --git a/webrtc/sdk/android/src/jni/native_handle_impl.cc b/webrtc/sdk/android/src/jni/native_handle_impl.cc index 907c90e092..ae4de0b3bc 100644 --- a/webrtc/sdk/android/src/jni/native_handle_impl.cc +++ b/webrtc/sdk/android/src/jni/native_handle_impl.cc @@ -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; }