Destroy EGLSurface immediately by focusing a placeholder surface
eglDestroySurface only destroys the surface when it's made not current. Pass the placeholder surface in FinalShaderProgramWrapper and use it when destroying eglSurface. PiperOrigin-RevId: 655139661
This commit is contained in:
parent
9c075b692e
commit
1797359950
@ -32,8 +32,10 @@ import android.graphics.Bitmap;
|
|||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
import android.opengl.EGLContext;
|
import android.opengl.EGLContext;
|
||||||
import android.opengl.EGLDisplay;
|
import android.opengl.EGLDisplay;
|
||||||
|
import android.opengl.EGLSurface;
|
||||||
import android.opengl.GLES20;
|
import android.opengl.GLES20;
|
||||||
import android.opengl.GLES30;
|
import android.opengl.GLES30;
|
||||||
|
import android.util.Pair;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.GuardedBy;
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
@ -813,7 +815,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
ColorInfo.isTransferHdr(outputColorInfo)
|
ColorInfo.isTransferHdr(outputColorInfo)
|
||||||
? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102
|
? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102
|
||||||
: GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888;
|
: GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_8888;
|
||||||
EGLContext eglContext =
|
Pair<EGLContext, EGLSurface> eglContextAndPlaceholderSurface =
|
||||||
createFocusedEglContextWithFallback(glObjectsProvider, eglDisplay, configAttributes);
|
createFocusedEglContextWithFallback(glObjectsProvider, eglDisplay, configAttributes);
|
||||||
|
|
||||||
ColorInfo linearColorInfo =
|
ColorInfo linearColorInfo =
|
||||||
@ -845,7 +847,8 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
new FinalShaderProgramWrapper(
|
new FinalShaderProgramWrapper(
|
||||||
context,
|
context,
|
||||||
eglDisplay,
|
eglDisplay,
|
||||||
eglContext,
|
eglContextAndPlaceholderSurface.first,
|
||||||
|
eglContextAndPlaceholderSurface.second,
|
||||||
debugViewProvider,
|
debugViewProvider,
|
||||||
outputColorInfo,
|
outputColorInfo,
|
||||||
videoFrameProcessingTaskExecutor,
|
videoFrameProcessingTaskExecutor,
|
||||||
@ -860,7 +863,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
context,
|
context,
|
||||||
glObjectsProvider,
|
glObjectsProvider,
|
||||||
eglDisplay,
|
eglDisplay,
|
||||||
eglContext,
|
eglContextAndPlaceholderSurface.first,
|
||||||
inputSwitcher,
|
inputSwitcher,
|
||||||
videoFrameProcessingTaskExecutor,
|
videoFrameProcessingTaskExecutor,
|
||||||
listener,
|
listener,
|
||||||
@ -1100,8 +1103,12 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates an OpenGL ES 3.0 context if possible, and an OpenGL ES 2.0 context otherwise. */
|
/**
|
||||||
private static EGLContext createFocusedEglContextWithFallback(
|
* Creates an OpenGL ES 3.0 context if possible, and an OpenGL ES 2.0 context otherwise.
|
||||||
|
*
|
||||||
|
* <p>See {@link #createFocusedEglContext}.
|
||||||
|
*/
|
||||||
|
private static Pair<EGLContext, EGLSurface> createFocusedEglContextWithFallback(
|
||||||
GlObjectsProvider glObjectsProvider, EGLDisplay eglDisplay, int[] configAttributes)
|
GlObjectsProvider glObjectsProvider, EGLDisplay eglDisplay, int[] configAttributes)
|
||||||
throws GlUtil.GlException {
|
throws GlUtil.GlException {
|
||||||
if (SDK_INT < 29) {
|
if (SDK_INT < 29) {
|
||||||
@ -1121,8 +1128,10 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
/**
|
/**
|
||||||
* Creates an {@link EGLContext} and focus it using a {@linkplain
|
* Creates an {@link EGLContext} and focus it using a {@linkplain
|
||||||
* GlObjectsProvider#createFocusedPlaceholderEglSurface placeholder EGL Surface}.
|
* GlObjectsProvider#createFocusedPlaceholderEglSurface placeholder EGL Surface}.
|
||||||
|
*
|
||||||
|
* @return The {@link EGLContext} and a placeholder {@link EGLSurface} as a {@link Pair}.
|
||||||
*/
|
*/
|
||||||
private static EGLContext createFocusedEglContext(
|
private static Pair<EGLContext, EGLSurface> createFocusedEglContext(
|
||||||
GlObjectsProvider glObjectsProvider,
|
GlObjectsProvider glObjectsProvider,
|
||||||
EGLDisplay eglDisplay,
|
EGLDisplay eglDisplay,
|
||||||
int openGlVersion,
|
int openGlVersion,
|
||||||
@ -1133,8 +1142,9 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
// Some OpenGL ES 3.0 contexts returned from createEglContext may throw EGL_BAD_MATCH when being
|
// Some OpenGL ES 3.0 contexts returned from createEglContext may throw EGL_BAD_MATCH when being
|
||||||
// used to createFocusedPlaceHolderEglSurface, despite GL documentation suggesting the contexts,
|
// used to createFocusedPlaceHolderEglSurface, despite GL documentation suggesting the contexts,
|
||||||
// if successfully created, are valid. Check early whether the context is really valid.
|
// if successfully created, are valid. Check early whether the context is really valid.
|
||||||
glObjectsProvider.createFocusedPlaceholderEglSurface(eglContext, eglDisplay);
|
EGLSurface eglSurface =
|
||||||
return eglContext;
|
glObjectsProvider.createFocusedPlaceholderEglSurface(eglContext, eglDisplay);
|
||||||
|
return Pair.create(eglContext, eglSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class InputStreamInfo {
|
private static final class InputStreamInfo {
|
||||||
|
@ -83,6 +83,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
private final List<RgbMatrix> rgbMatrices;
|
private final List<RgbMatrix> rgbMatrices;
|
||||||
private final EGLDisplay eglDisplay;
|
private final EGLDisplay eglDisplay;
|
||||||
private final EGLContext eglContext;
|
private final EGLContext eglContext;
|
||||||
|
private final EGLSurface placeholderSurface;
|
||||||
private final DebugViewProvider debugViewProvider;
|
private final DebugViewProvider debugViewProvider;
|
||||||
private final ColorInfo outputColorInfo;
|
private final ColorInfo outputColorInfo;
|
||||||
private final VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor;
|
private final VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor;
|
||||||
@ -129,6 +130,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
Context context,
|
Context context,
|
||||||
EGLDisplay eglDisplay,
|
EGLDisplay eglDisplay,
|
||||||
EGLContext eglContext,
|
EGLContext eglContext,
|
||||||
|
EGLSurface placeholderSurface,
|
||||||
DebugViewProvider debugViewProvider,
|
DebugViewProvider debugViewProvider,
|
||||||
ColorInfo outputColorInfo,
|
ColorInfo outputColorInfo,
|
||||||
VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor,
|
VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor,
|
||||||
@ -143,6 +145,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
this.rgbMatrices = new ArrayList<>();
|
this.rgbMatrices = new ArrayList<>();
|
||||||
this.eglDisplay = eglDisplay;
|
this.eglDisplay = eglDisplay;
|
||||||
this.eglContext = eglContext;
|
this.eglContext = eglContext;
|
||||||
|
this.placeholderSurface = placeholderSurface;
|
||||||
this.debugViewProvider = debugViewProvider;
|
this.debugViewProvider = debugViewProvider;
|
||||||
this.outputColorInfo = outputColorInfo;
|
this.outputColorInfo = outputColorInfo;
|
||||||
this.videoFrameProcessingTaskExecutor = videoFrameProcessingTaskExecutor;
|
this.videoFrameProcessingTaskExecutor = videoFrameProcessingTaskExecutor;
|
||||||
@ -354,16 +357,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
// outputEglSurface is a graphics buffer producer for a BufferQueue, and
|
// outputEglSurface is a graphics buffer producer for a BufferQueue, and
|
||||||
// this.outputSurfaceInfo.surface is the associated consumer. The consumer owns the
|
// this.outputSurfaceInfo.surface is the associated consumer. The consumer owns the
|
||||||
// BufferQueue https://source.android.com/docs/core/graphics/arch-bq-gralloc#BufferQueue.
|
// BufferQueue https://source.android.com/docs/core/graphics/arch-bq-gralloc#BufferQueue.
|
||||||
// If the consumer and the BufferQueue are released while the producer is still alive, EGL
|
// If the BufferQueue is released while the producer is still alive, EGL gets stuck trying
|
||||||
// gets stuck trying to dequeue a new buffer from the released BufferQueue. This probably
|
// to dequeue a new buffer from the released BufferQueue. This probably
|
||||||
// happens when the previously queued back buffer is ready for display.
|
// happens when the previously queued back buffer is ready for display.
|
||||||
try {
|
destroyOutputEglSurface();
|
||||||
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
|
|
||||||
} catch (GlUtil.GlException e) {
|
|
||||||
videoFrameProcessorListenerExecutor.execute(
|
|
||||||
() -> videoFrameProcessorListener.onError(VideoFrameProcessingException.from(e)));
|
|
||||||
}
|
|
||||||
this.outputEglSurface = null;
|
|
||||||
}
|
}
|
||||||
outputSurfaceInfoChanged =
|
outputSurfaceInfoChanged =
|
||||||
this.outputSurfaceInfo == null
|
this.outputSurfaceInfo == null
|
||||||
@ -374,6 +371,24 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
this.outputSurfaceInfo = outputSurfaceInfo;
|
this.outputSurfaceInfo = outputSurfaceInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private synchronized void destroyOutputEglSurface() {
|
||||||
|
if (outputEglSurface == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// outputEglSurface will be destroyed only if it's not current.
|
||||||
|
// See EGL docs. Make the placeholder surface current before destroying.
|
||||||
|
GlUtil.focusEglSurface(
|
||||||
|
eglDisplay, eglContext, placeholderSurface, /* width= */ 1, /* height= */ 1);
|
||||||
|
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
|
||||||
|
} catch (GlUtil.GlException e) {
|
||||||
|
videoFrameProcessorListenerExecutor.execute(
|
||||||
|
() -> videoFrameProcessorListener.onError(VideoFrameProcessingException.from(e)));
|
||||||
|
} finally {
|
||||||
|
this.outputEglSurface = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void renderFrame(
|
private synchronized void renderFrame(
|
||||||
GlObjectsProvider glObjectsProvider,
|
GlObjectsProvider glObjectsProvider,
|
||||||
GlTextureInfo inputTexture,
|
GlTextureInfo inputTexture,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user