Skip to content

Commit

Permalink
Add a method to disallow VFP destroying shared eglContext
Browse files Browse the repository at this point in the history
Previously in MultiInputVideoGraph, each VFP would destroy the shared
eglContext, such that the same eglContext object is destroyed multiple times.

Adding a flag to disallow this.

The alternative being we could add a flag on the VFP constructor, but I think
that is too subscriptive (meaning if we later might want to add another boolean
to control another GL behaviour, multiple booleans would make the class less
reason-able), and would incur a lot of code changes at places.

PiperOrigin-RevId: 660354367
(cherry picked from commit 8f8e487)
  • Loading branch information
claincly authored and tianyif committed Aug 21, 2024
1 parent efb7947 commit cd2a36f
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 17 deletions.
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
* DataSource:
* DRM:
* Effect:
* Add a `release()` method to `GlObjectsProvider`.
* Muxers:
* IMA extension:
* Session:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,11 @@ EGLSurface createFocusedPlaceholderEglSurface(EGLContext eglContext, EGLDisplay
* @throws GlException If an error occurs during creation.
*/
GlTextureInfo createBuffersForTexture(int texId, int width, int height) throws GlException;

/**
* Releases the created objects.
*
* @param eglDisplay The {@link EGLDisplay} to release the objects for.
*/
void release(EGLDisplay eglDisplay) throws GlException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package androidx.media3.effect;

import static androidx.media3.common.util.GlUtil.destroyEglContext;

import android.opengl.EGL14;
import android.opengl.EGLContext;
import android.opengl.EGLDisplay;
Expand All @@ -25,6 +27,8 @@
import androidx.media3.common.GlTextureInfo;
import androidx.media3.common.util.GlUtil;
import androidx.media3.common.util.UnstableApi;
import java.util.ArrayList;
import java.util.List;

// TODO(b/261820382): Add tests for sharing context.
/**
Expand All @@ -38,6 +42,7 @@
public final class DefaultGlObjectsProvider implements GlObjectsProvider {

private final EGLContext sharedEglContext;
private final List<EGLContext> createdEglContexts;

/** Creates an instance with no shared EGL context. */
public DefaultGlObjectsProvider() {
Expand All @@ -51,12 +56,16 @@ public DefaultGlObjectsProvider() {
*/
public DefaultGlObjectsProvider(@Nullable EGLContext sharedEglContext) {
this.sharedEglContext = sharedEglContext != null ? sharedEglContext : EGL14.EGL_NO_CONTEXT;
createdEglContexts = new ArrayList<>();
}

@Override
public EGLContext createEglContext(
EGLDisplay eglDisplay, int openGlVersion, int[] configAttributes) throws GlUtil.GlException {
return GlUtil.createEglContext(sharedEglContext, eglDisplay, openGlVersion, configAttributes);
EGLContext eglContext =
GlUtil.createEglContext(sharedEglContext, eglDisplay, openGlVersion, configAttributes);
createdEglContexts.add(eglContext);
return eglContext;
}

@Override
Expand All @@ -81,4 +90,11 @@ public GlTextureInfo createBuffersForTexture(int texId, int width, int height)
int fboId = GlUtil.createFboForTexture(texId);
return new GlTextureInfo(texId, fboId, /* rboId= */ C.INDEX_UNSET, width, height);
}

@Override
public void release(EGLDisplay eglDisplay) throws GlUtil.GlException {
for (int i = 0; i < createdEglContexts.size(); i++) {
destroyEglContext(eglDisplay, createdEglContexts.get(i));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -420,9 +420,9 @@ private void releaseGlObjects() {
Log.e(TAG, "Error releasing GL resources", e);
} finally {
try {
GlUtil.destroyEglContext(eglDisplay, eglContext);
glObjectsProvider.release(checkNotNull(eglDisplay));
} catch (GlUtil.GlException e) {
Log.e(TAG, "Error releasing GL context", e);
Log.e(TAG, "Error releasing GL objects", e);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.GlUtil.getDefaultEglDisplay;
import static androidx.media3.common.util.Util.SDK_INT;
import static androidx.media3.effect.DebugTraceUtil.COMPONENT_VFP;
import static androidx.media3.effect.DebugTraceUtil.EVENT_RECEIVE_END_OF_ALL_INPUT;
Expand Down Expand Up @@ -420,7 +421,6 @@ public DefaultVideoFrameProcessor create(
private final Context context;
private final GlObjectsProvider glObjectsProvider;
private final EGLDisplay eglDisplay;
private final EGLContext eglContext;
private final InputSwitcher inputSwitcher;
private final VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor;
private final VideoFrameProcessor.Listener listener;
Expand Down Expand Up @@ -454,18 +454,16 @@ private DefaultVideoFrameProcessor(
Context context,
GlObjectsProvider glObjectsProvider,
EGLDisplay eglDisplay,
EGLContext eglContext,
InputSwitcher inputSwitcher,
VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor,
VideoFrameProcessor.Listener listener,
Listener listener,
Executor listenerExecutor,
FinalShaderProgramWrapper finalShaderProgramWrapper,
boolean renderFramesAutomatically,
ColorInfo outputColorInfo) {
this.context = context;
this.glObjectsProvider = glObjectsProvider;
this.eglDisplay = eglDisplay;
this.eglContext = eglContext;
this.inputSwitcher = inputSwitcher;
this.videoFrameProcessingTaskExecutor = videoFrameProcessingTaskExecutor;
this.listener = listener;
Expand Down Expand Up @@ -774,7 +772,7 @@ private static DefaultVideoFrameProcessor createOpenGlObjectsAndFrameProcessor(
boolean experimentalAdjustSurfaceTextureTransformationMatrix,
boolean experimentalRepeatInputBitmapWithoutResampling)
throws GlUtil.GlException, VideoFrameProcessingException {
EGLDisplay eglDisplay = GlUtil.getDefaultEglDisplay();
EGLDisplay eglDisplay = getDefaultEglDisplay();
int[] configAttributes =
ColorInfo.isTransferHdr(outputColorInfo)
? GlUtil.EGL_CONFIG_ATTRIBUTES_RGBA_1010102
Expand Down Expand Up @@ -827,7 +825,6 @@ private static DefaultVideoFrameProcessor createOpenGlObjectsAndFrameProcessor(
context,
glObjectsProvider,
eglDisplay,
eglContextAndPlaceholderSurface.first,
inputSwitcher,
videoFrameProcessingTaskExecutor,
listener,
Expand Down Expand Up @@ -1052,9 +1049,9 @@ private void releaseGlObjects() {
}
} finally {
try {
GlUtil.destroyEglContext(eglDisplay, eglContext);
glObjectsProvider.release(eglDisplay);
} catch (GlUtil.GlException e) {
Log.e(TAG, "Error releasing GL context", e);
Log.e(TAG, "Error releasing GL objects", e);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.common.util.GlUtil.destroyEglContext;
import static androidx.media3.common.util.GlUtil.getDefaultEglDisplay;
import static androidx.media3.common.util.Util.contains;
import static androidx.media3.common.util.Util.newSingleThreadScheduledExecutor;
import static androidx.media3.effect.DebugTraceUtil.COMPONENT_COMPOSITOR;
Expand Down Expand Up @@ -47,6 +49,8 @@
import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.VideoGraph;
import androidx.media3.common.util.GlUtil;
import androidx.media3.common.util.GlUtil.GlException;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.UnstableApi;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.ArrayDeque;
Expand All @@ -61,6 +65,7 @@
@UnstableApi
public abstract class MultipleInputVideoGraph implements VideoGraph {

private static final String TAG = "MultiInputVG";
private static final String SHARED_EXECUTOR_NAME = "Effect:MultipleInputVideoGraph:Thread";

private static final long RELEASE_WAIT_TIME_MS = 1_000;
Expand All @@ -70,7 +75,7 @@ public abstract class MultipleInputVideoGraph implements VideoGraph {
private final Context context;

private final ColorInfo outputColorInfo;
private final GlObjectsProvider glObjectsProvider;
private final SingleContextGlObjectsProvider glObjectsProvider;
private final DebugViewProvider debugViewProvider;
private final VideoGraph.Listener listener;
private final Executor listenerExecutor;
Expand Down Expand Up @@ -299,6 +304,15 @@ public void release() {
compositionVideoFrameProcessor = null;
}

try {
// The eglContext is not released by any of the frame processors.
if (glObjectsProvider.singleEglContext != null) {
destroyEglContext(getDefaultEglDisplay(), glObjectsProvider.singleEglContext);
}
} catch (GlUtil.GlException e) {
Log.e(TAG, "Error releasing GL context", e);
}

sharedExecutorService.shutdown();
try {
sharedExecutorService.awaitTermination(RELEASE_WAIT_TIME_MS, MILLISECONDS);
Expand Down Expand Up @@ -460,8 +474,7 @@ public SingleContextGlObjectsProvider() {

@Override
public EGLContext createEglContext(
EGLDisplay eglDisplay, int openGlVersion, int[] configAttributes)
throws GlUtil.GlException {
EGLDisplay eglDisplay, int openGlVersion, int[] configAttributes) throws GlException {
if (singleEglContext == null) {
singleEglContext =
glObjectsProvider.createEglContext(eglDisplay, openGlVersion, configAttributes);
Expand All @@ -475,21 +488,26 @@ public EGLSurface createEglSurface(
Object surface,
@C.ColorTransfer int colorTransfer,
boolean isEncoderInputSurface)
throws GlUtil.GlException {
throws GlException {
return glObjectsProvider.createEglSurface(
eglDisplay, surface, colorTransfer, isEncoderInputSurface);
}

@Override
public EGLSurface createFocusedPlaceholderEglSurface(
EGLContext eglContext, EGLDisplay eglDisplay) throws GlUtil.GlException {
EGLContext eglContext, EGLDisplay eglDisplay) throws GlException {
return glObjectsProvider.createFocusedPlaceholderEglSurface(eglContext, eglDisplay);
}

@Override
public GlTextureInfo createBuffersForTexture(int texId, int width, int height)
throws GlUtil.GlException {
throws GlException {
return glObjectsProvider.createBuffersForTexture(texId, width, height);
}

@Override
public void release(EGLDisplay eglDisplay) {
// The eglContext is released in the VideoGraph after all VideoFrameProcessors are released.
}
}
}

0 comments on commit cd2a36f

Please sign in to comment.