Commit daa77da1 by leonwind Committed by Marc Baechinger

Merge RgbProcessor and MatrixTransformation.

PiperOrigin-RevId: 472325145
parent 83966478
Showing with 119 additions and 273 deletions
......@@ -28,7 +28,6 @@ import android.opengl.EGLSurface;
import androidx.media3.common.FrameProcessingException;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.junit.After;
......@@ -97,8 +96,7 @@ public final class MatrixTransformationProcessorPixelTest {
Matrix identityMatrix = new Matrix();
MatrixTransformation noEditsTransformation = (long presentationTimeUs) -> identityMatrix;
matrixTransformationFrameProcessor =
MatrixTransformationProcessor.create(
context, ImmutableList.of(noEditsTransformation), /* useHdr= */ false);
noEditsTransformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTransformationFrameProcessor.configure(width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ORIGINAL_PNG_ASSET_PATH);
......@@ -123,8 +121,7 @@ public final class MatrixTransformationProcessorPixelTest {
MatrixTransformation translateRightTransformation =
(long presentationTimeUs) -> translateRightMatrix;
matrixTransformationFrameProcessor =
MatrixTransformationProcessor.create(
context, ImmutableList.of(translateRightTransformation), /* useHdr= */ false);
translateRightTransformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTransformationFrameProcessor.configure(width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(TRANSLATE_RIGHT_PNG_ASSET_PATH);
......@@ -148,8 +145,7 @@ public final class MatrixTransformationProcessorPixelTest {
scaleNarrowMatrix.postScale(.5f, 1.2f);
MatrixTransformation scaleNarrowTransformation = (long presentationTimeUs) -> scaleNarrowMatrix;
matrixTransformationFrameProcessor =
MatrixTransformationProcessor.create(
context, ImmutableList.of(scaleNarrowTransformation), /* useHdr= */ false);
scaleNarrowTransformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTransformationFrameProcessor.configure(width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(SCALE_NARROW_PNG_ASSET_PATH);
......@@ -173,8 +169,7 @@ public final class MatrixTransformationProcessorPixelTest {
rotate90Matrix.postRotate(/* degrees= */ 90);
MatrixTransformation rotate90Transformation = (long presentationTimeUs) -> rotate90Matrix;
matrixTransformationFrameProcessor =
MatrixTransformationProcessor.create(
context, ImmutableList.of(rotate90Transformation), /* useHdr= */ false);
rotate90Transformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTransformationFrameProcessor.configure(width, height);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(ROTATE_90_PNG_ASSET_PATH);
......
......@@ -58,7 +58,7 @@ public final class RgbFilterPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor rgbMatrixProcessor;
private @MonotonicNonNull SingleFrameGlTextureProcessor matrixTransformationProcessor;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId;
private int outputTexId;
......@@ -90,8 +90,8 @@ public final class RgbFilterPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (rgbMatrixProcessor != null) {
rgbMatrixProcessor.release();
if (matrixTransformationProcessor != null) {
matrixTransformationProcessor.release();
}
GlUtil.destroyEglContext(eglDisplay, eglContext);
}
......@@ -100,11 +100,13 @@ public final class RgbFilterPixelTest {
public void drawFrame_grayscale_producesGrayscaleImage() throws Exception {
String testId = "drawFrame_grayscale";
RgbMatrix grayscaleMatrix = RgbFilter.createGrayscaleFilter();
rgbMatrixProcessor = new RgbMatrixProcessor(context, grayscaleMatrix, /* useHdr= */ false);
Pair<Integer, Integer> outputSize = rgbMatrixProcessor.configure(inputWidth, inputHeight);
matrixTransformationProcessor =
grayscaleMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Pair<Integer, Integer> outputSize =
matrixTransformationProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(GRAYSCALE_PNG_ASSET_PATH);
rgbMatrixProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixTransformationProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.first, outputSize.second);
......@@ -121,11 +123,13 @@ public final class RgbFilterPixelTest {
public void drawFrame_inverted_producesInvertedFrame() throws Exception {
String testId = "drawFrame_inverted";
RgbMatrix invertedMatrix = RgbFilter.createInvertedFilter();
rgbMatrixProcessor = new RgbMatrixProcessor(context, invertedMatrix, /* useHdr= */ false);
Pair<Integer, Integer> outputSize = rgbMatrixProcessor.configure(inputWidth, inputHeight);
matrixTransformationProcessor =
invertedMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Pair<Integer, Integer> outputSize =
matrixTransformationProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = BitmapTestUtil.readBitmap(INVERT_PNG_ASSET_PATH);
rgbMatrixProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixTransformationProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
BitmapTestUtil.createArgb8888BitmapFromCurrentGlFramebuffer(
outputSize.first, outputSize.second);
......
#version 100
// Copyright 2022 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ES 2 fragment shader that samples from a (non-external) texture with uTexSampler,
// copying from this texture to the current output.
precision mediump float;
uniform sampler2D uTexSampler;
varying vec2 vTexSamplingCoord;
void main() {
gl_FragColor = texture2D(uTexSampler, vTexSamplingCoord);
}
......@@ -15,7 +15,8 @@
// ES 3 fragment shader that:
// 1. samples optical linear BT.2020 RGB from a (non-external) texture with
// uTexSampler,
// uTexSampler, and applies a 4x4 RGB color matrix to change the pixel
// colors,
// 2. applies the HLG or PQ OETF to yield electrical (HLG or PQ) BT.2020 RGB,
// and
// 3. copies this converted texture color to the current output.
......@@ -28,6 +29,7 @@ out vec4 outColor;
// Only COLOR_TRANSFER_ST2084 and COLOR_TRANSFER_HLG are allowed.
uniform int uOetfColorTransfer;
uniform mat3 uColorTransform;
uniform mat4 uRgbMatrix;
// TODO(b/227624622): Consider using mediump to save precision, if it won't lead
// to noticeable quantization.
......@@ -83,5 +85,6 @@ highp vec3 getElectricalColor(highp vec3 linearColor) {
void main() {
vec4 inputColor = texture(uTexSampler, vTexSamplingCoord);
outColor = vec4(getElectricalColor(inputColor.rgb), inputColor.a);
vec4 transformedColors = uRgbMatrix * vec4(inputColor.rgb, 1);
outColor = vec4(getElectricalColor(transformedColors.rgb), inputColor.a);
}
......@@ -19,11 +19,11 @@
precision mediump float;
uniform sampler2D uTexSampler;
uniform mat4 uColorMatrix;
uniform mat4 uRgbMatrix;
varying vec2 vTexSamplingCoord;
void main() {
vec4 inputColor = texture2D(uTexSampler, vTexSamplingCoord);
gl_FragColor = uColorMatrix * vec4(inputColor.rgb, 1);
gl_FragColor = uRgbMatrix * vec4(inputColor.rgb, 1);
gl_FragColor.a = inputColor.a;
}
......@@ -14,12 +14,17 @@
// limitations under the License.
// ES 2 fragment shader that samples from an external texture with uTexSampler,
// copying from this texture to the current output.
// copying from this texture to the current output while applying a 4x4 RGB
// color matrix to change the pixel colors.
#extension GL_OES_EGL_image_external : require
precision mediump float;
uniform samplerExternalOES uTexSampler;
uniform mat4 uRgbMatrix;
varying vec2 vTexSamplingCoord;
void main() {
gl_FragColor = texture2D(uTexSampler, vTexSamplingCoord);
vec4 inputColor = texture2D(uTexSampler, vTexSamplingCoord);
gl_FragColor = uRgbMatrix * vec4(inputColor.rgb, 1);
gl_FragColor.a = inputColor.a;
}
......@@ -23,13 +23,15 @@
// 3. If uEotfColorTransfer is COLOR_TRANSFER_NO_VALUE, outputs electrical
// (HLG or PQ) BT.2020 RGB. Otherwise, outputs optical linear BT.2020 RGB for
// intermediate shaders by applying the HLG or PQ EOTF.
// 4. Copies this converted texture color to the current output, with alpha = 1.
// 4. Copies this converted texture color to the current output, with alpha = 1,
// while applying a 4x4 RGB color matrix to change the pixel colors.
#extension GL_OES_EGL_image_external : require
#extension GL_EXT_YUV_target : require
precision mediump float;
uniform __samplerExternal2DY2YEXT uTexSampler;
uniform mat3 uYuvToRgbColorTransform;
uniform mat4 uRgbMatrix;
// C.java#ColorTransfer value.
uniform int uEotfColorTransfer;
in vec2 vTexSamplingCoord;
......@@ -101,5 +103,5 @@ vec3 yuvToRgb(vec3 yuv) {
void main() {
vec3 srcYuv = texture(uTexSampler, vTexSamplingCoord).xyz;
vec3 rgb = yuvToRgb(srcYuv);
outColor = vec4(getOpticalColor(rgb), 1.0);
outColor = uRgbMatrix * vec4(getOpticalColor(rgb), 1.0);
}
......@@ -66,6 +66,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final Context context;
private final ImmutableList<GlMatrixTransformation> matrixTransformations;
private final ImmutableList<RgbMatrix> rgbMatrices;
private final EGLDisplay eglDisplay;
private final EGLContext eglContext;
private final DebugViewProvider debugViewProvider;
......@@ -100,6 +101,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
EGLDisplay eglDisplay,
EGLContext eglContext,
ImmutableList<GlMatrixTransformation> matrixTransformations,
ImmutableList<RgbMatrix> rgbMatrices,
FrameProcessor.Listener frameProcessorListener,
DebugViewProvider debugViewProvider,
boolean sampleFromExternalTexture,
......@@ -107,6 +109,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
boolean releaseFramesAutomatically) {
this.context = context;
this.matrixTransformations = matrixTransformations;
this.rgbMatrices = rgbMatrices;
this.eglDisplay = eglDisplay;
this.eglContext = eglContext;
this.debugViewProvider = debugViewProvider;
......@@ -374,11 +377,11 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
if (sampleFromExternalTexture) {
matrixTransformationProcessor =
MatrixTransformationProcessor.createWithExternalSamplerApplyingEotfThenOetf(
context, expandedMatrixTransformations, colorInfo);
context, expandedMatrixTransformations, rgbMatrices, colorInfo);
} else {
matrixTransformationProcessor =
MatrixTransformationProcessor.createApplyingOetf(
context, expandedMatrixTransformations, colorInfo);
context, expandedMatrixTransformations, rgbMatrices, colorInfo);
}
matrixTransformationProcessor.setTextureTransformMatrix(textureTransformMatrix);
......
......@@ -182,8 +182,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
new ImmutableList.Builder<>();
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder =
new ImmutableList.Builder<>();
ImmutableList.Builder<RgbMatrix> rgbaMatrixTransformationListBuilder =
new ImmutableList.Builder<>();
ImmutableList.Builder<RgbMatrix> rgbMatrixListBuilder = new ImmutableList.Builder<>();
boolean sampleFromExternalTexture = true;
for (int i = 0; i < effects.size(); i++) {
Effect effect = effects.get(i);
......@@ -198,62 +197,39 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
continue;
}
if (glEffect instanceof RgbMatrix) {
rgbaMatrixTransformationListBuilder.add((RgbMatrix) glEffect);
rgbMatrixListBuilder.add((RgbMatrix) glEffect);
continue;
}
ImmutableList<GlMatrixTransformation> matrixTransformations =
matrixTransformationListBuilder.build();
if (!matrixTransformations.isEmpty() || sampleFromExternalTexture) {
ImmutableList<RgbMatrix> rgbMatrices = rgbMatrixListBuilder.build();
if (!matrixTransformations.isEmpty() || !rgbMatrices.isEmpty() || sampleFromExternalTexture) {
MatrixTransformationProcessor matrixTransformationProcessor;
if (sampleFromExternalTexture) {
matrixTransformationProcessor =
MatrixTransformationProcessor.createWithExternalSamplerApplyingEotf(
context, matrixTransformations, colorInfo);
context, matrixTransformations, rgbMatrices, colorInfo);
} else {
matrixTransformationProcessor =
MatrixTransformationProcessor.create(
context, matrixTransformations, ColorInfo.isTransferHdr(colorInfo));
context, matrixTransformations, rgbMatrices, ColorInfo.isTransferHdr(colorInfo));
}
textureProcessorListBuilder.add(matrixTransformationProcessor);
matrixTransformationListBuilder = new ImmutableList.Builder<>();
rgbMatrixListBuilder = new ImmutableList.Builder<>();
sampleFromExternalTexture = false;
}
ImmutableList<RgbMatrix> rgbaMatrixTransformations =
rgbaMatrixTransformationListBuilder.build();
if (!rgbaMatrixTransformations.isEmpty()) {
textureProcessorListBuilder.add(
new RgbMatrixProcessor(
context, rgbaMatrixTransformations, ColorInfo.isTransferHdr(colorInfo)));
rgbaMatrixTransformationListBuilder = new ImmutableList.Builder<>();
}
textureProcessorListBuilder.add(
glEffect.toGlTextureProcessor(context, ColorInfo.isTransferHdr(colorInfo)));
}
ImmutableList<RgbMatrix> rgbaMatrixTransformations =
rgbaMatrixTransformationListBuilder.build();
if (!rgbaMatrixTransformations.isEmpty()) {
// Add a MatrixTransformationProcessor if none yet exists for sampling from an external
// texture.
if (sampleFromExternalTexture) {
// TODO(b/239757183): Remove the unnecessary MatrixTransformationProcessor after it got
// merged with RgbMatrixProcessor.
textureProcessorListBuilder.add(
MatrixTransformationProcessor.createWithExternalSamplerApplyingEotf(
context, /* matrixTransformations= */ ImmutableList.of(), colorInfo));
sampleFromExternalTexture = false;
}
textureProcessorListBuilder.add(
new RgbMatrixProcessor(
context, rgbaMatrixTransformations, ColorInfo.isTransferHdr(colorInfo)));
}
textureProcessorListBuilder.add(
new FinalMatrixTransformationProcessorWrapper(
context,
eglDisplay,
eglContext,
matrixTransformationListBuilder.build(),
rgbMatrixListBuilder.build(),
listener,
debugViewProvider,
sampleFromExternalTexture,
......
......@@ -54,6 +54,9 @@ public interface GlMatrixTransformation extends GlEffect {
default SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
throws FrameProcessingException {
return MatrixTransformationProcessor.create(
context, /* matrixTransformations= */ ImmutableList.of(this), useHdr);
context,
/* matrixTransformations= */ ImmutableList.of(this),
/* rgbMatrices= */ ImmutableList.of(),
useHdr);
}
}
......@@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkState;
import android.content.Context;
import androidx.media3.common.FrameProcessingException;
import com.google.common.collect.ImmutableList;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** Provides common color filters. */
......@@ -89,9 +90,13 @@ public class RgbFilter implements RgbMatrix {
}
@Override
public RgbMatrixProcessor toGlTextureProcessor(Context context, boolean useHdr)
public MatrixTransformationProcessor toGlTextureProcessor(Context context, boolean useHdr)
throws FrameProcessingException {
checkForConsistentHdrSetting(useHdr);
return new RgbMatrixProcessor(context, /* rgbMatrix= */ this, useHdr);
return MatrixTransformationProcessor.create(
context,
/* matrixTransformations= */ ImmutableList.of(),
/* rgbMatrices= */ ImmutableList.of(this),
useHdr);
}
}
......@@ -18,6 +18,7 @@ package androidx.media3.effect;
import android.content.Context;
import androidx.media3.common.FrameProcessingException;
import com.google.common.collect.ImmutableList;
/**
* Specifies a 4x4 RGB color transformation matrix to apply to each frame in the fragment shader.
......@@ -37,8 +38,12 @@ public interface RgbMatrix extends GlEffect {
float[] getMatrix(long presentationTimeUs, boolean useHdr);
@Override
default RgbMatrixProcessor toGlTextureProcessor(Context context, boolean useHdr)
default MatrixTransformationProcessor toGlTextureProcessor(Context context, boolean useHdr)
throws FrameProcessingException {
return new RgbMatrixProcessor(context, /* rgbMatrix= */ this, useHdr);
return MatrixTransformationProcessor.create(
context,
/* matrixTransformations= */ ImmutableList.of(),
/* rgbMatrices= */ ImmutableList.of(this),
useHdr);
}
}
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.effect;
import android.content.Context;
import android.opengl.GLES20;
import android.opengl.Matrix;
import android.util.Pair;
import androidx.media3.common.FrameProcessingException;
import com.google.android.exoplayer2.util.GlProgram;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
/**
* Applies a sequence of {@link RgbMatrix} to each frame.
*
* <p>After applying all {@link RgbMatrix} instances, color values are clamped to the limits of the
* color space. Intermediate results are not clamped.
*/
/* package */ final class RgbMatrixProcessor extends SingleFrameGlTextureProcessor {
private static final String VERTEX_SHADER_PATH = "shaders/vertex_shader_transformation_es2.glsl";
private static final String FRAGMENT_SHADER_PATH =
"shaders/fragment_shader_transformation_es2.glsl";
private final GlProgram glProgram;
private final ImmutableList<RgbMatrix> rgbMatrices;
private final boolean useHdr;
// TODO(b/239757183): Merge RgbMatrixProcessor with MatrixTransformationProcessor.
/**
* Creates a new instance.
*
* @param context The {@link Context}.
* @param rgbMatrix The {@link RgbMatrix} to apply to each frame.
* @param useHdr Whether input textures come from an HDR source. If {@code true}, colors will be
* in linear RGB BT.2020. If {@code false}, colors will be in gamma RGB BT.709.
* @throws FrameProcessingException If a problem occurs while reading shader files or an OpenGL
* operation fails or is unsupported.
*/
public RgbMatrixProcessor(Context context, RgbMatrix rgbMatrix, boolean useHdr)
throws FrameProcessingException {
this(context, ImmutableList.of(rgbMatrix), useHdr);
}
/**
* Creates a new instance.
*
* @param context The {@link Context}.
* @param rgbMatrices The {@link RgbMatrix} to apply to each frame.
* @param useHdr Whether input textures come from an HDR source. If {@code true}, colors will be
* in linear RGB BT.2020. If {@code false}, colors will be in gamma RGB BT.709.
* @throws FrameProcessingException If a problem occurs while reading shader files or an OpenGL
* operation fails or is unsupported.
*/
public RgbMatrixProcessor(Context context, ImmutableList<RgbMatrix> rgbMatrices, boolean useHdr)
throws FrameProcessingException {
super(useHdr);
this.rgbMatrices = rgbMatrices;
this.useHdr = useHdr;
try {
glProgram = new GlProgram(context, VERTEX_SHADER_PATH, FRAGMENT_SHADER_PATH);
} catch (IOException | GlUtil.GlException e) {
throw new FrameProcessingException(e);
}
// Draw the frame on the entire normalized device coordinate space, from -1 to 1, for x and y.
glProgram.setBufferAttribute(
"aFramePosition",
GlUtil.getNormalizedCoordinateBounds(),
GlUtil.HOMOGENEOUS_COORDINATE_VECTOR_SIZE);
float[] identityMatrix = new float[16];
Matrix.setIdentityM(identityMatrix, /* smOffset= */ 0);
glProgram.setFloatsUniform("uTransformationMatrix", identityMatrix);
glProgram.setFloatsUniform("uTexTransformationMatrix", identityMatrix);
}
@Override
public Pair<Integer, Integer> configure(int inputWidth, int inputHeight) {
return Pair.create(inputWidth, inputHeight);
}
private static float[] createCompositeRgbaMatrixArray(
ImmutableList<RgbMatrix> rgbMatrices, boolean useHdr, long presentationTimeUs) {
float[] tempResultMatrix = new float[16];
float[] compositeRgbaMatrix = new float[16];
Matrix.setIdentityM(compositeRgbaMatrix, /* smOffset= */ 0);
for (int i = 0; i < rgbMatrices.size(); i++) {
Matrix.multiplyMM(
/* result= */ tempResultMatrix,
/* resultOffset= */ 0,
/* lhs= */ rgbMatrices.get(i).getMatrix(presentationTimeUs, useHdr),
/* lhsOffset= */ 0,
/* rhs= */ compositeRgbaMatrix,
/* rhsOffset= */ 0);
System.arraycopy(
/* src= */ tempResultMatrix,
/* srcPos= */ 0,
/* dest= */ compositeRgbaMatrix,
/* destPost= */ 0,
/* length= */ tempResultMatrix.length);
}
return compositeRgbaMatrix;
}
@Override
public void drawFrame(int inputTexId, long presentationTimeUs) throws FrameProcessingException {
// TODO(b/239431666): Add caching for compacting Matrices.
float[] rgbMatrixArray =
createCompositeRgbaMatrixArray(rgbMatrices, useHdr, presentationTimeUs);
try {
glProgram.use();
glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* texUnitIndex= */ 0);
glProgram.setFloatsUniform("uColorMatrix", rgbMatrixArray);
glProgram.bindAttributesAndUniforms();
// The four-vertex triangle strip forms a quad.
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, /* first= */ 0, /* count= */ 4);
} catch (GlUtil.GlException e) {
throw new FrameProcessingException(e, presentationTimeUs);
}
}
@Override
public void release() throws FrameProcessingException {
super.release();
try {
glProgram.delete();
} catch (GlUtil.GlException e) {
throw new FrameProcessingException(e);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment