Skip to content

Commit

Permalink
Update effect to take in and use a GlObjectsProvider
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 514744747
  • Loading branch information
tof-tof authored and tonihei committed Mar 14, 2023
1 parent 0bec22f commit 82ab327
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.effect.GlShaderProgram;
import com.google.android.exoplayer2.util.GlObjectsProvider;
import com.google.android.exoplayer2.util.GlTextureInfo;
import com.google.android.exoplayer2.util.LibraryLoader;
import com.google.android.exoplayer2.util.Util;
Expand Down Expand Up @@ -159,6 +160,9 @@ public void setErrorListener(Executor executor, ErrorListener errorListener) {
() -> errorListener.onError(new VideoFrameProcessingException(error))));
}

@Override
public void setGlObjectsProvider(GlObjectsProvider glObjectsProvider) {}

@Override
public void queueInputFrame(GlTextureInfo inputTexture, long presentationTimeUs) {
AppTextureFrame appTextureFrame =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ public interface VideoFrameProcessor {

/** A factory for {@link VideoFrameProcessor} instances. */
interface Factory {

/**
* Sets the {@link GlObjectsProvider}.
*
* <p>Must be called before {@link #create}.
*/
Factory setGlObjectsProvider(GlObjectsProvider glObjectsProvider);

// TODO(271433904): Turn parameters with default values into setters.
/**
* Creates a new {@link VideoFrameProcessor} instance.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.DebugViewProvider;
import com.google.android.exoplayer2.util.FrameInfo;
import com.google.android.exoplayer2.util.GlObjectsProvider;
import com.google.android.exoplayer2.util.GlTextureInfo;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.android.exoplayer2.util.SurfaceInfo;
Expand Down Expand Up @@ -410,6 +411,9 @@ public void setOutputListener(OutputListener outputListener) {
@Override
public void setErrorListener(Executor executor, ErrorListener errorListener) {}

@Override
public void setGlObjectsProvider(GlObjectsProvider glObjectsProvider) {}

@Override
public void queueInputFrame(GlTextureInfo inputTexture, long presentationTimeUs) {
// No input is queued in these tests. The BlankFrameProducer is used to produce frames.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.google.android.exoplayer2.util.DebugViewProvider;
import com.google.android.exoplayer2.util.Effect;
import com.google.android.exoplayer2.util.FrameInfo;
import com.google.android.exoplayer2.util.GlObjectsProvider;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.android.exoplayer2.util.Log;
import com.google.android.exoplayer2.util.SurfaceInfo;
Expand All @@ -60,6 +61,20 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {

/** A factory for {@link DefaultVideoFrameProcessor} instances. */
public static final class Factory implements VideoFrameProcessor.Factory {
private GlObjectsProvider glObjectsProvider = GlObjectsProvider.DEFAULT;

/**
* {@inheritDoc}
*
* <p>The default value is {@link GlObjectsProvider#DEFAULT}.
*/
@Override
public DefaultVideoFrameProcessor.Factory setGlObjectsProvider(
GlObjectsProvider glObjectsProvider) {
this.glObjectsProvider = glObjectsProvider;
return this;
}

/**
* {@inheritDoc}
*
Expand Down Expand Up @@ -137,7 +152,8 @@ public DefaultVideoFrameProcessor create(
releaseFramesAutomatically,
singleThreadExecutorService,
listenerExecutor,
listener));
listener,
glObjectsProvider));

try {
return defaultVideoFrameProcessorFuture.get();
Expand Down Expand Up @@ -365,7 +381,8 @@ private static DefaultVideoFrameProcessor createOpenGlObjectsAndFrameProcessor(
boolean releaseFramesAutomatically,
ExecutorService singleThreadExecutorService,
Executor executor,
Listener listener)
Listener listener,
GlObjectsProvider glObjectsProvider)
throws GlUtil.GlException, VideoFrameProcessingException {
checkState(Thread.currentThread().getName().equals(THREAD_NAME));

Expand All @@ -378,7 +395,8 @@ private static DefaultVideoFrameProcessor createOpenGlObjectsAndFrameProcessor(
: GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888;
int openGlVersion =
ColorInfo.isTransferHdr(inputColorInfo) || ColorInfo.isTransferHdr(outputColorInfo) ? 3 : 2;
EGLContext eglContext = GlUtil.createEglContext(eglDisplay, openGlVersion, configAttributes);
EGLContext eglContext =
glObjectsProvider.createEglContext(eglDisplay, openGlVersion, configAttributes);
GlUtil.createFocusedPlaceholderEglSurface(eglContext, eglDisplay, configAttributes);

// Not releaseFramesAutomatically means outputting to a display surface. HDR display surfaces
Expand Down Expand Up @@ -407,6 +425,7 @@ private static DefaultVideoFrameProcessor createOpenGlObjectsAndFrameProcessor(
releaseFramesAutomatically,
executor,
listener);
setGlObjectProviderOnShaderPrograms(shaderPrograms, glObjectsProvider);
VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor =
new VideoFrameProcessingTaskExecutor(singleThreadExecutorService, listener);
chainShaderProgramsWithListeners(
Expand Down Expand Up @@ -520,6 +539,15 @@ private static ImmutableList<GlShaderProgram> getGlShaderProgramsForGlEffects(
return shaderProgramListBuilder.build();
}

/** Sets the {@link GlObjectsProvider} on all of the {@linkplain GlShaderProgram}s provided. */
private static void setGlObjectProviderOnShaderPrograms(
ImmutableList<GlShaderProgram> shaderPrograms, GlObjectsProvider glObjectsProvider) {
for (int i = 0; i < shaderPrograms.size() - 1; i++) {
GlShaderProgram shaderProgram = shaderPrograms.get(i);
shaderProgram.setGlObjectsProvider(glObjectsProvider);
}
}

/**
* Chains the given {@link GlShaderProgram} instances using {@link
* ChainingGlShaderProgramListener} instances.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.DebugViewProvider;
import com.google.android.exoplayer2.util.GlObjectsProvider;
import com.google.android.exoplayer2.util.GlTextureInfo;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.android.exoplayer2.util.Log;
Expand Down Expand Up @@ -86,9 +87,11 @@
private int inputHeight;
@Nullable private DefaultShaderProgram defaultShaderProgram;
@Nullable private SurfaceViewWrapper debugSurfaceViewWrapper;
private GlObjectsProvider glObjectsProvider;
private InputListener inputListener;
private @MonotonicNonNull Size outputSizeBeforeSurfaceTransformation;
@Nullable private SurfaceView debugSurfaceView;
private boolean frameProcessingStarted;

private volatile boolean outputSizeOrRotationChanged;

Expand Down Expand Up @@ -130,10 +133,19 @@ public FinalShaderProgramWrapper(

textureTransformMatrix = GlUtil.create4x4IdentityMatrix();
streamOffsetUsQueue = new ConcurrentLinkedQueue<>();
glObjectsProvider = GlObjectsProvider.DEFAULT;
inputListener = new InputListener() {};
availableFrames = new ConcurrentLinkedQueue<>();
}

@Override
public void setGlObjectsProvider(GlObjectsProvider glObjectsProvider) {
checkState(
!frameProcessingStarted,
"The GlObjectsProvider cannot be set after frame processing has started.");
this.glObjectsProvider = glObjectsProvider;
}

@Override
public void setInputListener(InputListener inputListener) {
this.inputListener = inputListener;
Expand All @@ -154,6 +166,7 @@ public void setErrorListener(Executor executor, ErrorListener errorListener) {

@Override
public void signalEndOfCurrentInputStream() {
frameProcessingStarted = true;
checkState(!streamOffsetUsQueue.isEmpty(), "No input stream to end.");
streamOffsetUsQueue.remove();
if (streamOffsetUsQueue.isEmpty()) {
Expand All @@ -178,6 +191,7 @@ public void appendStream(long streamOffsetUs) {

@Override
public void queueInputFrame(GlTextureInfo inputTexture, long presentationTimeUs) {
frameProcessingStarted = true;
long streamOffsetUs =
checkStateNotNull(streamOffsetUsQueue.peek(), "No input stream specified.");
long offsetPresentationTimeUs = presentationTimeUs + streamOffsetUs;
Expand All @@ -199,6 +213,7 @@ public void releaseOutputFrame(GlTextureInfo outputTexture) {
}

public void releaseOutputFrame(long releaseTimeNs) {
frameProcessingStarted = true;
checkState(!releaseFramesAutomatically);
Pair<GlTextureInfo, Long> oldestAvailableFrame = availableFrames.remove();
renderFrameToSurfaces(
Expand All @@ -209,6 +224,7 @@ public void releaseOutputFrame(long releaseTimeNs) {

@Override
public void flush() {
frameProcessingStarted = true;
// Drops all frames that aren't released yet.
availableFrames.clear();
if (defaultShaderProgram != null) {
Expand Down Expand Up @@ -304,7 +320,7 @@ private synchronized void maybeRenderFrameToOutputSurface(
outputEglSurface,
outputSurfaceInfo.width,
outputSurfaceInfo.height);
GlUtil.clearOutputFrame();
glObjectsProvider.clearOutputFrame();
defaultShaderProgram.drawFrame(inputTexture.texId, presentationTimeUs);

EGLExt.eglPresentationTimeANDROID(
Expand Down Expand Up @@ -446,7 +462,7 @@ private void maybeRenderFrameToDebugSurface(GlTextureInfo inputTexture, long pre
try {
debugSurfaceViewWrapper.maybeRenderToSurfaceView(
() -> {
GlUtil.clearOutputFrame();
glObjectsProvider.clearOutputFrame();
@C.ColorTransfer
int configuredColorTransfer = defaultShaderProgram.getOutputColorTransfer();
defaultShaderProgram.setOutputColorTransfer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import android.content.Context;
import android.opengl.GLES20;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.GlObjectsProvider;
import com.google.android.exoplayer2.util.GlProgram;
import com.google.android.exoplayer2.util.GlTextureInfo;
import com.google.android.exoplayer2.util.GlUtil;
Expand Down Expand Up @@ -49,10 +49,12 @@
private final int capacity;
private final boolean useHdr;

private GlObjectsProvider glObjectsProvider;
private InputListener inputListener;
private OutputListener outputListener;
private ErrorListener errorListener;
private Executor errorListenerExecutor;
private boolean frameProcessingStarted;

/** Creates a new instance. */
public FrameCacheGlShaderProgram(Context context, int capacity, boolean useHdr)
Expand Down Expand Up @@ -80,12 +82,21 @@ public FrameCacheGlShaderProgram(Context context, int capacity, boolean useHdr)
GlUtil.getNormalizedCoordinateBounds(),
GlUtil.HOMOGENEOUS_COORDINATE_VECTOR_SIZE);

glObjectsProvider = GlObjectsProvider.DEFAULT;
inputListener = new InputListener() {};
outputListener = new OutputListener() {};
errorListener = videoFrameProcessingException -> {};
errorListenerExecutor = MoreExecutors.directExecutor();
}

@Override
public void setGlObjectsProvider(GlObjectsProvider glObjectsProvider) {
checkState(
!frameProcessingStarted,
"The GlObjectsProvider cannot be set after frame processing has started.");
this.glObjectsProvider = glObjectsProvider;
}

@Override
public void setInputListener(InputListener inputListener) {
this.inputListener = inputListener;
Expand Down Expand Up @@ -115,6 +126,7 @@ public void setErrorListener(Executor errorListenerExecutor, ErrorListener error

@Override
public void queueInputFrame(GlTextureInfo inputTexture, long presentationTimeUs) {
frameProcessingStarted = true;
try {
configureAllOutputTextures(inputTexture.width, inputTexture.height);

Expand All @@ -125,7 +137,7 @@ public void queueInputFrame(GlTextureInfo inputTexture, long presentationTimeUs)
// Copy frame to fbo.
GlUtil.focusFramebufferUsingCurrentContext(
outputTexture.fboId, outputTexture.width, outputTexture.height);
GlUtil.clearOutputFrame();
glObjectsProvider.clearOutputFrame();
drawFrame(inputTexture.texId);
inputListener.onInputFrameProcessed(inputTexture);
outputListener.onOutputFrameAvailable(outputTexture, presentationTimeUs);
Expand All @@ -147,6 +159,7 @@ private void drawFrame(int inputTexId) throws GlUtil.GlException {

@Override
public void releaseOutputFrame(GlTextureInfo outputTexture) {
frameProcessingStarted = true;
checkState(inUseOutputTextures.contains(outputTexture));
inUseOutputTextures.remove(outputTexture);
freeOutputTextures.add(outputTexture);
Expand All @@ -155,11 +168,13 @@ public void releaseOutputFrame(GlTextureInfo outputTexture) {

@Override
public void signalEndOfCurrentInputStream() {
frameProcessingStarted = true;
outputListener.onCurrentOutputStreamEnded();
}

@Override
public void flush() {
frameProcessingStarted = true;
freeOutputTextures.addAll(inUseOutputTextures);
inUseOutputTextures.clear();
inputListener.onFlush();
Expand All @@ -170,6 +185,7 @@ public void flush() {

@Override
public void release() throws VideoFrameProcessingException {
frameProcessingStarted = true;
try {
deleteAllOutputTextures();
} catch (GlUtil.GlException e) {
Expand All @@ -196,9 +212,8 @@ private void createAllOutputTextures(int width, int height) throws GlUtil.GlExce
checkState(inUseOutputTextures.isEmpty());
for (int i = 0; i < capacity; i++) {
int outputTexId = GlUtil.createTexture(width, height, useHdr);
int outputFboId = GlUtil.createFboForTexture(outputTexId);
GlTextureInfo outputTexture =
new GlTextureInfo(outputTexId, outputFboId, /* rboId= */ C.INDEX_UNSET, width, height);
glObjectsProvider.createBuffersForTexture(outputTexId, width, height);
freeOutputTextures.add(outputTexture);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.effect;

import com.google.android.exoplayer2.util.GlObjectsProvider;
import com.google.android.exoplayer2.util.GlTextureInfo;
import com.google.android.exoplayer2.util.VideoFrameProcessingException;
import java.util.concurrent.Executor;
Expand Down Expand Up @@ -146,6 +147,13 @@ interface ErrorListener {
*/
void setErrorListener(Executor executor, ErrorListener errorListener);

/**
* Sets the {@link GlObjectsProvider}.
*
* <p>This method should not be called after any of the frame processing methods.
*/
void setGlObjectsProvider(GlObjectsProvider glObjectsProvider);

/**
* Processes an input frame if possible.
*
Expand Down
Loading

0 comments on commit 82ab327

Please sign in to comment.