Store LUT bitmap as texture with processor creation.
* Before this CL, the texture was stored during the construction of the LUT processor. This failed since if one creates a list of GlEffects on the application thread, the texture will get stored in the application thread during the effect creation and not on the GL thread, which executes the FrameProcessors. * This is an issue since the executing thread then can't index from the texture stored on a different thread. PiperOrigin-RevId: 476388021 (cherry picked from commit 44b9aec0b973b1cd5df31df32fff276f340e6ce4)
This commit is contained in:
parent
a7102992ba
commit
09e0dd8505
@ -356,12 +356,15 @@ public final class GlUtil {
|
||||
// TODO(b/201293185): Consider handling adjustments for sizes > GL_MAX_TEXTURE_SIZE
|
||||
// (ex. downscaling appropriately) in a texture processor instead of asserting incorrect
|
||||
// values.
|
||||
|
||||
// For valid GL sizes, see:
|
||||
// https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glTexImage2D.xml
|
||||
int[] maxTextureSizeBuffer = new int[1];
|
||||
GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxTextureSizeBuffer, 0);
|
||||
int maxTextureSize = maxTextureSizeBuffer[0];
|
||||
checkState(
|
||||
maxTextureSize > 0,
|
||||
"Create a OpenGL context first or run the GL methods on an OpenGL thread.");
|
||||
|
||||
if (width < 0 || height < 0) {
|
||||
throw new GlException("width or height is less than 0");
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
package androidx.media3.effect;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.media3.common.FrameProcessingException;
|
||||
import androidx.media3.common.util.GlUtil;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
@ -40,7 +41,9 @@ public interface ColorLut extends GlEffect {
|
||||
/** Releases the OpenGL texture of the LUT. */
|
||||
void release() throws GlUtil.GlException;
|
||||
|
||||
/** This method must be executed on the same thread as other GL commands. */
|
||||
@Override
|
||||
@WorkerThread
|
||||
default ColorLutProcessor toGlTextureProcessor(Context context, boolean useHdr)
|
||||
throws FrameProcessingException {
|
||||
return new ColorLutProcessor(context, /* colorLut= */ this, useHdr);
|
||||
|
@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.opengl.GLES20;
|
||||
import android.opengl.GLUtils;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.FrameProcessingException;
|
||||
import androidx.media3.common.util.GlUtil;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
@ -31,8 +32,8 @@ import androidx.media3.common.util.Util;
|
||||
/** Transforms the colors of a frame by applying the same color lookup table to each frame. */
|
||||
@UnstableApi
|
||||
public class SingleColorLut implements ColorLut {
|
||||
private final int lutTextureId;
|
||||
private final int length;
|
||||
private final Bitmap lut;
|
||||
private int lutTextureId;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
@ -40,7 +41,7 @@ public class SingleColorLut implements ColorLut {
|
||||
* <p>{@code lutCube} needs to be a {@code N x N x N} cube and each element is an integer
|
||||
* representing a color using the {@link Bitmap.Config#ARGB_8888} format.
|
||||
*/
|
||||
public static SingleColorLut createFromCube(int[][][] lutCube) throws GlUtil.GlException {
|
||||
public static SingleColorLut createFromCube(int[][][] lutCube) {
|
||||
checkArgument(
|
||||
lutCube.length > 0 && lutCube[0].length > 0 && lutCube[0][0].length > 0,
|
||||
"LUT must have three dimensions.");
|
||||
@ -60,7 +61,7 @@ public class SingleColorLut implements ColorLut {
|
||||
* N^2}. Each element must be an integer representing a color using the {@link
|
||||
* Bitmap.Config#ARGB_8888} format.
|
||||
*/
|
||||
public static SingleColorLut createFromBitmap(Bitmap lut) throws GlUtil.GlException {
|
||||
public static SingleColorLut createFromBitmap(Bitmap lut) {
|
||||
checkArgument(
|
||||
lut.getWidth() * lut.getWidth() == lut.getHeight(),
|
||||
Util.formatInvariant(
|
||||
@ -72,18 +73,9 @@ public class SingleColorLut implements ColorLut {
|
||||
return new SingleColorLut(lut);
|
||||
}
|
||||
|
||||
private SingleColorLut(Bitmap lut) throws GlUtil.GlException {
|
||||
length = lut.getWidth();
|
||||
lutTextureId = storeLutAsTexture(lut);
|
||||
}
|
||||
|
||||
private static int storeLutAsTexture(Bitmap bitmap) throws GlUtil.GlException {
|
||||
int lutTextureId =
|
||||
GlUtil.createTexture(
|
||||
bitmap.getWidth(), bitmap.getHeight(), /* useHighPrecisionColorComponents= */ false);
|
||||
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, /* level= */ 0, bitmap, /* border= */ 0);
|
||||
GlUtil.checkGlError();
|
||||
return lutTextureId;
|
||||
private SingleColorLut(Bitmap lut) {
|
||||
this.lut = lut;
|
||||
lutTextureId = Format.NO_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -136,14 +128,19 @@ public class SingleColorLut implements ColorLut {
|
||||
Bitmap.Config.ARGB_8888);
|
||||
}
|
||||
|
||||
/** Must be called after {@link #toGlTextureProcessor(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.");
|
||||
return lutTextureId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength(long presentationTimeUs) {
|
||||
return length;
|
||||
return lut.getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -155,6 +152,22 @@ public class SingleColorLut implements ColorLut {
|
||||
public ColorLutProcessor toGlTextureProcessor(Context context, boolean useHdr)
|
||||
throws FrameProcessingException {
|
||||
checkState(!useHdr, "HDR is currently not supported.");
|
||||
|
||||
try {
|
||||
lutTextureId = storeLutAsTexture(lut);
|
||||
} catch (GlUtil.GlException e) {
|
||||
throw new FrameProcessingException("Could not store the LUT as a texture.", e);
|
||||
}
|
||||
|
||||
return new ColorLutProcessor(context, /* colorLut= */ this, useHdr);
|
||||
}
|
||||
|
||||
private static int storeLutAsTexture(Bitmap bitmap) throws GlUtil.GlException {
|
||||
int lutTextureId =
|
||||
GlUtil.createTexture(
|
||||
bitmap.getWidth(), bitmap.getHeight(), /* useHighPrecisionColorComponents= */ false);
|
||||
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, /* level= */ 0, bitmap, /* border= */ 0);
|
||||
GlUtil.checkGlError();
|
||||
return lutTextureId;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user