mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Shader portion is bloat given we're scaling and biasing the colors. Swap out implementation.
PiperOrigin-RevId: 524113489
This commit is contained in:
parent
2f23774d53
commit
52a9ce3265
4 changed files with 30 additions and 138 deletions
|
|
@ -45,7 +45,7 @@ import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pixel test for contrast adjustment via {@link ContrastShaderProgram}.
|
* Pixel test for contrast adjustment via {@link Contrast}.
|
||||||
*
|
*
|
||||||
* <p>Expected images are taken from an emulator, so tests on different emulators or physical
|
* <p>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
|
* devices may fail. To test on other devices, please increase the {@link
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
@ -18,17 +18,17 @@ package androidx.media3.effect;
|
||||||
|
|
||||||
import static androidx.media3.common.util.Assertions.checkArgument;
|
import static androidx.media3.common.util.Assertions.checkArgument;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import androidx.annotation.FloatRange;
|
import androidx.annotation.FloatRange;
|
||||||
import androidx.media3.common.VideoFrameProcessingException;
|
|
||||||
import androidx.media3.common.util.UnstableApi;
|
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
|
@UnstableApi
|
||||||
public class Contrast implements GlEffect {
|
public class Contrast implements RgbMatrix {
|
||||||
|
|
||||||
/** Adjusts the contrast of video frames in the interval [-1, 1]. */
|
/** 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.
|
* 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) {
|
public Contrast(@FloatRange(from = -1, to = 1) float contrast) {
|
||||||
checkArgument(-1 <= contrast && contrast <= 1, "Contrast needs to be in the interval [-1, 1].");
|
checkArgument(-1 <= contrast && contrast <= 1, "Contrast needs to be in the interval [-1, 1].");
|
||||||
this.contrast = contrast;
|
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
|
@Override
|
||||||
public SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
|
public float[] getMatrix(long presentationTimeUs, boolean useHdr) {
|
||||||
throws VideoFrameProcessingException {
|
// Implementation is not currently time-varying, therefore matrix should not be changing between
|
||||||
return new ContrastShaderProgram(context, this, useHdr);
|
// frames.
|
||||||
|
return contrastMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue