Effect: Rename TextureProcessor to ShaderProgram.

Also, replace instances of "texture processor" to "shader program", with capitalization retained.

PiperOrigin-RevId: 507515655
This commit is contained in:
huangdarwin 2023-02-06 18:19:27 +00:00 committed by microkatz
parent 9224a36add
commit ca4d2be1fa
41 changed files with 531 additions and 550 deletions

View File

@ -23,14 +23,14 @@ import androidx.media3.common.FrameProcessingException;
import androidx.media3.common.util.GlProgram;
import androidx.media3.common.util.GlUtil;
import androidx.media3.common.util.Size;
import androidx.media3.effect.SingleFrameGlTextureProcessor;
import androidx.media3.effect.SingleFrameGlShaderProgram;
import java.io.IOException;
/**
* A {@link SingleFrameGlTextureProcessor} that periodically dims the frames such that pixels are
* A {@link SingleFrameGlShaderProgram} that periodically dims the frames such that pixels are
* darker the further they are away from the frame center.
*/
/* package */ final class PeriodicVignetteProcessor extends SingleFrameGlTextureProcessor {
/* package */ final class PeriodicVignetteShaderProgram extends SingleFrameGlShaderProgram {
private static final String VERTEX_SHADER_PATH = "vertex_shader_copy_es2.glsl";
private static final String FRAGMENT_SHADER_PATH = "fragment_shader_vignette_es2.glsl";
@ -61,7 +61,7 @@ import java.io.IOException;
* @param outerRadius The radius after which all pixels are black.
* @throws FrameProcessingException If a problem occurs while reading shader files.
*/
public PeriodicVignetteProcessor(
public PeriodicVignetteShaderProgram(
Context context,
boolean useHdr,
float centerX,

View File

@ -59,7 +59,7 @@ import androidx.media3.effect.BitmapOverlay;
import androidx.media3.effect.Contrast;
import androidx.media3.effect.DrawableOverlay;
import androidx.media3.effect.GlEffect;
import androidx.media3.effect.GlTextureProcessor;
import androidx.media3.effect.GlShaderProgram;
import androidx.media3.effect.HslAdjustment;
import androidx.media3.effect.OverlayEffect;
import androidx.media3.effect.OverlaySettings;
@ -414,7 +414,7 @@ public final class TransformerActivity extends AppCompatActivity {
(GlEffect)
(Context context, boolean useHdr) -> {
try {
return (GlTextureProcessor)
return (GlShaderProgram)
constructor.newInstance(
context,
useHdr,
@ -424,7 +424,7 @@ public final class TransformerActivity extends AppCompatActivity {
/* outputStreamName= */ "output_video");
} catch (Exception e) {
runOnUiThread(() -> showToast(R.string.no_media_pipe_error));
throw new RuntimeException("Failed to load MediaPipe processor", e);
throw new RuntimeException("Failed to load MediaPipeShaderProgram", e);
}
});
} catch (Exception e) {
@ -495,7 +495,7 @@ public final class TransformerActivity extends AppCompatActivity {
effects.add(
(GlEffect)
(Context context, boolean useHdr) ->
new PeriodicVignetteProcessor(
new PeriodicVignetteShaderProgram(
context,
useHdr,
bundle.getFloat(ConfigurationActivity.PERIODIC_VIGNETTE_CENTER_X),

View File

@ -35,7 +35,7 @@
<string name="select_audio_effects" translatable="false">Add audio effects</string>
<string name="select_video_effects" translatable="false">Add video effects</string>
<string name="periodic_vignette_options" translatable="false">Periodic vignette options</string>
<string name="no_media_pipe_error" translatable="false">Failed to load MediaPipe processor. Check the README for instructions.</string>
<string name="no_media_pipe_error" translatable="false">Failed to load MediaPipeShaderProgram. Check the README for instructions.</string>
<string name="transform" translatable="false">Transform</string>
<string name="debug_preview" translatable="false">Debug preview:</string>
<string name="debug_preview_not_available" translatable="false">No debug preview available.</string>

View File

@ -27,7 +27,7 @@ import androidx.media3.common.C;
import androidx.media3.common.FrameProcessingException;
import androidx.media3.common.util.LibraryLoader;
import androidx.media3.common.util.Util;
import androidx.media3.effect.GlTextureProcessor;
import androidx.media3.effect.GlShaderProgram;
import androidx.media3.effect.TextureInfo;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.mediapipe.components.FrameProcessor;
@ -43,9 +43,9 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
/** Runs a MediaPipe graph on input frames. */
/* package */ final class MediaPipeProcessor implements GlTextureProcessor {
/* package */ final class MediaPipeShaderProgram implements GlShaderProgram {
private static final String THREAD_NAME = "Demo:MediaPipeProcessor";
private static final String THREAD_NAME = "Demo:MediaPipeShaderProgram";
private static final long RELEASE_WAIT_TIME_MS = 100;
private static final long RETRY_WAIT_TIME_MS = 1;
@ -80,11 +80,11 @@ import java.util.concurrent.Future;
private boolean acceptedFrame;
/**
* Creates a new texture processor that wraps a MediaPipe graph.
* Creates a new shader program that wraps a MediaPipe graph.
*
* <p>If {@code isSingleFrameGraph} is {@code false}, the {@code MediaPipeProcessor} may waste CPU
* time by continuously attempting to queue input frames to MediaPipe until they are accepted or
* waste memory if MediaPipe accepts and stores many frames internally.
* <p>If {@code isSingleFrameGraph} is {@code false}, the {@code MediaPipeShaderProgram} may waste
* CPU time by continuously attempting to queue input frames to MediaPipe until they are accepted
* or waste memory if MediaPipe accepts and stores many frames internally.
*
* @param context The {@link Context}.
* @param useHdr Whether input textures come from an HDR source. If {@code true}, colors will be
@ -95,7 +95,7 @@ import java.util.concurrent.Future;
* @param inputStreamName Name of the input video stream in the graph.
* @param outputStreamName Name of the input video stream in the graph.
*/
public MediaPipeProcessor(
public MediaPipeShaderProgram(
Context context,
boolean useHdr,
String graphName,
@ -103,8 +103,8 @@ import java.util.concurrent.Future;
String inputStreamName,
String outputStreamName) {
checkState(LOADER.isAvailable());
// TODO(b/227624622): Confirm whether MediaPipeProcessor could support HDR colors.
checkArgument(!useHdr, "MediaPipeProcessor does not support HDR colors.");
// TODO(b/227624622): Confirm whether MediaPipeShaderProgram could support HDR colors.
checkArgument(!useHdr, "MediaPipeShaderProgram does not support HDR colors.");
this.isSingleFrameGraph = isSingleFrameGraph;
singleThreadExecutorService =
@ -233,7 +233,7 @@ import java.util.concurrent.Future;
@Override
public void flush() {
// TODO(b/238302341) Support seeking in MediaPipeProcessor.
// TODO(b/238302341) Support seeking in MediaPipeShaderProgram.
throw new UnsupportedOperationException();
}

View File

@ -411,7 +411,7 @@ public final class GlUtil {
*/
private static void assertValidTextureSize(int width, int height) throws GlException {
// TODO(b/201293185): Consider handling adjustments for sizes > GL_MAX_TEXTURE_SIZE
// (ex. downscaling appropriately) in a texture processor instead of asserting incorrect
// (ex. downscaling appropriately) in a shader program instead of asserting incorrect
// values.
// For valid GL sizes, see:
// https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glTexImage2D.xml

View File

@ -45,7 +45,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Pixel test for contrast adjustment via {@link ContrastProcessor}.
* Pixel test for contrast adjustment via {@link ContrastShaderProgram}.
*
* <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
@ -71,7 +71,7 @@ public class ContrastPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private @MonotonicNonNull SingleFrameGlTextureProcessor contrastProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram contrastShaderProgram;
private int inputTexId;
private int inputWidth;
private int inputHeight;
@ -90,8 +90,8 @@ public class ContrastPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (contrastProcessor != null) {
contrastProcessor.release();
if (contrastShaderProgram != null) {
contrastShaderProgram.release();
}
GlUtil.destroyEglContext(eglDisplay, eglContext);
}
@ -99,13 +99,13 @@ public class ContrastPixelTest {
@Test
public void drawFrame_noContrastChange_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_noContrastChange";
contrastProcessor =
new Contrast(/* contrast= */ 0.0f).toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = contrastProcessor.configure(inputWidth, inputHeight);
contrastShaderProgram =
new Contrast(/* contrast= */ 0.0f).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = contrastShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
contrastProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
contrastShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -118,9 +118,9 @@ public class ContrastPixelTest {
@Test
public void drawFrame_minimumContrast_producesAllGrayFrame() throws Exception {
String testId = "drawFrame_minimumContrast";
contrastProcessor =
new Contrast(/* contrast= */ -1.0f).toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = contrastProcessor.configure(inputWidth, inputHeight);
contrastShaderProgram =
new Contrast(/* contrast= */ -1.0f).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = contrastShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap =
createArgb8888BitmapWithSolidColor(
@ -129,7 +129,7 @@ public class ContrastPixelTest {
Color.rgb(
OPENGL_NEUTRAL_RGB_VALUE, OPENGL_NEUTRAL_RGB_VALUE, OPENGL_NEUTRAL_RGB_VALUE));
contrastProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
contrastShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -143,13 +143,13 @@ public class ContrastPixelTest {
public void drawFrame_decreaseContrast_decreasesPixelsGreaterEqual128IncreasesBelow()
throws Exception {
String testId = "drawFrame_decreaseContrast";
contrastProcessor =
new Contrast(/* contrast= */ -0.75f).toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = contrastProcessor.configure(inputWidth, inputHeight);
contrastShaderProgram =
new Contrast(/* contrast= */ -0.75f).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = contrastShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(DECREASE_CONTRAST_PNG_ASSET_PATH);
contrastProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
contrastShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -163,13 +163,13 @@ public class ContrastPixelTest {
public void drawFrame_increaseContrast_increasesPixelsGreaterEqual128DecreasesBelow()
throws Exception {
String testId = "drawFrame_increaseContrast";
contrastProcessor =
new Contrast(/* contrast= */ 0.75f).toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = contrastProcessor.configure(inputWidth, inputHeight);
contrastShaderProgram =
new Contrast(/* contrast= */ 0.75f).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = contrastShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(INCREASE_CONTRAST_PNG_ASSET_PATH);
contrastProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
contrastShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -182,13 +182,13 @@ public class ContrastPixelTest {
@Test
public void drawFrame_maximumContrast_pixelEither0or255() throws Exception {
String testId = "drawFrame_maximumContrast";
contrastProcessor =
new Contrast(/* contrast= */ 1.0f).toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = contrastProcessor.configure(inputWidth, inputHeight);
contrastShaderProgram =
new Contrast(/* contrast= */ 1.0f).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = contrastShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(MAXIMUM_CONTRAST_PNG_ASSET_PATH);
contrastProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
contrastShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());

View File

@ -63,7 +63,7 @@ public final class CropPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor cropTextureProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram cropShaderProgram;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId;
private int inputWidth;
@ -83,8 +83,8 @@ public final class CropPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (cropTextureProcessor != null) {
cropTextureProcessor.release();
if (cropShaderProgram != null) {
cropShaderProgram.release();
}
if (eglContext != null && eglDisplay != null) {
GlUtil.destroyEglContext(eglDisplay, eglContext);
@ -94,14 +94,14 @@ public final class CropPixelTest {
@Test
public void drawFrame_noEdits_matchesGoldenFile() throws Exception {
String testId = "drawFrame_noEdits";
cropTextureProcessor =
cropShaderProgram =
new Crop(/* left= */ -1, /* right= */ 1, /* bottom= */ -1, /* top= */ 1)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = cropTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = cropShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
cropTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
cropShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -115,14 +115,14 @@ public final class CropPixelTest {
@Test
public void drawFrame_cropSmaller_matchesGoldenFile() throws Exception {
String testId = "drawFrame_cropSmaller";
cropTextureProcessor =
cropShaderProgram =
new Crop(/* left= */ -.9f, /* right= */ .1f, /* bottom= */ -1f, /* top= */ .5f)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = cropTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = cropShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(CROP_SMALLER_PNG_ASSET_PATH);
cropTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
cropShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -136,14 +136,14 @@ public final class CropPixelTest {
@Test
public void drawFrame_cropLarger_matchesGoldenFile() throws Exception {
String testId = "drawFrame_cropLarger";
cropTextureProcessor =
cropShaderProgram =
new Crop(/* left= */ -2f, /* right= */ 2f, /* bottom= */ -1f, /* top= */ 2f)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = cropTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = cropShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(CROP_LARGER_PNG_ASSET_PATH);
cropTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
cropShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());

View File

@ -370,7 +370,7 @@ public final class GlEffectsFrameProcessorFrameReleaseTest {
}
/** Produces blank frames with the given timestamps. */
private static final class BlankFrameProducer implements GlTextureProcessor {
private static final class BlankFrameProducer implements GlShaderProgram {
private @MonotonicNonNull TextureInfo blankTexture;
private @MonotonicNonNull OutputListener outputListener;

View File

@ -17,7 +17,7 @@ package androidx.media3.effect;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.effect.OverlayTextureProcessorPixelTest.OVERLAY_PNG_ASSET_PATH;
import static androidx.media3.effect.OverlayShaderProgramPixelTest.OVERLAY_PNG_ASSET_PATH;
import static androidx.media3.test.utils.BitmapPixelTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE;
import static androidx.media3.test.utils.BitmapPixelTestUtil.getBitmapAveragePixelAbsoluteDifferenceArgb8888;
import static androidx.media3.test.utils.BitmapPixelTestUtil.readBitmap;
@ -503,9 +503,9 @@ public final class GlEffectsFrameProcessorPixelTest {
* Wraps a {@link GlEffect} to prevent the {@link GlEffectsFrameProcessor} from detecting its
* class and optimizing it.
*
* <p>This ensures that {@link GlEffectsFrameProcessor} uses a separate {@link GlTextureProcessor}
* <p>This ensures that {@link GlEffectsFrameProcessor} uses a separate {@link GlShaderProgram}
* for the wrapped {@link GlEffect} rather than merging it with preceding or subsequent {@link
* GlEffect} instances and applying them in one combined {@link GlTextureProcessor}.
* GlEffect} instances and applying them in one combined {@link GlShaderProgram}.
*/
private static final class GlEffectWrapper implements GlEffect {
@ -516,9 +516,9 @@ public final class GlEffectsFrameProcessorPixelTest {
}
@Override
public GlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
public GlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return effect.toGlTextureProcessor(context, useHdr);
return effect.toGlShaderProgram(context, useHdr);
}
}
}

View File

@ -75,7 +75,7 @@ public final class HslAdjustmentPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor hslProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram hslProcessor;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId;
private int inputWidth;
@ -111,7 +111,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_noOpAdjustment_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_noOpAdjustment";
HslAdjustment noOpAdjustment = new HslAdjustment.Builder().build();
hslProcessor = noOpAdjustment.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = noOpAdjustment.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
@ -129,7 +129,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_minimumSaturation_producesGrayFrame() throws Exception {
String testId = "drawFrame_minimumSaturation";
HslAdjustment minimumSaturation = new HslAdjustment.Builder().adjustSaturation(-100).build();
hslProcessor = minimumSaturation.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = minimumSaturation.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(MINIMUM_SATURATION_PNG_ASSET_PATH);
@ -147,7 +147,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_maximumSaturation_producesHighlySaturatedFrame() throws Exception {
String testId = "drawFrame_maximumSaturation";
HslAdjustment maximumSaturation = new HslAdjustment.Builder().adjustSaturation(100).build();
hslProcessor = maximumSaturation.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = maximumSaturation.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(MAXIMUM_SATURATION_PNG_ASSET_PATH);
@ -165,7 +165,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_rotateHueByNegative90Degrees_matchesGoldenFile() throws Exception {
String testId = "drawFrame_rotateHueByNegative90Degrees";
HslAdjustment negativeHueRotation90Degrees = new HslAdjustment.Builder().adjustHue(-90).build();
hslProcessor = negativeHueRotation90Degrees.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = negativeHueRotation90Degrees.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ROTATE_HUE_BY_NEGATIVE_90_DEGREES_PNG_ASSET_PATH);
@ -183,7 +183,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_rotateHueBy60Degrees_matchesGoldenFile() throws Exception {
String testId = "drawFrame_rotateHueBy60Degrees";
HslAdjustment hueRotation60Degrees = new HslAdjustment.Builder().adjustHue(60).build();
hslProcessor = hueRotation60Degrees.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = hueRotation60Degrees.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ROTATE_HUE_BY_60_DEGREES_PNG_ASSET_PATH);
@ -202,7 +202,7 @@ public final class HslAdjustmentPixelTest {
throws Exception {
String testId = "drawFrame_rotateHueByNegative300Degrees";
HslAdjustment hueRotation420Degrees = new HslAdjustment.Builder().adjustHue(-300).build();
hslProcessor = hueRotation420Degrees.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = hueRotation420Degrees.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ROTATE_HUE_BY_60_DEGREES_PNG_ASSET_PATH);
@ -220,7 +220,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_rotateHueBy360Degrees_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_rotateHueBy360Degrees";
HslAdjustment hueRotation360Degrees = new HslAdjustment.Builder().adjustHue(360).build();
hslProcessor = hueRotation360Degrees.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = hueRotation360Degrees.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
@ -238,7 +238,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_minimumLightness_producesBlackFrame() throws Exception {
String testId = "drawFrame_minimumLightness";
HslAdjustment minimumLightness = new HslAdjustment.Builder().adjustLightness(-100).build();
hslProcessor = minimumLightness.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = minimumLightness.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap =
createArgb8888BitmapWithSolidColor(inputWidth, inputHeight, Color.BLACK);
@ -257,7 +257,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_decreaseLightness_producesDarkerFrame() throws Exception {
String testId = "drawFrame_decreaseLightness";
HslAdjustment decreasedLightness = new HslAdjustment.Builder().adjustLightness(-50).build();
hslProcessor = decreasedLightness.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = decreasedLightness.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(DECREASE_LIGHTNESS_PNG_ASSET_PATH);
@ -275,7 +275,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_increaseLightness_producesBrighterFrame() throws Exception {
String testId = "drawFrame_increaseLightness";
HslAdjustment increasedLightness = new HslAdjustment.Builder().adjustLightness(50).build();
hslProcessor = increasedLightness.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = increasedLightness.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(INCREASE_LIGHTNESS_PNG_ASSET_PATH);
@ -293,7 +293,7 @@ public final class HslAdjustmentPixelTest {
public void drawFrame_maximumLightness_producesWhiteFrame() throws Exception {
String testId = "drawFrame_maximumLightness";
HslAdjustment maximumLightness = new HslAdjustment.Builder().adjustLightness(100).build();
hslProcessor = maximumLightness.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = maximumLightness.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap =
createArgb8888BitmapWithSolidColor(inputWidth, inputHeight, Color.WHITE);
@ -313,7 +313,7 @@ public final class HslAdjustmentPixelTest {
String testId = "drawFrame_adjustAllHslSettings";
HslAdjustment allHslSettingsAdjusted =
new HslAdjustment.Builder().adjustHue(60).adjustSaturation(30).adjustLightness(50).build();
hslProcessor = allHslSettingsAdjusted.toGlTextureProcessor(context, /* useHdr= */ false);
hslProcessor = allHslSettingsAdjusted.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = hslProcessor.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ADJUST_ALL_HSL_SETTINGS_PNG_ASSET_PATH);

View File

@ -42,7 +42,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Pixel test for texture processing via {@link MatrixTextureProcessor}.
* Pixel test for texture processing via {@link MatrixShaderProgram}.
*
* <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
@ -50,7 +50,7 @@ import org.junit.runner.RunWith;
* bitmaps as recommended in {@link GlEffectsFrameProcessorPixelTest}.
*/
@RunWith(AndroidJUnit4.class)
public final class MatrixTextureProcessorPixelTest {
public final class MatrixShaderProgramPixelTest {
public static final String ORIGINAL_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/electrical_colors/original.png";
public static final String TRANSLATE_RIGHT_PNG_ASSET_PATH =
@ -64,7 +64,7 @@ public final class MatrixTextureProcessorPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor matrixTextureProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram matrixShaderProgram;
private int inputTexId;
private int inputWidth;
private int inputHeight;
@ -88,8 +88,8 @@ public final class MatrixTextureProcessorPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (matrixTextureProcessor != null) {
matrixTextureProcessor.release();
if (matrixShaderProgram != null) {
matrixShaderProgram.release();
}
if (eglContext != null && eglDisplay != null) {
GlUtil.destroyEglContext(eglDisplay, eglContext);
@ -101,12 +101,11 @@ public final class MatrixTextureProcessorPixelTest {
String testId = "drawFrame_noEdits";
Matrix identityMatrix = new Matrix();
MatrixTransformation noEditsTransformation = (long presentationTimeUs) -> identityMatrix;
matrixTextureProcessor =
noEditsTransformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = noEditsTransformation.toGlShaderProgram(context, /* useHdr= */ false);
matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap = createArgb8888BitmapFromCurrentGlFramebuffer(inputWidth, inputHeight);
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
@ -123,12 +122,12 @@ public final class MatrixTextureProcessorPixelTest {
translateRightMatrix.postTranslate(/* dx= */ 1, /* dy= */ 0);
MatrixTransformation translateRightTransformation =
(long presentationTimeUs) -> translateRightMatrix;
matrixTextureProcessor =
translateRightTransformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram =
translateRightTransformation.toGlShaderProgram(context, /* useHdr= */ false);
matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(TRANSLATE_RIGHT_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap = createArgb8888BitmapFromCurrentGlFramebuffer(inputWidth, inputHeight);
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
@ -144,12 +143,11 @@ public final class MatrixTextureProcessorPixelTest {
Matrix scaleNarrowMatrix = new Matrix();
scaleNarrowMatrix.postScale(.5f, 1.2f);
MatrixTransformation scaleNarrowTransformation = (long presentationTimeUs) -> scaleNarrowMatrix;
matrixTextureProcessor =
scaleNarrowTransformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = scaleNarrowTransformation.toGlShaderProgram(context, /* useHdr= */ false);
matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(SCALE_NARROW_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap = createArgb8888BitmapFromCurrentGlFramebuffer(inputWidth, inputHeight);
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);
@ -165,12 +163,11 @@ public final class MatrixTextureProcessorPixelTest {
Matrix rotate90Matrix = new Matrix();
rotate90Matrix.postRotate(/* degrees= */ 90);
MatrixTransformation rotate90Transformation = (long presentationTimeUs) -> rotate90Matrix;
matrixTextureProcessor =
rotate90Transformation.toGlTextureProcessor(context, /* useHdr= */ false);
matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = rotate90Transformation.toGlShaderProgram(context, /* useHdr= */ false);
matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ROTATE_90_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap = createArgb8888BitmapFromCurrentGlFramebuffer(inputWidth, inputHeight);
maybeSaveTestBitmapToCacheDirectory(testId, /* bitmapLabel= */ "actual", actualBitmap);

View File

@ -49,7 +49,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Pixel test for texture processing via {@link OverlayTextureProcessor}.
* Pixel test for texture processing via {@link OverlayShaderProgram}.
*
* <p>Expected bitmaps are taken from an emulator, so tests on different emulators or physical
* devices may fail. To test on other devices, please increase the {@link
@ -57,7 +57,7 @@ import org.junit.runner.RunWith;
* bitmaps as recommended in {@link GlEffectsFrameProcessorPixelTest}.
*/
@RunWith(AndroidJUnit4.class)
public class OverlayTextureProcessorPixelTest {
public class OverlayShaderProgramPixelTest {
public static final String OVERLAY_PNG_ASSET_PATH = "media/bitmap/overlay/media3test.png";
public static final String ORIGINAL_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/electrical_colors/original.png";
@ -82,7 +82,7 @@ public class OverlayTextureProcessorPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor overlayTextureProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram overlayShaderProgram;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId;
private int inputWidth;
@ -102,8 +102,8 @@ public class OverlayTextureProcessorPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (overlayTextureProcessor != null) {
overlayTextureProcessor.release();
if (overlayShaderProgram != null) {
overlayShaderProgram.release();
}
GlUtil.destroyEglContext(eglDisplay, eglContext);
}
@ -111,14 +111,14 @@ public class OverlayTextureProcessorPixelTest {
@Test
public void drawFrame_noOverlay_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_noOverlay";
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(/* textureOverlays= */ ImmutableList.of())
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -133,14 +133,14 @@ public class OverlayTextureProcessorPixelTest {
String testId = "drawFrame_bitmapOverlay";
Bitmap overlayBitmap = readBitmap(OVERLAY_PNG_ASSET_PATH);
BitmapOverlay bitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(overlayBitmap);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(bitmapOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_BITMAP_DEFAULT);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -178,14 +178,14 @@ public class OverlayTextureProcessorPixelTest {
return overlaySettings;
}
};
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(staticBitmapOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_BITMAP_SCALED);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -205,14 +205,14 @@ public class OverlayTextureProcessorPixelTest {
new OverlaySettings.Builder().setMatrix(translateMatrix).setAnchor(-1f, 1f).build();
BitmapOverlay staticBitmapOverlay =
BitmapOverlay.createStaticBitmapOverlay(overlayBitmap, overlaySettings);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(staticBitmapOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_BITMAP_ANCHORED);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -229,14 +229,14 @@ public class OverlayTextureProcessorPixelTest {
OverlaySettings overlaySettings = new OverlaySettings.Builder().setAlpha(0.5f).build();
BitmapOverlay translucentBitmapOverlay =
BitmapOverlay.createStaticBitmapOverlay(bitmap, overlaySettings);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(translucentBitmapOverlay))
.toGlTextureProcessor(context, false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_BITMAP_TRANSLUCENT);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -258,14 +258,14 @@ public class OverlayTextureProcessorPixelTest {
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextOverlay staticTextOverlay =
TextOverlay.createStaticTextOverlay(overlayText, overlaySettings);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(staticTextOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -285,14 +285,14 @@ public class OverlayTextureProcessorPixelTest {
/* end= */ 4,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextOverlay staticTextOverlay = TextOverlay.createStaticTextOverlay(overlayText);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(staticTextOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_TEXT_DEFAULT);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -317,14 +317,14 @@ public class OverlayTextureProcessorPixelTest {
new OverlaySettings.Builder().setMatrix(translateMatrix).build();
TextOverlay staticTextOverlay =
TextOverlay.createStaticTextOverlay(overlayText, overlaySettings);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(staticTextOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_TEXT_TRANSLATE);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -351,14 +351,14 @@ public class OverlayTextureProcessorPixelTest {
Bitmap bitmap = readBitmap(OVERLAY_PNG_ASSET_PATH);
OverlaySettings overlaySettings2 = new OverlaySettings.Builder().setAlpha(0.5f).build();
BitmapOverlay bitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(bitmap, overlaySettings2);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(textOverlay, bitmapOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_MULTIPLE);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -388,14 +388,14 @@ public class OverlayTextureProcessorPixelTest {
OverlaySettings overlaySettings2 = new OverlaySettings.Builder().setMatrix(scaleMatrix).build();
BitmapOverlay bitmapOverlay = BitmapOverlay.createStaticBitmapOverlay(bitmap, overlaySettings2);
overlayTextureProcessor =
overlayShaderProgram =
new OverlayEffect(ImmutableList.of(bitmapOverlay, textOverlay))
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = overlayTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = overlayShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(OVERLAY_OVERLAP);
overlayTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
overlayShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());

View File

@ -72,7 +72,7 @@ public final class PresentationPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor presentationTextureProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram presentationShaderProgram;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId;
private int inputWidth;
@ -92,8 +92,8 @@ public final class PresentationPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (presentationTextureProcessor != null) {
presentationTextureProcessor.release();
if (presentationShaderProgram != null) {
presentationShaderProgram.release();
}
if (eglContext != null && eglDisplay != null) {
GlUtil.destroyEglContext(eglDisplay, eglContext);
@ -103,14 +103,14 @@ public final class PresentationPixelTest {
@Test
public void drawFrame_noEdits_matchesGoldenFile() throws Exception {
String testId = "drawFrame_noEdits";
presentationTextureProcessor =
presentationShaderProgram =
Presentation.createForHeight(C.LENGTH_UNSET)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = presentationShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
presentationTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
presentationShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -124,14 +124,14 @@ public final class PresentationPixelTest {
@Test
public void drawFrame_changeAspectRatio_scaleToFit_narrow_matchesGoldenFile() throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFit_narrow";
presentationTextureProcessor =
presentationShaderProgram =
Presentation.createForAspectRatio(/* aspectRatio= */ 1f, Presentation.LAYOUT_SCALE_TO_FIT)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = presentationShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ASPECT_RATIO_SCALE_TO_FIT_NARROW_PNG_ASSET_PATH);
presentationTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
presentationShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -145,14 +145,14 @@ public final class PresentationPixelTest {
@Test
public void drawFrame_changeAspectRatio_scaleToFit_wide_matchesGoldenFile() throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFit_wide";
presentationTextureProcessor =
presentationShaderProgram =
Presentation.createForAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = presentationShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WIDE_PNG_ASSET_PATH);
presentationTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
presentationShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -167,15 +167,15 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow_matchesGoldenFile()
throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_narrow";
presentationTextureProcessor =
presentationShaderProgram =
Presentation.createForAspectRatio(
/* aspectRatio= */ 1f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = presentationShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_NARROW_PNG_ASSET_PATH);
presentationTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
presentationShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -190,15 +190,15 @@ public final class PresentationPixelTest {
public void drawFrame_changeAspectRatio_scaleToFitWithCrop_wide_matchesGoldenFile()
throws Exception {
String testId = "drawFrame_changeAspectRatio_scaleToFitWithCrop_wide";
presentationTextureProcessor =
presentationShaderProgram =
Presentation.createForAspectRatio(
/* aspectRatio= */ 2f, Presentation.LAYOUT_SCALE_TO_FIT_WITH_CROP)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = presentationShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ASPECT_RATIO_SCALE_TO_FIT_WITH_CROP_WIDE_PNG_ASSET_PATH);
presentationTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
presentationShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -212,14 +212,14 @@ public final class PresentationPixelTest {
@Test
public void drawFrame_changeAspectRatio_stretchToFit_narrow_matchesGoldenFile() throws Exception {
String testId = "drawFrame_changeAspectRatio_stretchToFit_narrow";
presentationTextureProcessor =
presentationShaderProgram =
Presentation.createForAspectRatio(/* aspectRatio= */ 1f, Presentation.LAYOUT_STRETCH_TO_FIT)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = presentationShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_NARROW_PNG_ASSET_PATH);
presentationTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
presentationShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -233,14 +233,14 @@ public final class PresentationPixelTest {
@Test
public void drawFrame_changeAspectRatio_stretchToFit_wide_matchesGoldenFile() throws Exception {
String testId = "drawFrame_changeAspectRatio_stretchToFit_wide";
presentationTextureProcessor =
presentationShaderProgram =
Presentation.createForAspectRatio(/* aspectRatio= */ 2f, Presentation.LAYOUT_STRETCH_TO_FIT)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = presentationTextureProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = presentationShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ASPECT_RATIO_STRETCH_TO_FIT_WIDE_PNG_ASSET_PATH);
presentationTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
presentationShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());

View File

@ -69,7 +69,7 @@ public final class RgbAdjustmentPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor matrixTextureProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram matrixShaderProgram;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId;
private int inputWidth;
@ -100,8 +100,8 @@ public final class RgbAdjustmentPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (matrixTextureProcessor != null) {
matrixTextureProcessor.release();
if (matrixShaderProgram != null) {
matrixShaderProgram.release();
}
GlUtil.destroyEglContext(eglDisplay, eglContext);
}
@ -110,11 +110,11 @@ public final class RgbAdjustmentPixelTest {
public void drawFrame_identityMatrix_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_identityMatrix";
RgbMatrix identityMatrix = new RgbAdjustment.Builder().build();
matrixTextureProcessor = identityMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = identityMatrix.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -129,13 +129,13 @@ public final class RgbAdjustmentPixelTest {
String testId = "drawFrame_removeColors";
RgbMatrix removeColorMatrix =
new RgbAdjustment.Builder().setRedScale(0).setGreenScale(0).setBlueScale(0).build();
matrixTextureProcessor = removeColorMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = removeColorMatrix.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap =
createArgb8888BitmapWithSolidColor(
outputSize.getWidth(), outputSize.getHeight(), Color.BLACK);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -149,11 +149,11 @@ public final class RgbAdjustmentPixelTest {
public void drawFrame_redOnlyFilter_removeBlueAndGreenValues() throws Exception {
String testId = "drawFrame_redOnlyFilter";
RgbMatrix redOnlyMatrix = new RgbAdjustment.Builder().setBlueScale(0).setGreenScale(0).build();
matrixTextureProcessor = redOnlyMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = redOnlyMatrix.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ONLY_RED_CHANNEL_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -167,11 +167,11 @@ public final class RgbAdjustmentPixelTest {
public void drawFrame_increaseRedChannel_producesBrighterAndRedderFrame() throws Exception {
String testId = "drawFrame_increaseRedChannel";
RgbMatrix increaseRedMatrix = new RgbAdjustment.Builder().setRedScale(5).build();
matrixTextureProcessor = increaseRedMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = increaseRedMatrix.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(INCREASE_RED_CHANNEL_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -186,12 +186,11 @@ public final class RgbAdjustmentPixelTest {
String testId = "drawFrame_increaseBrightness";
RgbMatrix increaseBrightnessMatrix =
new RgbAdjustment.Builder().setRedScale(5).setGreenScale(5).setBlueScale(5).build();
matrixTextureProcessor =
increaseBrightnessMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = increaseBrightnessMatrix.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(INCREASE_BRIGHTNESS_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -207,18 +206,18 @@ public final class RgbAdjustmentPixelTest {
RgbMatrix noRed = new RgbAdjustment.Builder().setRedScale(0).build();
RgbMatrix noGreen = new RgbAdjustment.Builder().setGreenScale(0).build();
RgbMatrix noBlue = new RgbAdjustment.Builder().setBlueScale(0).build();
matrixTextureProcessor =
MatrixTextureProcessor.create(
matrixShaderProgram =
MatrixShaderProgram.create(
context,
/* matrixTransformations= */ ImmutableList.of(),
/* rgbMatrices= */ ImmutableList.of(noRed, noGreen, noBlue),
/* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap =
createArgb8888BitmapWithSolidColor(
outputSize.getWidth(), outputSize.getHeight(), Color.BLACK);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -233,16 +232,16 @@ public final class RgbAdjustmentPixelTest {
String testId = "drawFrame_removeBlueAndGreenValuesInAChain";
RgbMatrix noGreen = new RgbAdjustment.Builder().setGreenScale(0).build();
RgbMatrix noBlue = new RgbAdjustment.Builder().setBlueScale(0).build();
matrixTextureProcessor =
MatrixTextureProcessor.create(
matrixShaderProgram =
MatrixShaderProgram.create(
context,
/* matrixTransformations= */ ImmutableList.of(),
/* rgbMatrices= */ ImmutableList.of(noGreen, noBlue),
/* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ONLY_RED_CHANNEL_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -259,16 +258,16 @@ public final class RgbAdjustmentPixelTest {
RgbMatrix scaleRedMatrix = new RgbAdjustment.Builder().setRedScale(redScale).build();
RgbMatrix scaleRedByInverseMatrix =
new RgbAdjustment.Builder().setRedScale(1 / redScale).build();
matrixTextureProcessor =
MatrixTextureProcessor.create(
matrixShaderProgram =
MatrixShaderProgram.create(
context,
/* matrixTransformations= */ ImmutableList.of(),
/* rgbMatrices= */ ImmutableList.of(scaleRedMatrix, scaleRedByInverseMatrix),
/* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());

View File

@ -64,7 +64,7 @@ public final class RgbFilterPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull SingleFrameGlTextureProcessor matrixTextureProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram matrixShaderProgram;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private int inputTexId;
private int inputWidth;
@ -95,8 +95,8 @@ public final class RgbFilterPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (matrixTextureProcessor != null) {
matrixTextureProcessor.release();
if (matrixShaderProgram != null) {
matrixShaderProgram.release();
}
GlUtil.destroyEglContext(eglDisplay, eglContext);
}
@ -105,11 +105,11 @@ public final class RgbFilterPixelTest {
public void drawFrame_grayscale_producesGrayscaleImage() throws Exception {
String testId = "drawFrame_grayscale";
RgbMatrix grayscaleMatrix = RgbFilter.createGrayscaleFilter();
matrixTextureProcessor = grayscaleMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = grayscaleMatrix.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(GRAYSCALE_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -123,11 +123,11 @@ public final class RgbFilterPixelTest {
public void drawFrame_inverted_producesInvertedFrame() throws Exception {
String testId = "drawFrame_inverted";
RgbMatrix invertedMatrix = RgbFilter.createInvertedFilter();
matrixTextureProcessor = invertedMatrix.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram = invertedMatrix.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
Bitmap expectedBitmap = readBitmap(INVERT_PNG_ASSET_PATH);
matrixTextureProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
matrixShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());

View File

@ -44,7 +44,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Pixel test for Lookup Tables via {@link ColorLutProcessor}.
* Pixel test for Lookup Tables via {@link ColorLutShaderProgram}.
*
* <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
@ -70,7 +70,7 @@ public class SingleColorLutPixelTest {
private @MonotonicNonNull EGLDisplay eglDisplay;
private @MonotonicNonNull EGLContext eglContext;
private @MonotonicNonNull EGLSurface placeholderEglSurface;
private @MonotonicNonNull SingleFrameGlTextureProcessor colorLutProcessor;
private @MonotonicNonNull SingleFrameGlShaderProgram colorLutShaderProgram;
private int inputTexId;
private int inputWidth;
private int inputHeight;
@ -89,8 +89,8 @@ public class SingleColorLutPixelTest {
@After
public void release() throws GlUtil.GlException, FrameProcessingException {
if (colorLutProcessor != null) {
colorLutProcessor.release();
if (colorLutShaderProgram != null) {
colorLutShaderProgram.release();
}
GlUtil.destroyEglContext(eglDisplay, eglContext);
}
@ -99,14 +99,14 @@ public class SingleColorLutPixelTest {
public void drawFrame_identityCubeLutSize2_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_identityLutCubeSize2";
int[][][] cubeIdentityLut = createIdentityLutCube(/* length= */ 2);
colorLutProcessor =
colorLutShaderProgram =
SingleColorLut.createFromCube(cubeIdentityLut)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -120,14 +120,14 @@ public class SingleColorLutPixelTest {
public void drawFrame_identityCubeLutSize64_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_identityLutCubeSize64";
int[][][] cubeIdentityLut = createIdentityLutCube(/* length= */ 64);
colorLutProcessor =
colorLutShaderProgram =
SingleColorLut.createFromCube(cubeIdentityLut)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -141,14 +141,13 @@ public class SingleColorLutPixelTest {
public void drawFrame_identityBitmapLutSize2_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_identityBitmapLutSize2";
Bitmap bitmapLut = createIdentityLutBitmap(/* length= */ 2);
colorLutProcessor =
SingleColorLut.createFromBitmap(bitmapLut)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
colorLutShaderProgram =
SingleColorLut.createFromBitmap(bitmapLut).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -162,14 +161,13 @@ public class SingleColorLutPixelTest {
public void drawFrame_identityBitmapLutSize64_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_identityBitmapLutSize64";
Bitmap bitmapLut = createIdentityLutBitmap(/* length= */ 64);
colorLutProcessor =
SingleColorLut.createFromBitmap(bitmapLut)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
colorLutShaderProgram =
SingleColorLut.createFromBitmap(bitmapLut).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -183,14 +181,13 @@ public class SingleColorLutPixelTest {
public void drawFrame_identityLutFromHaldImage_leavesFrameUnchanged() throws Exception {
String testId = "drawFrame_identityLutFromHaldImage";
Bitmap bitmapLut = readBitmap(VERTICAL_HALD_IDENTITY_LUT);
colorLutProcessor =
SingleColorLut.createFromBitmap(bitmapLut)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
colorLutShaderProgram =
SingleColorLut.createFromBitmap(bitmapLut).toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(ORIGINAL_PNG_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -206,14 +203,14 @@ public class SingleColorLutPixelTest {
int length = 3;
int[][][] mapWhiteToGreen = createIdentityLutCube(length);
mapWhiteToGreen[length - 1][length - 1][length - 1] = Color.GREEN;
colorLutProcessor =
colorLutShaderProgram =
SingleColorLut.createFromCube(mapWhiteToGreen)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(LUT_MAP_WHITE_TO_GREEN_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -227,14 +224,14 @@ public class SingleColorLutPixelTest {
public void drawFrame_applyInvertedLut_producesInvertedFrame() throws Exception {
String testId = "drawFrame_applyInvertedLut";
Bitmap invertedLutBitmap = readBitmap(VERTICAL_HALD_INVERTED_LUT);
colorLutProcessor =
colorLutShaderProgram =
SingleColorLut.createFromBitmap(invertedLutBitmap)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(INVERT_PNG_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());
@ -248,14 +245,14 @@ public class SingleColorLutPixelTest {
public void drawFrame_applyGrayscaleLut_producesGrayscaleFrame() throws Exception {
String testId = "drawFrame_applyGrayscaleLut";
Bitmap grayscaleLutBitmap = readBitmap(VERTICAL_HALD_GRAYSCALE_LUT);
colorLutProcessor =
colorLutShaderProgram =
SingleColorLut.createFromBitmap(grayscaleLutBitmap)
.toGlTextureProcessor(context, /* useHdr= */ false);
Size outputSize = colorLutProcessor.configure(inputWidth, inputHeight);
.toGlShaderProgram(context, /* useHdr= */ false);
Size outputSize = colorLutShaderProgram.configure(inputWidth, inputHeight);
setupOutputTexture(outputSize.getWidth(), outputSize.getHeight());
Bitmap expectedBitmap = readBitmap(GRAYSCALE_PNG_ASSET_PATH);
colorLutProcessor.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
colorLutShaderProgram.drawFrame(inputTexId, /* presentationTimeUs= */ 0);
Bitmap actualBitmap =
createArgb8888BitmapFromCurrentGlFramebuffer(outputSize.getWidth(), outputSize.getHeight());

View File

@ -19,48 +19,48 @@ import android.util.Pair;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.effect.GlTextureProcessor.InputListener;
import androidx.media3.effect.GlTextureProcessor.OutputListener;
import androidx.media3.effect.GlShaderProgram.InputListener;
import androidx.media3.effect.GlShaderProgram.OutputListener;
import java.util.ArrayDeque;
import java.util.Queue;
/**
* Connects a producing and a consuming {@link GlTextureProcessor} instance.
* Connects a producing and a consuming {@link GlShaderProgram} instance.
*
* <p>This listener should be set as {@link InputListener} on the consuming {@link
* GlTextureProcessor} and as {@link OutputListener} on the producing {@link GlTextureProcessor}.
* <p>This listener should be set as {@link InputListener} on the consuming {@link GlShaderProgram}
* and as {@link OutputListener} on the producing {@link GlShaderProgram}.
*/
/* package */ final class ChainingGlTextureProcessorListener
implements GlTextureProcessor.InputListener, GlTextureProcessor.OutputListener {
/* package */ final class ChainingGlShaderProgramListener
implements GlShaderProgram.InputListener, GlShaderProgram.OutputListener {
private final GlTextureProcessor producingGlTextureProcessor;
private final GlTextureProcessor consumingGlTextureProcessor;
private final GlShaderProgram producingGlShaderProgram;
private final GlShaderProgram consumingGlShaderProgram;
private final FrameProcessingTaskExecutor frameProcessingTaskExecutor;
@GuardedBy("this")
private final Queue<Pair<TextureInfo, Long>> availableFrames;
@GuardedBy("this")
private int consumingGlTextureProcessorInputCapacity;
private int consumingGlShaderProgramInputCapacity;
/**
* Creates a new instance.
*
* @param producingGlTextureProcessor The {@link GlTextureProcessor} for which this listener will
* be set as {@link OutputListener}.
* @param consumingGlTextureProcessor The {@link GlTextureProcessor} for which this listener will
* be set as {@link InputListener}.
* @param producingGlShaderProgram The {@link GlShaderProgram} for which this listener will be set
* as {@link OutputListener}.
* @param consumingGlShaderProgram The {@link GlShaderProgram} for which this listener will be set
* as {@link InputListener}.
* @param frameProcessingTaskExecutor The {@link FrameProcessingTaskExecutor} that is used for
* OpenGL calls. All calls to the producing/consuming {@link GlTextureProcessor} will be
* executed by the {@link FrameProcessingTaskExecutor}. The caller is responsible for
* releasing the {@link FrameProcessingTaskExecutor}.
* OpenGL calls. All calls to the producing/consuming {@link GlShaderProgram} will be executed
* by the {@link FrameProcessingTaskExecutor}. The caller is responsible for releasing the
* {@link FrameProcessingTaskExecutor}.
*/
public ChainingGlTextureProcessorListener(
GlTextureProcessor producingGlTextureProcessor,
GlTextureProcessor consumingGlTextureProcessor,
public ChainingGlShaderProgramListener(
GlShaderProgram producingGlShaderProgram,
GlShaderProgram consumingGlShaderProgram,
FrameProcessingTaskExecutor frameProcessingTaskExecutor) {
this.producingGlTextureProcessor = producingGlTextureProcessor;
this.consumingGlTextureProcessor = consumingGlTextureProcessor;
this.producingGlShaderProgram = producingGlShaderProgram;
this.consumingGlShaderProgram = consumingGlShaderProgram;
this.frameProcessingTaskExecutor = frameProcessingTaskExecutor;
availableFrames = new ArrayDeque<>();
}
@ -69,18 +69,17 @@ import java.util.Queue;
public synchronized void onReadyToAcceptInputFrame() {
@Nullable Pair<TextureInfo, Long> pendingFrame = availableFrames.poll();
if (pendingFrame == null) {
consumingGlTextureProcessorInputCapacity++;
consumingGlShaderProgramInputCapacity++;
return;
}
long presentationTimeUs = pendingFrame.second;
if (presentationTimeUs == C.TIME_END_OF_SOURCE) {
frameProcessingTaskExecutor.submit(
consumingGlTextureProcessor::signalEndOfCurrentInputStream);
frameProcessingTaskExecutor.submit(consumingGlShaderProgram::signalEndOfCurrentInputStream);
} else {
frameProcessingTaskExecutor.submit(
() ->
consumingGlTextureProcessor.queueInputFrame(
consumingGlShaderProgram.queueInputFrame(
/* inputTexture= */ pendingFrame.first, presentationTimeUs));
}
}
@ -88,25 +87,25 @@ import java.util.Queue;
@Override
public void onInputFrameProcessed(TextureInfo inputTexture) {
frameProcessingTaskExecutor.submit(
() -> producingGlTextureProcessor.releaseOutputFrame(inputTexture));
() -> producingGlShaderProgram.releaseOutputFrame(inputTexture));
}
@Override
public synchronized void onFlush() {
consumingGlTextureProcessorInputCapacity = 0;
consumingGlShaderProgramInputCapacity = 0;
availableFrames.clear();
frameProcessingTaskExecutor.submit(producingGlTextureProcessor::flush);
frameProcessingTaskExecutor.submit(producingGlShaderProgram::flush);
}
@Override
public synchronized void onOutputFrameAvailable(
TextureInfo outputTexture, long presentationTimeUs) {
if (consumingGlTextureProcessorInputCapacity > 0) {
if (consumingGlShaderProgramInputCapacity > 0) {
frameProcessingTaskExecutor.submit(
() ->
consumingGlTextureProcessor.queueInputFrame(
consumingGlShaderProgram.queueInputFrame(
/* inputTexture= */ outputTexture, presentationTimeUs));
consumingGlTextureProcessorInputCapacity--;
consumingGlShaderProgramInputCapacity--;
} else {
availableFrames.add(new Pair<>(outputTexture, presentationTimeUs));
}
@ -117,8 +116,7 @@ import java.util.Queue;
if (!availableFrames.isEmpty()) {
availableFrames.add(new Pair<>(TextureInfo.UNSET, C.TIME_END_OF_SOURCE));
} else {
frameProcessingTaskExecutor.submit(
consumingGlTextureProcessor::signalEndOfCurrentInputStream);
frameProcessingTaskExecutor.submit(consumingGlShaderProgram::signalEndOfCurrentInputStream);
}
}
}

View File

@ -44,8 +44,8 @@ public interface ColorLut extends GlEffect {
/** This method must be executed on the same thread as other GL commands. */
@Override
@WorkerThread
default SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
default SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return new ColorLutProcessor(context, /* colorLut= */ this, useHdr);
return new ColorLutShaderProgram(context, /* colorLut= */ this, useHdr);
}
}

View File

@ -27,7 +27,7 @@ import androidx.media3.common.util.Size;
import java.io.IOException;
/** Applies a {@link ColorLut} to each frame in the fragment shader. */
/* package */ final class ColorLutProcessor extends SingleFrameGlTextureProcessor {
/* package */ final class ColorLutShaderProgram 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_lut_es2.glsl";
@ -43,11 +43,11 @@ import java.io.IOException;
* in linear RGB BT.2020. If {@code false}, colors will be in linear RGB BT.709.
* @throws FrameProcessingException If a problem occurs while reading shader files.
*/
public ColorLutProcessor(Context context, ColorLut colorLut, boolean useHdr)
public ColorLutShaderProgram(Context context, ColorLut colorLut, boolean useHdr)
throws FrameProcessingException {
super(useHdr);
// TODO(b/246315245): Add HDR support.
checkArgument(!useHdr, "LutProcessor does not support HDR colors.");
checkArgument(!useHdr, "ColorLutShaderProgram does not support HDR colors.");
this.colorLut = colorLut;
try {

View File

@ -41,8 +41,8 @@ public class Contrast implements GlEffect {
}
@Override
public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
public SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return new ContrastProcessor(context, this, useHdr);
return new ContrastShaderProgram(context, this, useHdr);
}
}

View File

@ -25,7 +25,7 @@ import androidx.media3.common.util.Size;
import java.io.IOException;
/** Applies a {@link Contrast} to each frame in the fragment shader. */
/* package */ final class ContrastProcessor extends SingleFrameGlTextureProcessor {
/* 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";
@ -40,7 +40,7 @@ import java.io.IOException;
* in linear RGB BT.2020. If {@code false}, colors will be in linear RGB BT.709.
* @throws FrameProcessingException If a problem occurs while reading shader files.
*/
public ContrastProcessor(Context context, Contrast contrastEffect, boolean useHdr)
public ContrastShaderProgram(Context context, Contrast contrastEffect, boolean useHdr)
throws FrameProcessingException {
super(useHdr);
// Use 1.0001f to avoid division by zero issues.

View File

@ -16,12 +16,12 @@
package androidx.media3.effect;
/**
* Interface for a {@link GlTextureProcessor} that samples from an external texture.
* Interface for a {@link GlShaderProgram} that samples from an external texture.
*
* <p>Use {@link #setTextureTransformMatrix(float[])} to provide the texture's transformation
* matrix.
*/
/* package */ interface ExternalTextureProcessor extends GlTextureProcessor {
/* package */ interface ExternalShaderProgram extends GlShaderProgram {
/**
* Sets the texture transform matrix for converting an external surface texture's coordinates to

View File

@ -25,26 +25,26 @@ import androidx.media3.common.FrameInfo;
import androidx.media3.common.FrameProcessingException;
import androidx.media3.common.FrameProcessor;
import androidx.media3.common.util.GlUtil;
import androidx.media3.effect.GlTextureProcessor.InputListener;
import androidx.media3.effect.GlShaderProgram.InputListener;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Forwards externally produced frames that become available via a {@link SurfaceTexture} to an
* {@link ExternalTextureProcessor} for consumption.
* {@link ExternalShaderProgram} for consumption.
*/
/* package */ class ExternalTextureManager implements InputListener {
private final FrameProcessingTaskExecutor frameProcessingTaskExecutor;
private final ExternalTextureProcessor externalTextureProcessor;
private final ExternalShaderProgram externalShaderProgram;
private final int externalTexId;
private final SurfaceTexture surfaceTexture;
private final float[] textureTransformMatrix;
private final Queue<FrameInfo> pendingFrames;
// Incremented on any thread, decremented on the GL thread only.
private final AtomicInteger externalTextureProcessorInputCapacity;
private final AtomicInteger externalShaderProgramInputCapacity;
// Counts the frames that are registered before flush but are made available after flush.
// Read and written only on GL thread.
private int numberOfFramesToDropOnBecomingAvailable;
@ -66,16 +66,16 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* Creates a new instance.
*
* @param externalTextureProcessor The {@link ExternalTextureProcessor} for which this {@code
* @param externalShaderProgram The {@link ExternalShaderProgram} for which this {@code
* ExternalTextureManager} will be set as the {@link InputListener}.
* @param frameProcessingTaskExecutor The {@link FrameProcessingTaskExecutor}.
* @throws FrameProcessingException If a problem occurs while creating the external texture.
*/
public ExternalTextureManager(
ExternalTextureProcessor externalTextureProcessor,
ExternalShaderProgram externalShaderProgram,
FrameProcessingTaskExecutor frameProcessingTaskExecutor)
throws FrameProcessingException {
this.externalTextureProcessor = externalTextureProcessor;
this.externalShaderProgram = externalShaderProgram;
this.frameProcessingTaskExecutor = frameProcessingTaskExecutor;
try {
externalTexId = GlUtil.createExternalTexture();
@ -85,7 +85,7 @@ import java.util.concurrent.atomic.AtomicInteger;
surfaceTexture = new SurfaceTexture(externalTexId);
textureTransformMatrix = new float[16];
pendingFrames = new ConcurrentLinkedQueue<>();
externalTextureProcessorInputCapacity = new AtomicInteger();
externalShaderProgramInputCapacity = new AtomicInteger();
previousStreamOffsetUs = C.TIME_UNSET;
}
@ -101,7 +101,7 @@ import java.util.concurrent.atomic.AtomicInteger;
maybeExecuteAfterFlushTask();
} else {
availableFrameCount++;
maybeQueueFrameToExternalTextureProcessor();
maybeQueueFrameToExternalShaderProgram();
}
}));
return surfaceTexture;
@ -111,8 +111,8 @@ import java.util.concurrent.atomic.AtomicInteger;
public void onReadyToAcceptInputFrame() {
frameProcessingTaskExecutor.submit(
() -> {
externalTextureProcessorInputCapacity.incrementAndGet();
maybeQueueFrameToExternalTextureProcessor();
externalShaderProgramInputCapacity.incrementAndGet();
maybeQueueFrameToExternalShaderProgram();
});
}
@ -121,7 +121,7 @@ import java.util.concurrent.atomic.AtomicInteger;
frameProcessingTaskExecutor.submit(
() -> {
currentFrame = null;
maybeQueueFrameToExternalTextureProcessor();
maybeQueueFrameToExternalShaderProgram();
});
}
@ -148,7 +148,7 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* Returns the number of {@linkplain #registerInputFrame(FrameInfo) registered} frames that have
* not been sent to the downstream {@link ExternalTextureProcessor} yet.
* not been sent to the downstream {@link ExternalShaderProgram} yet.
*
* <p>Can be called on any thread.
*/
@ -166,7 +166,7 @@ import java.util.concurrent.atomic.AtomicInteger;
() -> {
inputStreamEnded = true;
if (pendingFrames.isEmpty() && currentFrame == null) {
externalTextureProcessor.signalEndOfCurrentInputStream();
externalShaderProgram.signalEndOfCurrentInputStream();
}
});
}
@ -183,7 +183,7 @@ import java.util.concurrent.atomic.AtomicInteger;
availableFrameCount--;
surfaceTexture.updateTexImage();
}
externalTextureProcessorInputCapacity.set(0);
externalShaderProgramInputCapacity.set(0);
currentFrame = null;
pendingFrames.clear();
maybeExecuteAfterFlushTask();
@ -197,8 +197,8 @@ import java.util.concurrent.atomic.AtomicInteger;
}
@WorkerThread
private void maybeQueueFrameToExternalTextureProcessor() {
if (externalTextureProcessorInputCapacity.get() == 0
private void maybeQueueFrameToExternalShaderProgram() {
if (externalShaderProgramInputCapacity.get() == 0
|| availableFrameCount == 0
|| currentFrame != null) {
return;
@ -209,28 +209,28 @@ import java.util.concurrent.atomic.AtomicInteger;
this.currentFrame = pendingFrames.peek();
FrameInfo currentFrame = checkStateNotNull(this.currentFrame);
externalTextureProcessorInputCapacity.decrementAndGet();
externalShaderProgramInputCapacity.decrementAndGet();
surfaceTexture.getTransformMatrix(textureTransformMatrix);
externalTextureProcessor.setTextureTransformMatrix(textureTransformMatrix);
externalShaderProgram.setTextureTransformMatrix(textureTransformMatrix);
long frameTimeNs = surfaceTexture.getTimestamp();
long offsetToAddUs = currentFrame.offsetToAddUs;
long streamOffsetUs = currentFrame.streamOffsetUs;
if (streamOffsetUs != previousStreamOffsetUs) {
if (previousStreamOffsetUs != C.TIME_UNSET) {
externalTextureProcessor.signalEndOfCurrentInputStream();
externalShaderProgram.signalEndOfCurrentInputStream();
}
previousStreamOffsetUs = streamOffsetUs;
}
// Correct the presentation time so that processors don't see the stream offset.
// Correct the presentation time so that GlShaderPrograms don't see the stream offset.
long presentationTimeUs = (frameTimeNs / 1000) + offsetToAddUs - streamOffsetUs;
externalTextureProcessor.queueInputFrame(
externalShaderProgram.queueInputFrame(
new TextureInfo(
externalTexId, /* fboId= */ C.INDEX_UNSET, currentFrame.width, currentFrame.height),
presentationTimeUs);
checkStateNotNull(pendingFrames.remove());
if (inputStreamEnded && pendingFrames.isEmpty()) {
externalTextureProcessor.signalEndOfCurrentInputStream();
externalShaderProgram.signalEndOfCurrentInputStream();
}
}
}

View File

@ -51,19 +51,19 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/**
* Wrapper around a {@link GlTextureProcessor} that writes to the provided output surface and
* optional debug surface view.
* Wrapper around a {@link GlShaderProgram} that writes to the provided output surface and optional
* debug surface view.
*
* <p>The wrapped {@link GlTextureProcessor} applies the {@link GlMatrixTransformation} and {@link
* <p>The wrapped {@link GlShaderProgram} applies the {@link GlMatrixTransformation} and {@link
* RgbMatrix} instances passed to the constructor, followed by any transformations needed to convert
* the frames to the dimensions specified by the provided {@link SurfaceInfo}.
*
* <p>This wrapper is used for the final {@link GlTextureProcessor} instance in the chain of {@link
* GlTextureProcessor} instances used by {@link FrameProcessor}.
* <p>This wrapper is used for the final {@link GlShaderProgram} instance in the chain of {@link
* GlShaderProgram} instances used by {@link FrameProcessor}.
*/
/* package */ final class FinalMatrixTextureProcessorWrapper implements ExternalTextureProcessor {
/* package */ final class FinalMatrixShaderProgramWrapper implements ExternalShaderProgram {
private static final String TAG = "FinalProcessorWrapper";
private static final String TAG = "FinalShaderWrapper";
private final Context context;
private final ImmutableList<GlMatrixTransformation> matrixTransformations;
@ -83,7 +83,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private int inputWidth;
private int inputHeight;
@Nullable private MatrixTextureProcessor matrixTextureProcessor;
@Nullable private MatrixShaderProgram matrixShaderProgram;
@Nullable private SurfaceViewWrapper debugSurfaceViewWrapper;
private InputListener inputListener;
private @MonotonicNonNull Size outputSizeBeforeSurfaceTransformation;
@ -99,7 +99,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Nullable
private EGLSurface outputEglSurface;
public FinalMatrixTextureProcessorWrapper(
public FinalMatrixShaderProgramWrapper(
Context context,
EGLDisplay eglDisplay,
EGLContext eglContext,
@ -167,7 +167,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override
public void releaseOutputFrame(TextureInfo outputTexture) {
// The final texture processor writes to a surface so there is no texture to release.
// The final shader program writes to a surface so there is no texture to release.
throw new UnsupportedOperationException();
}
@ -195,8 +195,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public void flush() {
// Drops all frames that aren't released yet.
availableFrames.clear();
if (matrixTextureProcessor != null) {
matrixTextureProcessor.flush();
if (matrixShaderProgram != null) {
matrixShaderProgram.flush();
}
inputListener.onFlush();
inputListener.onReadyToAcceptInputFrame();
@ -205,8 +205,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Override
@WorkerThread
public synchronized void release() throws FrameProcessingException {
if (matrixTextureProcessor != null) {
matrixTextureProcessor.release();
if (matrixShaderProgram != null) {
matrixShaderProgram.release();
}
try {
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
@ -224,8 +224,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/* destPost= */ 0,
/* length= */ textureTransformMatrix.length);
if (matrixTextureProcessor != null) {
matrixTextureProcessor.setTextureTransformMatrix(textureTransformMatrix);
if (matrixShaderProgram != null) {
matrixShaderProgram.setTextureTransformMatrix(textureTransformMatrix);
}
}
@ -295,7 +295,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
EGLSurface outputEglSurface = this.outputEglSurface;
SurfaceInfo outputSurfaceInfo = this.outputSurfaceInfo;
MatrixTextureProcessor matrixTextureProcessor = this.matrixTextureProcessor;
MatrixShaderProgram matrixShaderProgram = this.matrixShaderProgram;
GlUtil.focusEglSurface(
eglDisplay,
@ -304,7 +304,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
outputSurfaceInfo.width,
outputSurfaceInfo.height);
GlUtil.clearOutputFrame();
matrixTextureProcessor.drawFrame(inputTexture.texId, presentationTimeUs);
matrixShaderProgram.drawFrame(inputTexture.texId, presentationTimeUs);
EGLExt.eglPresentationTimeANDROID(
eglDisplay,
@ -316,7 +316,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@EnsuresNonNullIf(
expression = {"outputSurfaceInfo", "outputEglSurface", "matrixTextureProcessor"},
expression = {"outputSurfaceInfo", "outputEglSurface", "matrixShaderProgram"},
result = true)
private synchronized boolean ensureConfigured(int inputWidth, int inputHeight)
throws FrameProcessingException, GlUtil.GlException {
@ -340,9 +340,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
if (outputSurfaceInfo == null) {
if (matrixTextureProcessor != null) {
matrixTextureProcessor.release();
matrixTextureProcessor = null;
if (matrixShaderProgram != null) {
matrixShaderProgram.release();
matrixShaderProgram = null;
}
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
outputEglSurface = null;
@ -372,13 +372,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
this.debugSurfaceView = debugSurfaceView;
}
if (matrixTextureProcessor != null && outputSizeOrRotationChanged) {
matrixTextureProcessor.release();
matrixTextureProcessor = null;
if (matrixShaderProgram != null && outputSizeOrRotationChanged) {
matrixShaderProgram.release();
matrixShaderProgram = null;
outputSizeOrRotationChanged = false;
}
if (matrixTextureProcessor == null) {
matrixTextureProcessor = createMatrixTextureProcessorForOutputSurface(outputSurfaceInfo);
if (matrixShaderProgram == null) {
matrixShaderProgram = createMatrixShaderProgramForOutputSurface(outputSurfaceInfo);
}
this.outputSurfaceInfo = outputSurfaceInfo;
@ -386,7 +386,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return true;
}
private MatrixTextureProcessor createMatrixTextureProcessorForOutputSurface(
private MatrixShaderProgram createMatrixShaderProgramForOutputSurface(
SurfaceInfo outputSurfaceInfo) throws FrameProcessingException {
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder =
new ImmutableList.Builder<GlMatrixTransformation>().addAll(matrixTransformations);
@ -400,46 +400,46 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
Presentation.createForWidthAndHeight(
outputSurfaceInfo.width, outputSurfaceInfo.height, Presentation.LAYOUT_SCALE_TO_FIT));
MatrixTextureProcessor matrixTextureProcessor;
MatrixShaderProgram matrixShaderProgram;
ImmutableList<GlMatrixTransformation> expandedMatrixTransformations =
matrixTransformationListBuilder.build();
if (sampleFromExternalTexture) {
matrixTextureProcessor =
MatrixTextureProcessor.createWithExternalSampler(
matrixShaderProgram =
MatrixShaderProgram.createWithExternalSampler(
context,
expandedMatrixTransformations,
rgbMatrices,
/* inputColorInfo= */ inputColorInfo,
/* outputColorInfo= */ outputColorInfo);
} else {
matrixTextureProcessor =
MatrixTextureProcessor.createApplyingOetf(
matrixShaderProgram =
MatrixShaderProgram.createApplyingOetf(
context, expandedMatrixTransformations, rgbMatrices, outputColorInfo);
}
matrixTextureProcessor.setTextureTransformMatrix(textureTransformMatrix);
Size outputSize = matrixTextureProcessor.configure(inputWidth, inputHeight);
matrixShaderProgram.setTextureTransformMatrix(textureTransformMatrix);
Size outputSize = matrixShaderProgram.configure(inputWidth, inputHeight);
checkState(outputSize.getWidth() == outputSurfaceInfo.width);
checkState(outputSize.getHeight() == outputSurfaceInfo.height);
return matrixTextureProcessor;
return matrixShaderProgram;
}
private void maybeRenderFrameToDebugSurface(TextureInfo inputTexture, long presentationTimeUs) {
if (debugSurfaceViewWrapper == null || this.matrixTextureProcessor == null) {
if (debugSurfaceViewWrapper == null || this.matrixShaderProgram == null) {
return;
}
MatrixTextureProcessor matrixTextureProcessor = this.matrixTextureProcessor;
MatrixShaderProgram matrixShaderProgram = this.matrixShaderProgram;
try {
debugSurfaceViewWrapper.maybeRenderToSurfaceView(
() -> {
GlUtil.clearOutputFrame();
@C.ColorTransfer
int configuredColorTransfer = matrixTextureProcessor.getOutputColorTransfer();
matrixTextureProcessor.setOutputColorTransfer(
int configuredColorTransfer = matrixShaderProgram.getOutputColorTransfer();
matrixShaderProgram.setOutputColorTransfer(
checkNotNull(debugSurfaceViewWrapper).outputColorTransfer);
matrixTextureProcessor.drawFrame(inputTexture.texId, presentationTimeUs);
matrixTextureProcessor.setOutputColorTransfer(configuredColorTransfer);
matrixShaderProgram.drawFrame(inputTexture.texId, presentationTimeUs);
matrixShaderProgram.setOutputColorTransfer(configuredColorTransfer);
});
} catch (FrameProcessingException | GlUtil.GlException e) {
Log.d(TAG, "Error rendering to debug preview", e);

View File

@ -50,8 +50,8 @@ public class FrameCache implements GlEffect {
}
@Override
public GlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
public GlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return new FrameCacheTextureProcessor(context, capacity, useHdr);
return new FrameCacheShaderProgram(context, capacity, useHdr);
}
}

View File

@ -35,7 +35,7 @@ import java.util.concurrent.Executor;
*
* <p>Implements {@link FrameCache}.
*/
/* package */ class FrameCacheTextureProcessor implements GlTextureProcessor {
/* package */ class FrameCacheShaderProgram implements GlShaderProgram {
private static final String VERTEX_SHADER_TRANSFORMATION_ES2_PATH =
"shaders/vertex_shader_transformation_es2.glsl";
private static final String FRAGMENT_SHADER_TRANSFORMATION_ES2_PATH =
@ -53,7 +53,7 @@ import java.util.concurrent.Executor;
private Executor errorListenerExecutor;
/** Creates a new instance. */
public FrameCacheTextureProcessor(Context context, int capacity, boolean useHdr)
public FrameCacheShaderProgram(Context context, int capacity, boolean useHdr)
throws FrameProcessingException {
freeOutputTextures = new ArrayDeque<>();
inUseOutputTextures = new ArrayDeque<>();

View File

@ -21,24 +21,23 @@ import androidx.media3.common.FrameProcessingException;
import androidx.media3.common.util.UnstableApi;
/**
* Interface for a video frame effect with a {@link GlTextureProcessor} implementation.
* Interface for a video frame effect with a {@link GlShaderProgram} implementation.
*
* <p>Implementations contain information specifying the effect and can be {@linkplain
* #toGlTextureProcessor(Context, boolean) converted} to a {@link GlTextureProcessor} which applies
* the effect.
* #toGlShaderProgram(Context, boolean) converted} to a {@link GlShaderProgram} which applies the
* effect.
*/
@UnstableApi
public interface GlEffect extends Effect {
/**
* Returns a {@link GlTextureProcessor} that applies the effect.
* Returns a {@link GlShaderProgram} that applies the effect.
*
* @param context A {@link Context}.
* @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 FrameProcessingException If an error occurs while creating the {@link
* GlTextureProcessor}.
* @throws FrameProcessingException If an error occurs while creating the {@link GlShaderProgram}.
*/
GlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
GlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException;
}

View File

@ -152,8 +152,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
/**
* Creates the OpenGL context, surfaces, textures, and frame buffers, initializes {@link
* GlTextureProcessor} instances corresponding to the {@link GlEffect} instances, and returns a
* new {@code GlEffectsFrameProcessor}.
* GlShaderProgram} instances corresponding to the {@link GlEffect} instances, and returns a new
* {@code GlEffectsFrameProcessor}.
*
* <p>All {@link Effect} instances must be {@link GlEffect} instances.
*
@ -199,8 +199,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
}
}
ImmutableList<GlTextureProcessor> textureProcessors =
getGlTextureProcessorsForGlEffects(
ImmutableList<GlShaderProgram> shaderPrograms =
getGlShaderProgramsForGlEffects(
context,
effects,
eglDisplay,
@ -213,29 +213,29 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
listener);
FrameProcessingTaskExecutor frameProcessingTaskExecutor =
new FrameProcessingTaskExecutor(singleThreadExecutorService, listener);
chainTextureProcessorsWithListeners(
textureProcessors, frameProcessingTaskExecutor, listener, executor);
chainShaderProgramsWithListeners(
shaderPrograms, frameProcessingTaskExecutor, listener, executor);
return new GlEffectsFrameProcessor(
eglDisplay,
eglContext,
frameProcessingTaskExecutor,
textureProcessors,
shaderPrograms,
releaseFramesAutomatically);
}
/**
* Combines consecutive {@link GlMatrixTransformation} and {@link RgbMatrix} instances into a
* single {@link MatrixTextureProcessor} and converts all other {@link GlEffect} instances to
* separate {@link GlTextureProcessor} instances.
* single {@link MatrixShaderProgram} and converts all other {@link GlEffect} instances to
* separate {@link GlShaderProgram} instances.
*
* <p>All {@link Effect} instances must be {@link GlEffect} instances.
*
* @return A non-empty list of {@link GlTextureProcessor} instances to apply in the given order.
* The first is an {@link ExternalTextureProcessor} and the last is a {@link
* FinalMatrixTextureProcessorWrapper}.
* @return A non-empty list of {@link GlShaderProgram} instances to apply in the given order. The
* first is an {@link ExternalShaderProgram} and the last is a {@link
* FinalMatrixShaderProgramWrapper}.
*/
private static ImmutableList<GlTextureProcessor> getGlTextureProcessorsForGlEffects(
private static ImmutableList<GlShaderProgram> getGlShaderProgramsForGlEffects(
Context context,
List<Effect> effects,
EGLDisplay eglDisplay,
@ -247,8 +247,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
Executor executor,
Listener listener)
throws FrameProcessingException {
ImmutableList.Builder<GlTextureProcessor> textureProcessorListBuilder =
new ImmutableList.Builder<>();
ImmutableList.Builder<GlShaderProgram> shaderProgramListBuilder = new ImmutableList.Builder<>();
ImmutableList.Builder<GlMatrixTransformation> matrixTransformationListBuilder =
new ImmutableList.Builder<>();
ImmutableList.Builder<RgbMatrix> rgbMatrixListBuilder = new ImmutableList.Builder<>();
@ -277,30 +276,30 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
ImmutableList<RgbMatrix> rgbMatrices = rgbMatrixListBuilder.build();
boolean isOutputTransferHdr = ColorInfo.isTransferHdr(outputColorInfo);
if (!matrixTransformations.isEmpty() || !rgbMatrices.isEmpty() || sampleFromExternalTexture) {
MatrixTextureProcessor matrixTextureProcessor;
MatrixShaderProgram matrixShaderProgram;
if (sampleFromExternalTexture) {
matrixTextureProcessor =
MatrixTextureProcessor.createWithExternalSampler(
matrixShaderProgram =
MatrixShaderProgram.createWithExternalSampler(
context,
matrixTransformations,
rgbMatrices,
/* inputColorInfo= */ inputColorInfo,
/* outputColorInfo= */ linearColorInfo);
} else {
matrixTextureProcessor =
MatrixTextureProcessor.create(
matrixShaderProgram =
MatrixShaderProgram.create(
context, matrixTransformations, rgbMatrices, isOutputTransferHdr);
}
textureProcessorListBuilder.add(matrixTextureProcessor);
shaderProgramListBuilder.add(matrixShaderProgram);
matrixTransformationListBuilder = new ImmutableList.Builder<>();
rgbMatrixListBuilder = new ImmutableList.Builder<>();
sampleFromExternalTexture = false;
}
textureProcessorListBuilder.add(glEffect.toGlTextureProcessor(context, isOutputTransferHdr));
shaderProgramListBuilder.add(glEffect.toGlShaderProgram(context, isOutputTransferHdr));
}
textureProcessorListBuilder.add(
new FinalMatrixTextureProcessorWrapper(
shaderProgramListBuilder.add(
new FinalMatrixShaderProgramWrapper(
context,
eglDisplay,
eglContext,
@ -313,30 +312,28 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
releaseFramesAutomatically,
executor,
listener));
return textureProcessorListBuilder.build();
return shaderProgramListBuilder.build();
}
/**
* Chains the given {@link GlTextureProcessor} instances using {@link
* ChainingGlTextureProcessorListener} instances.
* Chains the given {@link GlShaderProgram} instances using {@link
* ChainingGlShaderProgramListener} instances.
*/
private static void chainTextureProcessorsWithListeners(
ImmutableList<GlTextureProcessor> textureProcessors,
private static void chainShaderProgramsWithListeners(
ImmutableList<GlShaderProgram> shaderPrograms,
FrameProcessingTaskExecutor frameProcessingTaskExecutor,
Listener frameProcessorListener,
Executor frameProcessorListenerExecutor) {
for (int i = 0; i < textureProcessors.size() - 1; i++) {
GlTextureProcessor producingGlTextureProcessor = textureProcessors.get(i);
GlTextureProcessor consumingGlTextureProcessor = textureProcessors.get(i + 1);
ChainingGlTextureProcessorListener chainingGlTextureProcessorListener =
new ChainingGlTextureProcessorListener(
producingGlTextureProcessor,
consumingGlTextureProcessor,
frameProcessingTaskExecutor);
producingGlTextureProcessor.setOutputListener(chainingGlTextureProcessorListener);
producingGlTextureProcessor.setErrorListener(
for (int i = 0; i < shaderPrograms.size() - 1; i++) {
GlShaderProgram producingGlShaderProgram = shaderPrograms.get(i);
GlShaderProgram consumingGlShaderProgram = shaderPrograms.get(i + 1);
ChainingGlShaderProgramListener chainingGlShaderProgramListener =
new ChainingGlShaderProgramListener(
producingGlShaderProgram, consumingGlShaderProgram, frameProcessingTaskExecutor);
producingGlShaderProgram.setOutputListener(chainingGlShaderProgramListener);
producingGlShaderProgram.setErrorListener(
frameProcessorListenerExecutor, frameProcessorListener::onFrameProcessingError);
consumingGlTextureProcessor.setInputListener(chainingGlTextureProcessorListener);
consumingGlShaderProgram.setInputListener(chainingGlShaderProgramListener);
}
}
@ -349,8 +346,8 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
private final ExternalTextureManager inputExternalTextureManager;
private final Surface inputSurface;
private final boolean releaseFramesAutomatically;
private final FinalMatrixTextureProcessorWrapper finalTextureProcessorWrapper;
private final ImmutableList<GlTextureProcessor> allTextureProcessors;
private final FinalMatrixShaderProgramWrapper finalShaderProgramWrapper;
private final ImmutableList<GlShaderProgram> allShaderPrograms;
/**
* Offset compared to original media presentation time that has been added to incoming frame
@ -365,7 +362,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
EGLDisplay eglDisplay,
EGLContext eglContext,
FrameProcessingTaskExecutor frameProcessingTaskExecutor,
ImmutableList<GlTextureProcessor> textureProcessors,
ImmutableList<GlShaderProgram> shaderPrograms,
boolean releaseFramesAutomatically)
throws FrameProcessingException {
@ -374,17 +371,17 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
this.frameProcessingTaskExecutor = frameProcessingTaskExecutor;
this.releaseFramesAutomatically = releaseFramesAutomatically;
checkState(!textureProcessors.isEmpty());
checkState(textureProcessors.get(0) instanceof ExternalTextureProcessor);
checkState(getLast(textureProcessors) instanceof FinalMatrixTextureProcessorWrapper);
ExternalTextureProcessor inputExternalTextureProcessor =
(ExternalTextureProcessor) textureProcessors.get(0);
checkState(!shaderPrograms.isEmpty());
checkState(shaderPrograms.get(0) instanceof ExternalShaderProgram);
checkState(getLast(shaderPrograms) instanceof FinalMatrixShaderProgramWrapper);
ExternalShaderProgram inputExternalShaderProgram =
(ExternalShaderProgram) shaderPrograms.get(0);
inputExternalTextureManager =
new ExternalTextureManager(inputExternalTextureProcessor, frameProcessingTaskExecutor);
inputExternalTextureProcessor.setInputListener(inputExternalTextureManager);
new ExternalTextureManager(inputExternalShaderProgram, frameProcessingTaskExecutor);
inputExternalShaderProgram.setInputListener(inputExternalTextureManager);
inputSurface = new Surface(inputExternalTextureManager.getSurfaceTexture());
finalTextureProcessorWrapper = (FinalMatrixTextureProcessorWrapper) getLast(textureProcessors);
allTextureProcessors = textureProcessors;
finalShaderProgramWrapper = (FinalMatrixShaderProgramWrapper) getLast(shaderPrograms);
allShaderPrograms = shaderPrograms;
previousStreamOffsetUs = C.TIME_UNSET;
}
@ -423,7 +420,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
nextInputFrameInfo = adjustForPixelWidthHeightRatio(inputFrameInfo);
if (nextInputFrameInfo.streamOffsetUs != previousStreamOffsetUs) {
finalTextureProcessorWrapper.appendStream(nextInputFrameInfo.streamOffsetUs);
finalShaderProgramWrapper.appendStream(nextInputFrameInfo.streamOffsetUs);
previousStreamOffsetUs = nextInputFrameInfo.streamOffsetUs;
}
}
@ -444,7 +441,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
@Override
public void setOutputSurfaceInfo(@Nullable SurfaceInfo outputSurfaceInfo) {
finalTextureProcessorWrapper.setOutputSurfaceInfo(outputSurfaceInfo);
finalShaderProgramWrapper.setOutputSurfaceInfo(outputSurfaceInfo);
}
@Override
@ -453,7 +450,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
!releaseFramesAutomatically,
"Calling this method is not allowed when releaseFramesAutomatically is enabled");
frameProcessingTaskExecutor.submitWithHighPriority(
() -> finalTextureProcessorWrapper.releaseOutputFrame(releaseTimeNs));
() -> finalShaderProgramWrapper.releaseOutputFrame(releaseTimeNs));
}
@Override
@ -469,7 +466,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
frameProcessingTaskExecutor.flush();
CountDownLatch latch = new CountDownLatch(1);
inputExternalTextureManager.setOnFlushCompleteListener(latch::countDown);
frameProcessingTaskExecutor.submit(finalTextureProcessorWrapper::flush);
frameProcessingTaskExecutor.submit(finalShaderProgramWrapper::flush);
latch.await();
inputExternalTextureManager.setOnFlushCompleteListener(null);
} catch (InterruptedException e) {
@ -481,8 +478,7 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
public void release() {
try {
frameProcessingTaskExecutor.release(
/* releaseTask= */ this::releaseTextureProcessorsAndDestroyGlContext,
RELEASE_WAIT_TIME_MS);
/* releaseTask= */ this::releaseShaderProgramsAndDestroyGlContext, RELEASE_WAIT_TIME_MS);
} catch (InterruptedException unexpected) {
Thread.currentThread().interrupt();
throw new IllegalStateException(unexpected);
@ -513,15 +509,15 @@ public final class GlEffectsFrameProcessor implements FrameProcessor {
}
/**
* Releases the {@link GlTextureProcessor} instances and destroys the OpenGL context.
* Releases the {@link GlShaderProgram} instances and destroys the OpenGL context.
*
* <p>This method must be called on the {@linkplain #THREAD_NAME background thread}.
*/
@WorkerThread
private void releaseTextureProcessorsAndDestroyGlContext()
private void releaseShaderProgramsAndDestroyGlContext()
throws GlUtil.GlException, FrameProcessingException {
for (int i = 0; i < allTextureProcessors.size(); i++) {
allTextureProcessors.get(i).release();
for (int i = 0; i < allShaderPrograms.size(); i++) {
allShaderPrograms.get(i).release();
}
GlUtil.destroyEglContext(eglDisplay, eglContext);
}

View File

@ -53,9 +53,9 @@ public interface GlMatrixTransformation extends GlEffect {
float[] getGlMatrixArray(long presentationTimeUs);
@Override
default SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
default SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return MatrixTextureProcessor.create(
return MatrixShaderProgram.create(
context,
/* matrixTransformations= */ ImmutableList.of(this),
/* rgbMatrices= */ ImmutableList.of(),

View File

@ -22,29 +22,29 @@ import java.util.concurrent.Executor;
/**
* Processes frames from one OpenGL 2D texture to another.
*
* <p>The {@code GlTextureProcessor} consumes input frames it accepts via {@link
* <p>The {@code GlShaderProgram} consumes input frames it accepts via {@link
* #queueInputFrame(TextureInfo, long)} and surrenders each texture back to the caller via its
* {@linkplain InputListener#onInputFrameProcessed(TextureInfo) listener} once the texture's
* contents have been processed.
*
* <p>The {@code GlTextureProcessor} produces output frames asynchronously and notifies its owner
* when they are available via its {@linkplain OutputListener#onOutputFrameAvailable(TextureInfo,
* long) listener}. The {@code GlTextureProcessor} instance's owner must surrender the texture back
* to the {@code GlTextureProcessor} via {@link #releaseOutputFrame(TextureInfo)} when it has
* finished processing it.
* <p>The {@code GlShaderProgram} produces output frames asynchronously and notifies its owner when
* they are available via its {@linkplain OutputListener#onOutputFrameAvailable(TextureInfo, long)
* listener}. The {@code GlShaderProgram} instance's owner must surrender the texture back to the
* {@code GlShaderProgram} via {@link #releaseOutputFrame(TextureInfo)} when it has finished
* processing it.
*
* <p>{@code GlTextureProcessor} implementations can choose to produce output frames before
* receiving input frames or process several input frames before producing an output frame. However,
* {@code GlTextureProcessor} implementations cannot assume that they will receive more than one
* input frame at a time, so they must process each input frame they accept even if they cannot
* produce output yet.
* <p>{@code GlShaderProgram} implementations can choose to produce output frames before receiving
* input frames or process several input frames before producing an output frame. However, {@code
* GlShaderProgram} implementations cannot assume that they will receive more than one input frame
* at a time, so they must process each input frame they accept even if they cannot produce output
* yet.
*
* <p>The methods in this interface must be called on the thread that owns the parent OpenGL
* context. If the implementation uses another OpenGL context, e.g., on another thread, it must
* configure it to share data with the context of thread the interface methods are called on.
*/
@UnstableApi
public interface GlTextureProcessor {
public interface GlShaderProgram {
/**
* Listener for input-related frame processing events.
@ -53,7 +53,7 @@ public interface GlTextureProcessor {
*/
interface InputListener {
/**
* Called when the {@link GlTextureProcessor} is ready to accept another input frame.
* Called when the {@link GlShaderProgram} is ready to accept another input frame.
*
* <p>For each time this method is called, {@link #queueInputFrame(TextureInfo, long)} can be
* called once.
@ -61,9 +61,9 @@ public interface GlTextureProcessor {
default void onReadyToAcceptInputFrame() {}
/**
* Called when the {@link GlTextureProcessor} has processed an input frame.
* Called when the {@link GlShaderProgram} has processed an input frame.
*
* <p>The implementation shall not assume the {@link GlTextureProcessor} is {@linkplain
* <p>The implementation shall not assume the {@link GlShaderProgram} is {@linkplain
* #onReadyToAcceptInputFrame ready to accept another input frame} when this method is called.
*
* @param inputTexture The {@link TextureInfo} that was used to {@linkplain
@ -72,9 +72,9 @@ public interface GlTextureProcessor {
default void onInputFrameProcessed(TextureInfo inputTexture) {}
/**
* Called when the {@link GlTextureProcessor} has been flushed.
* Called when the {@link GlShaderProgram} has been flushed.
*
* <p>The implementation shall not assume the {@link GlTextureProcessor} is {@linkplain
* <p>The implementation shall not assume the {@link GlShaderProgram} is {@linkplain
* #onReadyToAcceptInputFrame ready to accept another input frame} when this method is called.
*/
default void onFlush() {}
@ -87,12 +87,12 @@ public interface GlTextureProcessor {
*/
interface OutputListener {
/**
* Called when the {@link GlTextureProcessor} has produced an output frame.
* Called when the {@link GlShaderProgram} has produced an output frame.
*
* <p>After the listener's owner has processed the output frame, it must call {@link
* #releaseOutputFrame(TextureInfo)}. The output frame should be released as soon as possible,
* as there is no guarantee that the {@link GlTextureProcessor} will produce further output
* frames before this output frame is released.
* as there is no guarantee that the {@link GlShaderProgram} will produce further output frames
* before this output frame is released.
*
* @param outputTexture A {@link TextureInfo} describing the texture containing the output
* frame.
@ -101,8 +101,8 @@ public interface GlTextureProcessor {
default void onOutputFrameAvailable(TextureInfo outputTexture, long presentationTimeUs) {}
/**
* Called when the {@link GlTextureProcessor} will not produce further output frames belonging
* to the current output stream.
* Called when the {@link GlShaderProgram} will not produce further output frames belonging to
* the current output stream.
*/
default void onCurrentOutputStreamEnded() {}
}
@ -117,7 +117,7 @@ public interface GlTextureProcessor {
* Called when an exception occurs during asynchronous frame processing.
*
* <p>If an error occurred, consuming and producing further frames will not work as expected and
* the {@link GlTextureProcessor} should be released.
* the {@link GlShaderProgram} should be released.
*/
void onFrameProcessingError(FrameProcessingException e);
}
@ -150,11 +150,11 @@ public interface GlTextureProcessor {
/**
* Processes an input frame if possible.
*
* <p>The {@code GlTextureProcessor} owns the accepted frame until it calls {@link
* <p>The {@code GlShaderProgram} owns the accepted frame until it calls {@link
* InputListener#onInputFrameProcessed(TextureInfo)}. The caller should not overwrite or release
* the texture before the {@code GlTextureProcessor} has finished processing it.
* the texture before the {@code GlShaderProgram} has finished processing it.
*
* <p>This method must only be called when the {@code GlTextureProcessor} can {@linkplain
* <p>This method must only be called when the {@code GlShaderProgram} can {@linkplain
* InputListener#onReadyToAcceptInputFrame() accept an input frame}.
*
* @param inputTexture A {@link TextureInfo} describing the texture containing the input frame.
@ -163,13 +163,13 @@ public interface GlTextureProcessor {
void queueInputFrame(TextureInfo inputTexture, long presentationTimeUs);
/**
* Notifies the texture processor that the frame on the given output texture is no longer used and
* can be overwritten.
* Notifies the {@code GlShaderProgram} that the frame on the given output texture is no longer
* used and can be overwritten.
*/
void releaseOutputFrame(TextureInfo outputTexture);
/**
* Notifies the {@code GlTextureProcessor} that no further input frames belonging to the current
* Notifies the {@code GlShaderProgram} that no further input frames belonging to the current
* input stream will be queued.
*
* <p>Input frames that are queued after this method is called belong to a different input stream,
@ -179,11 +179,11 @@ public interface GlTextureProcessor {
void signalEndOfCurrentInputStream();
/**
* Flushes the {@code GlTextureProcessor}.
* Flushes the {@code GlShaderProgram}.
*
* <p>The texture processor should reclaim the ownership of its allocated textures, {@linkplain
* InputListener#onFlush notify} its {@link InputListener} about the flush event, and {@linkplain
* InputListener#onReadyToAcceptInputFrame report its availability} if necessary.
* <p>The {@code GlShaderProgram} should reclaim the ownership of its allocated textures,
* {@linkplain InputListener#onFlush notify} its {@link InputListener} about the flush event, and
* {@linkplain InputListener#onReadyToAcceptInputFrame report its availability} if necessary.
*/
void flush();

View File

@ -113,8 +113,8 @@ public class HslAdjustment implements GlEffect {
}
@Override
public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
public SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return new HslProcessor(context, /* hslAdjustment= */ this, useHdr);
return new HslShaderProgram(context, /* hslAdjustment= */ this, useHdr);
}
}

View File

@ -27,7 +27,7 @@ import androidx.media3.common.util.Size;
import java.io.IOException;
/** Applies the {@link HslAdjustment} to each frame in the fragment shader. */
/* package */ final class HslProcessor extends SingleFrameGlTextureProcessor {
/* package */ final class HslShaderProgram 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_hsl_es2.glsl";
@ -42,7 +42,7 @@ import java.io.IOException;
* in linear RGB BT.2020. If {@code false}, colors will be in linear RGB BT.709.
* @throws FrameProcessingException If a problem occurs while reading shader files.
*/
public HslProcessor(Context context, HslAdjustment hslAdjustment, boolean useHdr)
public HslShaderProgram(Context context, HslAdjustment hslAdjustment, boolean useHdr)
throws FrameProcessingException {
super(useHdr);
// TODO(b/241241680): Check if HDR <-> HSL works the same or not.

View File

@ -52,8 +52,8 @@ import java.util.List;
*/
@UnstableApi
@SuppressWarnings("FunctionalInterfaceClash") // b/228192298
/* package */ final class MatrixTextureProcessor extends SingleFrameGlTextureProcessor
implements ExternalTextureProcessor {
/* package */ final class MatrixShaderProgram extends SingleFrameGlShaderProgram
implements ExternalShaderProgram {
private static final String VERTEX_SHADER_TRANSFORMATION_PATH =
"shaders/vertex_shader_transformation_es2.glsl";
@ -144,7 +144,7 @@ import java.util.List;
* @throws FrameProcessingException If a problem occurs while reading shader files or an OpenGL
* operation fails or is unsupported.
*/
public static MatrixTextureProcessor create(
public static MatrixShaderProgram create(
Context context,
List<GlMatrixTransformation> matrixTransformations,
List<RgbMatrix> rgbMatrices,
@ -155,7 +155,7 @@ import java.util.List;
context, VERTEX_SHADER_TRANSFORMATION_PATH, FRAGMENT_SHADER_TRANSFORMATION_PATH);
// No transfer functions needed, because input and output are both optical colors.
return new MatrixTextureProcessor(
return new MatrixShaderProgram(
glProgram,
ImmutableList.copyOf(matrixTransformations),
ImmutableList.copyOf(rgbMatrices),
@ -171,7 +171,7 @@ import java.util.List;
* external texture.
*
* <p>Applies the {@linkplain ColorInfo#colorTransfer inputColorInfo EOTF} to convert from
* electrical color input, to intermediate optical {@link GlTextureProcessor} color output, before
* electrical color input, to intermediate optical {@link GlShaderProgram} color output, before
* {@code matrixTransformations} and {@code rgbMatrices} are applied. Also applies the {@linkplain
* ColorInfo#colorTransfer outputColorInfo OETF}, if needed, to convert back to an electrical
* color output.
@ -188,7 +188,7 @@ import java.util.List;
* @throws FrameProcessingException If a problem occurs while reading shader files or an OpenGL
* operation fails or is unsupported.
*/
public static MatrixTextureProcessor createWithExternalSampler(
public static MatrixShaderProgram createWithExternalSampler(
Context context,
List<GlMatrixTransformation> matrixTransformations,
List<RgbMatrix> rgbMatrices,
@ -242,7 +242,7 @@ import java.util.List;
glProgram.setIntUniform("uOutputColorTransfer", outputColorTransfer);
}
return new MatrixTextureProcessor(
return new MatrixShaderProgram(
glProgram,
ImmutableList.copyOf(matrixTransformations),
ImmutableList.copyOf(rgbMatrices),
@ -254,7 +254,7 @@ import java.util.List;
* Creates a new instance.
*
* <p>Applies the {@linkplain ColorInfo#colorTransfer outputColorInfo OETF} to convert from
* intermediate optical {@link GlTextureProcessor} color input, to electrical color output, after
* intermediate optical {@link GlShaderProgram} color input, to electrical color output, after
* {@code matrixTransformations} and {@code rgbMatrices} are applied.
*
* <p>Intermediate optical/linear colors are RGB BT.2020 if {@code outputColorInfo} is {@linkplain
@ -269,7 +269,7 @@ import java.util.List;
* @throws FrameProcessingException If a problem occurs while reading shader files or an OpenGL
* operation fails or is unsupported.
*/
public static MatrixTextureProcessor createApplyingOetf(
public static MatrixShaderProgram createApplyingOetf(
Context context,
List<GlMatrixTransformation> matrixTransformations,
List<RgbMatrix> rgbMatrices,
@ -297,7 +297,7 @@ import java.util.List;
glProgram.setIntUniform("uOutputColorTransfer", outputColorTransfer);
}
return new MatrixTextureProcessor(
return new MatrixShaderProgram(
glProgram,
ImmutableList.copyOf(matrixTransformations),
ImmutableList.copyOf(rgbMatrices),
@ -317,7 +317,7 @@ import java.util.List;
* @param useHdr Whether to process the input as an HDR signal. Using HDR requires the {@code
* EXT_YUV_target} OpenGL extension.
*/
private MatrixTextureProcessor(
private MatrixShaderProgram(
GlProgram glProgram,
ImmutableList<GlMatrixTransformation> matrixTransformations,
ImmutableList<RgbMatrix> rgbMatrices,
@ -403,7 +403,7 @@ import java.util.List;
/**
* Sets the output {@link C.ColorTransfer}.
*
* <p>This method must not be called on {@code MatrixTextureProcessor} instances that output
* <p>This method must not be called on {@code MatrixShaderProgram} instances that output
* {@linkplain C#COLOR_TRANSFER_LINEAR linear colors}.
*/
public void setOutputColorTransfer(@C.ColorTransfer int colorTransfer) {

View File

@ -39,8 +39,8 @@ public final class OverlayEffect implements GlEffect {
}
@Override
public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
public SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return new OverlayTextureProcessor(context, useHdr, overlays);
return new OverlayShaderProgram(context, useHdr, overlays);
}
}

View File

@ -29,7 +29,7 @@ import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableList;
/** Applies zero or more {@link TextureOverlay}s onto each frame. */
/* package */ final class OverlayTextureProcessor extends SingleFrameGlTextureProcessor {
/* package */ final class OverlayShaderProgram extends SingleFrameGlShaderProgram {
private static final int MATRIX_OFFSET = 0;
@ -51,16 +51,16 @@ import com.google.common.collect.ImmutableList;
* in linear RGB BT.2020. If {@code false}, colors will be in linear RGB BT.709.
* @throws FrameProcessingException If a problem occurs while reading shader files.
*/
public OverlayTextureProcessor(
public OverlayShaderProgram(
Context context, boolean useHdr, ImmutableList<TextureOverlay> overlays)
throws FrameProcessingException {
super(useHdr);
checkArgument(!useHdr, "OverlayTextureProcessor does not support HDR colors yet.");
checkArgument(!useHdr, "OverlayShaderProgram does not support HDR colors yet.");
// The maximum number of samplers allowed in a single GL program is 16.
// We use one for every overlay and one for the video.
checkArgument(
overlays.size() <= 15,
"OverlayTextureProcessor does not support more than 15 overlays in the same processor.");
"OverlayShaderProgram does not support more than 15 overlays in the same instance.");
this.overlays = overlays;
aspectRatioMatrix = GlUtil.create4x4IdentityMatrix();
overlayMatrix = GlUtil.create4x4IdentityMatrix();

View File

@ -91,9 +91,9 @@ public class RgbFilter implements RgbMatrix {
}
@Override
public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
public SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
checkForConsistentHdrSetting(useHdr);
return RgbMatrix.super.toGlTextureProcessor(context, useHdr);
return RgbMatrix.super.toGlShaderProgram(context, useHdr);
}
}

View File

@ -34,15 +34,15 @@ public interface RgbMatrix extends GlEffect {
* @param presentationTimeUs The timestamp of the frame to apply the matrix on.
* @param useHdr If {@code true}, colors will be in linear RGB BT.2020. If {@code false}, colors
* will be in linear RGB BT.709. Must be consistent with {@code useHdr} in {@link
* #toGlTextureProcessor(Context, boolean)}.
* #toGlShaderProgram(Context, boolean)}.
* @return The {@code RgbMatrix} to apply to the frame.
*/
float[] getMatrix(long presentationTimeUs, boolean useHdr);
@Override
default SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
default SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
return MatrixTextureProcessor.create(
return MatrixShaderProgram.create(
context,
/* matrixTransformations= */ ImmutableList.of(),
/* rgbMatrices= */ ImmutableList.of(this),

View File

@ -128,13 +128,13 @@ public class SingleColorLut implements ColorLut {
Bitmap.Config.ARGB_8888);
}
/** Must be called after {@link #toGlTextureProcessor(Context, boolean)}. */
/** Must be called after {@link #toGlShaderProgram(Context, boolean)}. */
@Override
public int getLutTextureId(long presentationTimeUs) {
checkState(
lutTextureId != Format.NO_VALUE,
"The LUT has not been stored as a texture in OpenGL yet. You must to call"
+ " #toGlTextureProcessor() first.");
+ " #toGlShaderProgram() first.");
return lutTextureId;
}
@ -149,7 +149,7 @@ public class SingleColorLut implements ColorLut {
}
@Override
public SingleFrameGlTextureProcessor toGlTextureProcessor(Context context, boolean useHdr)
public SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws FrameProcessingException {
checkState(!useHdr, "HDR is currently not supported.");
@ -159,7 +159,7 @@ public class SingleColorLut implements ColorLut {
throw new FrameProcessingException("Could not store the LUT as a texture.", e);
}
return new ColorLutProcessor(context, /* colorLut= */ this, useHdr);
return new ColorLutShaderProgram(context, /* colorLut= */ this, useHdr);
}
private static int storeLutAsTexture(Bitmap bitmap) throws GlUtil.GlException {

View File

@ -31,14 +31,14 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* Manages a GLSL shader program for processing a frame. Implementations generally copy input pixels
* into an output frame, with changes to pixels specific to the implementation.
*
* <p>{@code SingleFrameGlTextureProcessor} implementations must produce exactly one output frame
* per input frame with the same presentation timestamp. For more flexibility, implement {@link
* GlTextureProcessor} directly.
* <p>{@code SingleFrameGlShaderProgram} implementations must produce exactly one output frame per
* input frame with the same presentation timestamp. For more flexibility, implement {@link
* GlShaderProgram} directly.
*
* <p>All methods in this class must be called on the thread that owns the OpenGL context.
*/
@UnstableApi
public abstract class SingleFrameGlTextureProcessor implements GlTextureProcessor {
public abstract class SingleFrameGlShaderProgram implements GlShaderProgram {
private final boolean useHdr;
@ -52,12 +52,12 @@ public abstract class SingleFrameGlTextureProcessor implements GlTextureProcesso
private boolean outputTextureInUse;
/**
* Creates a {@code SingleFrameGlTextureProcessor} instance.
* Creates a {@code SingleFrameGlShaderProgram} instance.
*
* @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.
*/
public SingleFrameGlTextureProcessor(boolean useHdr) {
public SingleFrameGlShaderProgram(boolean useHdr) {
this.useHdr = useHdr;
inputListener = new InputListener() {};
outputListener = new OutputListener() {};
@ -66,7 +66,7 @@ public abstract class SingleFrameGlTextureProcessor implements GlTextureProcesso
}
/**
* Configures the texture processor based on the input dimensions.
* Configures the instance based on the input dimensions.
*
* <p>This method must be called before {@linkplain #drawFrame(int,long) drawing} the first frame
* and before drawing subsequent frames with different input dimensions.
@ -81,9 +81,9 @@ public abstract class SingleFrameGlTextureProcessor implements GlTextureProcesso
/**
* Draws one frame.
*
* <p>This method may only be called after the texture processor has been {@link #configure(int,
* int) configured}. The caller is responsible for focussing the correct render target before
* calling this method.
* <p>This method may only be called after the shader program has been {@link #configure(int, int)
* configured}. The caller is responsible for focussing the correct render target before calling
* this method.
*
* <p>A minimal implementation should tell OpenGL to use its shader program, bind the shader
* program's vertex attributes and uniforms, and issue a drawing command.
@ -118,7 +118,7 @@ public abstract class SingleFrameGlTextureProcessor implements GlTextureProcesso
public final void queueInputFrame(TextureInfo inputTexture, long presentationTimeUs) {
checkState(
!outputTextureInUse,
"The texture processor does not currently accept input frames. Release prior output frames"
"The shader program does not currently accept input frames. Release prior output frames"
+ " first.");
try {

View File

@ -25,9 +25,9 @@ import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
/** Tests for {@link ChainingGlTextureProcessorListener}. */
/** Tests for {@link ChainingGlShaderProgramListener}. */
@RunWith(AndroidJUnit4.class)
public final class ChainingGlTextureProcessorListenerTest {
public final class ChainingGlShaderProgramListenerTest {
private static final long EXECUTOR_WAIT_TIME_MS = 100;
private final FrameProcessor.Listener mockFrameProcessorListener =
@ -35,13 +35,11 @@ public final class ChainingGlTextureProcessorListenerTest {
private final FrameProcessingTaskExecutor frameProcessingTaskExecutor =
new FrameProcessingTaskExecutor(
Util.newSingleThreadExecutor("Test"), mockFrameProcessorListener);
private final GlTextureProcessor mockProducingGlTextureProcessor = mock(GlTextureProcessor.class);
private final GlTextureProcessor mockConsumingGlTextureProcessor = mock(GlTextureProcessor.class);
private final ChainingGlTextureProcessorListener chainingGlTextureProcessorListener =
new ChainingGlTextureProcessorListener(
mockProducingGlTextureProcessor,
mockConsumingGlTextureProcessor,
frameProcessingTaskExecutor);
private final GlShaderProgram mockProducingGlShaderProgram = mock(GlShaderProgram.class);
private final GlShaderProgram mockConsumingGlShaderProgram = mock(GlShaderProgram.class);
private final ChainingGlShaderProgramListener chainingGlShaderProgramListener =
new ChainingGlShaderProgramListener(
mockProducingGlShaderProgram, mockConsumingGlShaderProgram, frameProcessingTaskExecutor);
@After
public void release() throws InterruptedException {
@ -49,47 +47,47 @@ public final class ChainingGlTextureProcessorListenerTest {
}
@Test
public void onInputFrameProcessed_surrendersFrameToPreviousGlTextureProcessor()
public void onInputFrameProcessed_surrendersFrameToPreviousGlShaderProgram()
throws InterruptedException {
TextureInfo texture =
new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100);
chainingGlTextureProcessorListener.onInputFrameProcessed(texture);
chainingGlShaderProgramListener.onInputFrameProcessed(texture);
Thread.sleep(EXECUTOR_WAIT_TIME_MS);
verify(mockProducingGlTextureProcessor).releaseOutputFrame(texture);
verify(mockProducingGlShaderProgram).releaseOutputFrame(texture);
}
@Test
public void onOutputFrameAvailable_afterAcceptsInputFrame_passesFrameToNextGlTextureProcessor()
public void onOutputFrameAvailable_afterAcceptsInputFrame_passesFrameToNextGlShaderProgram()
throws InterruptedException {
TextureInfo texture =
new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100);
long presentationTimeUs = 123;
chainingGlTextureProcessorListener.onReadyToAcceptInputFrame();
chainingGlTextureProcessorListener.onOutputFrameAvailable(texture, presentationTimeUs);
chainingGlShaderProgramListener.onReadyToAcceptInputFrame();
chainingGlShaderProgramListener.onOutputFrameAvailable(texture, presentationTimeUs);
Thread.sleep(EXECUTOR_WAIT_TIME_MS);
verify(mockConsumingGlTextureProcessor).queueInputFrame(texture, presentationTimeUs);
verify(mockConsumingGlShaderProgram).queueInputFrame(texture, presentationTimeUs);
}
@Test
public void onOutputFrameAvailable_beforeAcceptsInputFrame_passesFrameToNextGlTextureProcessor()
public void onOutputFrameAvailable_beforeAcceptsInputFrame_passesFrameToNextGlShaderProgram()
throws InterruptedException {
TextureInfo texture =
new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100);
long presentationTimeUs = 123;
chainingGlTextureProcessorListener.onOutputFrameAvailable(texture, presentationTimeUs);
chainingGlTextureProcessorListener.onReadyToAcceptInputFrame();
chainingGlShaderProgramListener.onOutputFrameAvailable(texture, presentationTimeUs);
chainingGlShaderProgramListener.onReadyToAcceptInputFrame();
Thread.sleep(EXECUTOR_WAIT_TIME_MS);
verify(mockConsumingGlTextureProcessor).queueInputFrame(texture, presentationTimeUs);
verify(mockConsumingGlShaderProgram).queueInputFrame(texture, presentationTimeUs);
}
@Test
public void onOutputFrameAvailable_twoFrames_passesFirstBeforeSecondToNextGlTextureProcessor()
public void onOutputFrameAvailable_twoFrames_passesFirstBeforeSecondToNextGlShaderProgram()
throws InterruptedException {
TextureInfo firstTexture =
new TextureInfo(/* texId= */ 1, /* fboId= */ 1, /* width= */ 100, /* height= */ 100);
@ -98,25 +96,22 @@ public final class ChainingGlTextureProcessorListenerTest {
new TextureInfo(/* texId= */ 2, /* fboId= */ 2, /* width= */ 100, /* height= */ 100);
long secondPresentationTimeUs = 567;
chainingGlTextureProcessorListener.onOutputFrameAvailable(
firstTexture, firstPresentationTimeUs);
chainingGlTextureProcessorListener.onOutputFrameAvailable(
secondTexture, secondPresentationTimeUs);
chainingGlTextureProcessorListener.onReadyToAcceptInputFrame();
chainingGlTextureProcessorListener.onReadyToAcceptInputFrame();
chainingGlShaderProgramListener.onOutputFrameAvailable(firstTexture, firstPresentationTimeUs);
chainingGlShaderProgramListener.onOutputFrameAvailable(secondTexture, secondPresentationTimeUs);
chainingGlShaderProgramListener.onReadyToAcceptInputFrame();
chainingGlShaderProgramListener.onReadyToAcceptInputFrame();
Thread.sleep(EXECUTOR_WAIT_TIME_MS);
verify(mockConsumingGlTextureProcessor).queueInputFrame(firstTexture, firstPresentationTimeUs);
verify(mockConsumingGlTextureProcessor)
.queueInputFrame(secondTexture, secondPresentationTimeUs);
verify(mockConsumingGlShaderProgram).queueInputFrame(firstTexture, firstPresentationTimeUs);
verify(mockConsumingGlShaderProgram).queueInputFrame(secondTexture, secondPresentationTimeUs);
}
@Test
public void onOutputStreamEnded_signalsInputStreamEndedToNextGlTextureProcessor()
public void onOutputStreamEnded_signalsInputStreamEndedToNextGlShaderProgram()
throws InterruptedException {
chainingGlTextureProcessorListener.onCurrentOutputStreamEnded();
chainingGlShaderProgramListener.onCurrentOutputStreamEnded();
Thread.sleep(EXECUTOR_WAIT_TIME_MS);
verify(mockConsumingGlTextureProcessor).signalEndOfCurrentInputStream();
verify(mockConsumingGlShaderProgram).signalEndOfCurrentInputStream();
}
}

View File

@ -25,8 +25,8 @@ import org.junit.runner.RunWith;
/**
* Unit tests for {@link ScaleToFitTransformation}.
*
* <p>See {@code MatrixTextureProcessorPixelTest} for pixel tests testing {@link
* MatrixTextureProcessor} given a transformation matrix.
* <p>See {@code MatrixShaderProgramPixelTest} for pixel tests testing {@link MatrixShaderProgram}
* given a transformation matrix.
*/
@RunWith(AndroidJUnit4.class)
public final class ScaleToFitTransformationTest {