diff --git a/libraries/effect/src/androidTest/java/androidx/media3/effect/ContrastPixelTest.java b/libraries/effect/src/androidTest/java/androidx/media3/effect/ContrastPixelTest.java index 20652e14ca..27259fb85b 100644 --- a/libraries/effect/src/androidTest/java/androidx/media3/effect/ContrastPixelTest.java +++ b/libraries/effect/src/androidTest/java/androidx/media3/effect/ContrastPixelTest.java @@ -45,7 +45,7 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * Pixel test for contrast adjustment via {@link ContrastShaderProgram}. + * Pixel test for contrast adjustment via {@link Contrast}. * *
Expected images are taken from an emulator, so tests on different emulators or physical * devices may fail. To test on other devices, please increase the {@link diff --git a/libraries/effect/src/main/assets/shaders/fragment_shader_contrast_es2.glsl b/libraries/effect/src/main/assets/shaders/fragment_shader_contrast_es2.glsl deleted file mode 100644 index 6a7cb50270..0000000000 --- a/libraries/effect/src/main/assets/shaders/fragment_shader_contrast_es2.glsl +++ /dev/null @@ -1,33 +0,0 @@ -#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 -// while adjusting contrast based on uContrastFactor. - -precision mediump float; -uniform sampler2D uTexSampler; -uniform float uContrastFactor; -varying vec2 vTexSamplingCoord; - -void main() { - vec4 inputColor = texture2D(uTexSampler, vTexSamplingCoord); - - gl_FragColor = vec4( - uContrastFactor * (inputColor.r - 0.5) + 0.5, - uContrastFactor * (inputColor.g - 0.5) + 0.5, - uContrastFactor * (inputColor.b - 0.5) + 0.5, - inputColor.a); -} diff --git a/libraries/effect/src/main/java/androidx/media3/effect/Contrast.java b/libraries/effect/src/main/java/androidx/media3/effect/Contrast.java index 8755eae90b..9548dfd520 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/Contrast.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/Contrast.java @@ -18,17 +18,17 @@ package androidx.media3.effect; import static androidx.media3.common.util.Assertions.checkArgument; -import android.content.Context; import androidx.annotation.FloatRange; -import androidx.media3.common.VideoFrameProcessingException; import androidx.media3.common.util.UnstableApi; -/** A {@link GlEffect} to control the contrast of video frames. */ +/** A {@link RgbMatrix} to control the contrast of video frames. */ @UnstableApi -public class Contrast implements GlEffect { +public class Contrast implements RgbMatrix { /** Adjusts the contrast of video frames in the interval [-1, 1]. */ - public final float contrast; + private final float contrast; + + private final float[] contrastMatrix; /** * Creates a new instance for the given contrast value. @@ -39,12 +39,33 @@ public class Contrast implements GlEffect { public Contrast(@FloatRange(from = -1, to = 1) float contrast) { checkArgument(-1 <= contrast && contrast <= 1, "Contrast needs to be in the interval [-1, 1]."); this.contrast = contrast; + float contrastFactor = (1 + contrast) / (1.0001f - contrast); + contrastMatrix = + new float[] { + contrastFactor, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + contrastFactor, + 0.0f, + 0.0f, + 0.0f, + 0.0f, + contrastFactor, + 0.0f, + (1.0f - contrastFactor) * 0.5f, + (1.0f - contrastFactor) * 0.5f, + (1.0f - contrastFactor) * 0.5f, + 1.0f + }; } @Override - public SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr) - throws VideoFrameProcessingException { - return new ContrastShaderProgram(context, this, useHdr); + public float[] getMatrix(long presentationTimeUs, boolean useHdr) { + // Implementation is not currently time-varying, therefore matrix should not be changing between + // frames. + return contrastMatrix; } @Override diff --git a/libraries/effect/src/main/java/androidx/media3/effect/ContrastShaderProgram.java b/libraries/effect/src/main/java/androidx/media3/effect/ContrastShaderProgram.java deleted file mode 100644 index caabebd09b..0000000000 --- a/libraries/effect/src/main/java/androidx/media3/effect/ContrastShaderProgram.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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 androidx.media3.common.VideoFrameProcessingException; -import androidx.media3.common.util.GlProgram; -import androidx.media3.common.util.GlUtil; -import androidx.media3.common.util.Size; -import java.io.IOException; - -/** Applies a {@link Contrast} to each frame in the fragment shader. */ -/* package */ final class ContrastShaderProgram extends SingleFrameGlShaderProgram { - private static final String VERTEX_SHADER_PATH = "shaders/vertex_shader_transformation_es2.glsl"; - private static final String FRAGMENT_SHADER_PATH = "shaders/fragment_shader_contrast_es2.glsl"; - - private final GlProgram glProgram; - - /** - * Creates a new instance. - * - * @param context The {@link Context}. - * @param contrastEffect The {@link Contrast} to apply to each frame in order. - * @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 linear RGB BT.709. - * @throws VideoFrameProcessingException If a problem occurs while reading shader files. - */ - public ContrastShaderProgram(Context context, Contrast contrastEffect, boolean useHdr) - throws VideoFrameProcessingException { - super(useHdr); - // Use 1.0001f to avoid division by zero issues. - float contrastFactor = (1 + contrastEffect.contrast) / (1.0001f - contrastEffect.contrast); - - try { - glProgram = new GlProgram(context, VERTEX_SHADER_PATH, FRAGMENT_SHADER_PATH); - } catch (IOException | GlUtil.GlException e) { - throw new VideoFrameProcessingException(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 = GlUtil.create4x4IdentityMatrix(); - glProgram.setFloatsUniform("uTransformationMatrix", identityMatrix); - glProgram.setFloatsUniform("uTexTransformationMatrix", identityMatrix); - glProgram.setFloatUniform("uContrastFactor", contrastFactor); - } - - @Override - public Size configure(int inputWidth, int inputHeight) { - return new Size(inputWidth, inputHeight); - } - - @Override - public void drawFrame(int inputTexId, long presentationTimeUs) - throws VideoFrameProcessingException { - try { - glProgram.use(); - glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* texUnitIndex= */ 0); - 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 VideoFrameProcessingException(e, presentationTimeUs); - } - } - - @Override - public void release() throws VideoFrameProcessingException { - super.release(); - try { - glProgram.delete(); - } catch (GlUtil.GlException e) { - throw new VideoFrameProcessingException(e); - } - } -}