diff --git a/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java b/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java
index c377379118..c19b3b7b3b 100644
--- a/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java
+++ b/libraries/effect/src/main/java/androidx/media3/effect/MatrixTransformationProcessor.java
@@ -100,11 +100,18 @@ import java.util.List;
* for the most recent frame.
*/
private final float[][] transformationMatrixCache;
+ /** The RGB matrices provided by the {@link RgbMatrix RgbMatrices} for the most recent frame. */
+ private final float[][] rgbMatrixCache;
/**
* The product of the {@link #transformationMatrixCache} for the most recent frame, to be applied
* in the vertex shader.
*/
- private final float[] compositeTransformationMatrix;
+ private final float[] compositeTransformationMatrixArray;
+ /**
+ * The product of the {@link #rgbMatrixCache} for the most recent frame, to be applied in the
+ * fragment shader.
+ */
+ private final float[] compositeRgbMatrixArray;
/** Matrix for storing an intermediate calculation result. */
private final float[] tempResultMatrix;
@@ -112,9 +119,9 @@ import java.util.List;
* A polygon in the input space chosen such that no additional clipping is needed to keep vertices
* inside the NDC range when applying each of the {@link #matrixTransformations}.
*
- *
This means that this polygon and {@link #compositeTransformationMatrix} can be used instead
- * of applying each of the {@link #matrixTransformations} to {@link #NDC_SQUARE} in separate
- * shaders.
+ *
This means that this polygon and {@link #compositeTransformationMatrixArray} can be used
+ * instead of applying each of the {@link #matrixTransformations} to {@link #NDC_SQUARE} in
+ * separate shaders.
*/
private ImmutableList visiblePolygon;
@@ -345,8 +352,11 @@ import java.util.List;
this.useHdr = useHdr;
transformationMatrixCache = new float[matrixTransformations.size()][16];
- compositeTransformationMatrix = new float[16];
- Matrix.setIdentityM(compositeTransformationMatrix, /* smOffset= */ 0);
+ rgbMatrixCache = new float[rgbMatrices.size()][16];
+ compositeTransformationMatrixArray = new float[16];
+ Matrix.setIdentityM(compositeTransformationMatrixArray, /* smOffset= */ 0);
+ compositeRgbMatrixArray = new float[16];
+ Matrix.setIdentityM(compositeRgbMatrixArray, /* smOffset= */ 0);
tempResultMatrix = new float[16];
visiblePolygon = NDC_SQUARE;
}
@@ -380,17 +390,17 @@ import java.util.List;
@Override
public void drawFrame(int inputTexId, long presentationTimeUs) throws FrameProcessingException {
+ updateCompositeRgbaMatrixArray(presentationTimeUs);
updateCompositeTransformationMatrixAndVisiblePolygon(presentationTimeUs);
if (visiblePolygon.size() < 3) {
return; // Need at least three visible vertices for a triangle.
}
- float[] compositeRgbMatrix =
- createCompositeRgbaMatrixArray(rgbMatrices, useHdr, presentationTimeUs);
+
try {
glProgram.use();
glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* texUnitIndex= */ 0);
- glProgram.setFloatsUniform("uTransformationMatrix", compositeTransformationMatrix);
- glProgram.setFloatsUniform("uRgbMatrix", compositeRgbMatrix);
+ glProgram.setFloatsUniform("uTransformationMatrix", compositeTransformationMatrixArray);
+ glProgram.setFloatsUniform("uRgbMatrix", compositeRgbMatrixArray);
glProgram.setBufferAttribute(
"aFramePosition",
GlUtil.createVertexBuffer(visiblePolygon),
@@ -415,17 +425,23 @@ import java.util.List;
}
/**
- * Updates {@link #compositeTransformationMatrix} and {@link #visiblePolygon} based on the given
- * frame timestamp.
+ * Updates {@link #compositeTransformationMatrixArray} and {@link #visiblePolygon} based on the
+ * given frame timestamp.
*/
private void updateCompositeTransformationMatrixAndVisiblePolygon(long presentationTimeUs) {
- if (!updateTransformationMatrixCache(presentationTimeUs)) {
+ float[][] matricesAtPresentationTime = new float[matrixTransformations.size()][16];
+ for (int i = 0; i < matrixTransformations.size(); i++) {
+ matricesAtPresentationTime[i] =
+ matrixTransformations.get(i).getGlMatrixArray(presentationTimeUs);
+ }
+
+ if (!updateMatrixCache(transformationMatrixCache, matricesAtPresentationTime)) {
return;
}
// Compute the compositeTransformationMatrix and transform and clip the visiblePolygon for each
// MatrixTransformation's matrix.
- Matrix.setIdentityM(compositeTransformationMatrix, /* smOffset= */ 0);
+ Matrix.setIdentityM(compositeTransformationMatrixArray, /* smOffset= */ 0);
visiblePolygon = NDC_SQUARE;
for (float[] transformationMatrix : transformationMatrixCache) {
Matrix.multiplyMM(
@@ -433,12 +449,12 @@ import java.util.List;
/* resultOffset= */ 0,
/* lhs= */ transformationMatrix,
/* lhsOffset= */ 0,
- /* rhs= */ compositeTransformationMatrix,
+ /* rhs= */ compositeTransformationMatrixArray,
/* rhsOffset= */ 0);
System.arraycopy(
/* src= */ tempResultMatrix,
/* srcPos= */ 0,
- /* dest= */ compositeTransformationMatrix,
+ /* dest= */ compositeTransformationMatrixArray,
/* destPost= */ 0,
/* length= */ tempResultMatrix.length);
visiblePolygon =
@@ -451,41 +467,23 @@ import java.util.List;
}
// Calculate the input frame vertices corresponding to the output frame's visible polygon.
Matrix.invertM(
- tempResultMatrix, /* mInvOffset= */ 0, compositeTransformationMatrix, /* mOffset= */ 0);
+ tempResultMatrix,
+ /* mInvOffset= */ 0,
+ compositeTransformationMatrixArray,
+ /* mOffset= */ 0);
visiblePolygon = MatrixUtils.transformPoints(tempResultMatrix, visiblePolygon);
}
- /**
- * Updates {@link #transformationMatrixCache} with the transformation matrices provided by the
- * {@link #matrixTransformations} for the given frame timestamp and returns whether any matrix in
- * {@link #transformationMatrixCache} changed.
- */
- private boolean updateTransformationMatrixCache(long presentationTimeUs) {
- boolean matrixChanged = false;
- for (int i = 0; i < matrixTransformations.size(); i++) {
- float[] cachedMatrix = transformationMatrixCache[i];
- float[] matrix = matrixTransformations.get(i).getGlMatrixArray(presentationTimeUs);
- if (!Arrays.equals(cachedMatrix, matrix)) {
- checkState(matrix.length == 16, "A 4x4 transformation matrix must have 16 elements");
- System.arraycopy(
- /* src= */ matrix,
- /* srcPos= */ 0,
- /* dest= */ cachedMatrix,
- /* destPost= */ 0,
- /* length= */ matrix.length);
- matrixChanged = true;
- }
+ /** Updates {@link #compositeRgbMatrixArray} based on the given frame timestamp. */
+ private void updateCompositeRgbaMatrixArray(long presentationTimeUs) {
+ float[][] matricesCurrTimestamp = new float[rgbMatrices.size()][16];
+ for (int i = 0; i < rgbMatrices.size(); i++) {
+ matricesCurrTimestamp[i] = rgbMatrices.get(i).getMatrix(presentationTimeUs, useHdr);
}
- return matrixChanged;
- }
- // TODO(b/239757183): Add caching for RgbMatrix and refactor RgbMatrix and MatrixTransformation
- // composing.
- private static float[] createCompositeRgbaMatrixArray(
- ImmutableList rgbMatrices, boolean useHdr, long presentationTimeUs) {
- float[] tempResultMatrix = new float[16];
- float[] compositeRgbaMatrix = new float[16];
- Matrix.setIdentityM(compositeRgbaMatrix, /* smOffset= */ 0);
+ if (!updateMatrixCache(rgbMatrixCache, matricesCurrTimestamp)) {
+ return;
+ }
for (int i = 0; i < rgbMatrices.size(); i++) {
Matrix.multiplyMM(
@@ -493,16 +491,40 @@ import java.util.List;
/* resultOffset= */ 0,
/* lhs= */ rgbMatrices.get(i).getMatrix(presentationTimeUs, useHdr),
/* lhsOffset= */ 0,
- /* rhs= */ compositeRgbaMatrix,
+ /* rhs= */ compositeRgbMatrixArray,
/* rhsOffset= */ 0);
System.arraycopy(
/* src= */ tempResultMatrix,
/* srcPos= */ 0,
- /* dest= */ compositeRgbaMatrix,
+ /* dest= */ compositeRgbMatrixArray,
/* destPost= */ 0,
/* length= */ tempResultMatrix.length);
}
+ }
- return compositeRgbaMatrix;
+ /**
+ * Updates the {@code cachedMatrices} with the {@code newMatrices}. Returns whether a matrix has
+ * changed inside the cache.
+ *
+ * @param cachedMatrices The existing cached matrices. Gets updated if it is out of date.
+ * @param newMatrices The new matrices to compare the cached matrices against.
+ */
+ private static boolean updateMatrixCache(float[][] cachedMatrices, float[][] newMatrices) {
+ boolean matrixChanged = false;
+ for (int i = 0; i < cachedMatrices.length; i++) {
+ float[] cachedMatrix = cachedMatrices[i];
+ float[] newMatrix = newMatrices[i];
+ if (!Arrays.equals(cachedMatrix, newMatrix)) {
+ checkState(newMatrix.length == 16, "A 4x4 transformation matrix must have 16 elements");
+ System.arraycopy(
+ /* src= */ newMatrix,
+ /* srcPos= */ 0,
+ /* dest= */ cachedMatrix,
+ /* destPost= */ 0,
+ /* length= */ newMatrix.length);
+ matrixChanged = true;
+ }
+ }
+ return matrixChanged;
}
}