Commit 65662371 by andrewlewis Committed by tonihei

Mark methods needing to be called on GL thread

Also remove @WorkerThread annotations, as static checks associated with
this annotation aren't useful in this part of the codebase because
almost no methods are called on the main thread.

This change should be a no-op.

PiperOrigin-RevId: 512060367
parent 51f8d103
......@@ -17,7 +17,6 @@
package com.google.android.exoplayer2.effect;
import android.content.Context;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.android.exoplayer2.util.VideoFrameProcessingException;
......@@ -39,9 +38,7 @@ 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 SingleFrameGlShaderProgram toGlShaderProgram(Context context, boolean useHdr)
throws VideoFrameProcessingException {
return new ColorLutShaderProgram(context, /* colorLut= */ this, useHdr);
......
......@@ -20,7 +20,6 @@ import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull;
import android.graphics.SurfaceTexture;
import android.view.Surface;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.effect.GlShaderProgram.InputListener;
import com.google.android.exoplayer2.util.FrameInfo;
......@@ -186,7 +185,15 @@ import java.util.concurrent.atomic.AtomicInteger;
surface.release();
}
@WorkerThread
private void maybeExecuteAfterFlushTask() {
if (onFlushCompleteTask == null || numberOfFramesToDropOnBecomingAvailable > 0) {
return;
}
videoFrameProcessingTaskExecutor.submitWithHighPriority(onFlushCompleteTask);
}
// Methods that must be called on the GL thread.
private void flush() {
// A frame that is registered before flush may arrive after flush.
numberOfFramesToDropOnBecomingAvailable = pendingFrames.size() - availableFrameCount;
......@@ -200,14 +207,6 @@ import java.util.concurrent.atomic.AtomicInteger;
maybeExecuteAfterFlushTask();
}
private void maybeExecuteAfterFlushTask() {
if (onFlushCompleteTask == null || numberOfFramesToDropOnBecomingAvailable > 0) {
return;
}
videoFrameProcessingTaskExecutor.submitWithHighPriority(onFlushCompleteTask);
}
@WorkerThread
private void maybeQueueFrameToExternalShaderProgram() {
if (externalShaderProgramInputCapacity.get() == 0
|| availableFrameCount == 0
......
......@@ -32,7 +32,6 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.DebugViewProvider;
import com.google.android.exoplayer2.util.GlUtil;
......@@ -153,6 +152,30 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@Override
public void signalEndOfCurrentInputStream() {
checkState(!streamOffsetUsQueue.isEmpty(), "No input stream to end.");
streamOffsetUsQueue.remove();
if (streamOffsetUsQueue.isEmpty()) {
videoFrameProcessorListenerExecutor.execute(videoFrameProcessorListener::onEnded);
}
}
/**
* Signals that there will be another input stream after all previously appended input streams
* have {@linkplain #signalEndOfCurrentInputStream() ended}.
*
* <p>This method does not need to be called on the GL thread, but the caller must ensure that
* stream offsets are appended in the correct order.
*
* @param streamOffsetUs The presentation timestamp offset, in microseconds.
*/
public void appendStream(long streamOffsetUs) {
streamOffsetUsQueue.add(streamOffsetUs);
}
// Methods that must be called on the GL thread.
@Override
public void queueInputFrame(TextureInfo inputTexture, long presentationTimeUs) {
long streamOffsetUs =
checkStateNotNull(streamOffsetUsQueue.peek(), "No input stream specified.");
......@@ -174,7 +197,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
throw new UnsupportedOperationException();
}
@WorkerThread
public void releaseOutputFrame(long releaseTimeNs) {
checkState(!releaseFramesAutomatically);
Pair<TextureInfo, Long> oldestAvailableFrame = availableFrames.remove();
......@@ -185,15 +207,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@Override
public void signalEndOfCurrentInputStream() {
checkState(!streamOffsetUsQueue.isEmpty(), "No input stream to end.");
streamOffsetUsQueue.remove();
if (streamOffsetUsQueue.isEmpty()) {
videoFrameProcessorListenerExecutor.execute(videoFrameProcessorListener::onEnded);
}
}
@Override
public void flush() {
// Drops all frames that aren't released yet.
availableFrames.clear();
......@@ -205,19 +218,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
@Override
@WorkerThread
public synchronized void release() throws VideoFrameProcessingException {
if (defaultShaderProgram != null) {
defaultShaderProgram.release();
}
try {
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
} catch (GlUtil.GlException e) {
throw new VideoFrameProcessingException(e);
}
}
@Override
public void setTextureTransformMatrix(float[] textureTransformMatrix) {
System.arraycopy(
/* src= */ textureTransformMatrix,
......@@ -231,17 +231,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
}
/**
* Signals that there will be another input stream after all previously appended input streams
* have {@linkplain #signalEndOfCurrentInputStream() ended}.
*
* <p>This method does not need to be called on the GL thread, but the caller must ensure that
* stream offsets are appended in the correct order.
*
* @param streamOffsetUs The presentation timestamp offset, in microseconds.
*/
public void appendStream(long streamOffsetUs) {
streamOffsetUsQueue.add(streamOffsetUs);
@Override
public synchronized void release() throws VideoFrameProcessingException {
if (defaultShaderProgram != null) {
defaultShaderProgram.release();
}
try {
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
} catch (GlUtil.GlException e) {
throw new VideoFrameProcessingException(e);
}
}
/**
......@@ -495,12 +494,36 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
height = surfaceView.getHeight();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {}
@Override
public synchronized void surfaceChanged(
SurfaceHolder holder, int format, int width, int height) {
this.width = width;
this.height = height;
Surface newSurface = holder.getSurface();
if (surface == null || !surface.equals(newSurface)) {
surface = newSurface;
eglSurface = null;
}
}
@Override
public synchronized void surfaceDestroyed(SurfaceHolder holder) {
surface = null;
eglSurface = null;
width = C.LENGTH_UNSET;
height = C.LENGTH_UNSET;
}
/**
* Focuses the wrapped surface view's surface as an {@link EGLSurface}, renders using {@code
* renderingTask} and swaps buffers, if the view's holder has a valid surface. Does nothing
* otherwise.
*
* <p>Must be called on the GL thread.
*/
@WorkerThread
public synchronized void maybeRenderToSurfaceView(VideoFrameProcessingTask renderingTask)
throws GlUtil.GlException, VideoFrameProcessingException {
if (surface == null) {
......@@ -519,28 +542,5 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// Prevents white flashing on the debug SurfaceView when frames are rendered too fast.
GLES20.glFinish();
}
@Override
public void surfaceCreated(SurfaceHolder holder) {}
@Override
public synchronized void surfaceChanged(
SurfaceHolder holder, int format, int width, int height) {
this.width = width;
this.height = height;
Surface newSurface = holder.getSurface();
if (surface == null || !surface.equals(newSurface)) {
surface = newSurface;
eglSurface = null;
}
}
@Override
public synchronized void surfaceDestroyed(SurfaceHolder holder) {
surface = null;
eglSurface = null;
width = C.LENGTH_UNSET;
height = C.LENGTH_UNSET;
}
}
}
......@@ -21,7 +21,6 @@ import static java.lang.Math.floor;
import android.graphics.Bitmap;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import androidx.annotation.WorkerThread;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.util.GlUtil;
import com.google.android.exoplayer2.util.VideoFrameProcessingException;
......@@ -34,7 +33,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
* Forwards a video frame produced from a {@link Bitmap} to a {@link GlShaderProgram} for
* consumption.
*
* <p>Methods in this class can be called from any thread.
* <p>Public methods in this class can be called from any thread.
*/
/* package */ final class InternalTextureManager implements GlShaderProgram.InputListener {
private final GlShaderProgram shaderProgram;
......@@ -99,7 +98,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
});
}
@WorkerThread
// Methods that must be called on the GL thread.
private void setupBitmap(Bitmap bitmap, long durationUs, float frameRate, boolean useHdr)
throws VideoFrameProcessingException {
this.useHdr = useHdr;
......@@ -113,7 +113,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
maybeQueueToShaderProgram();
}
@WorkerThread
private void maybeQueueToShaderProgram() throws VideoFrameProcessingException {
if (pendingBitmaps.isEmpty() || downstreamShaderProgramCapacity == 0) {
return;
......@@ -156,7 +155,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
}
@WorkerThread
private void maybeSignalEndOfOutput() {
if (framesToQueueForCurrentBitmap == 0
&& pendingBitmaps.isEmpty()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment