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