diff --git a/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java b/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java index 164483c40b..53adf76baf 100644 --- a/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java +++ b/libraries/common/src/main/java/androidx/media3/common/VideoFrameProcessor.java @@ -49,7 +49,7 @@ public interface VideoFrameProcessor { /** A listener for frame processing events. */ @UnstableApi - public interface OnInputFrameProcessedListener { + interface OnInputFrameProcessedListener { /** Called when the given input frame has been processed. */ void onInputFrameProcessed(int textureId) throws VideoFrameProcessingException; @@ -291,18 +291,6 @@ public interface VideoFrameProcessor { */ void renderOutputFrame(long renderTimeNs); - /** - * Releases resources associated with all output frames with presentation time less than or equal - * to {@code presentationTimeUs}. - * - *
Not needed for outputting to an {@linkplain #setOutputSurfaceInfo output surface}, but may - * be required for other outputs. - * - * @param presentationTimeUs The presentation time where all frames before and at this time should - * be released, in microseconds. - */ - void releaseOutputFrame(long presentationTimeUs); - /** * Informs the {@code VideoFrameProcessor} that no further input frames should be accepted. * diff --git a/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java b/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java index f468bf22ba..58f9146f17 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java @@ -71,11 +71,24 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { /** Listener interface for texture output. */ @VisibleForTesting(otherwise = PACKAGE_PRIVATE) public interface TextureOutputListener { - /** Called when a texture has been rendered to. */ - void onTextureRendered(GlTextureInfo outputTexture, long presentationTimeUs) + /** + * Called when a texture has been rendered to. {@code releaseOutputTextureCallback} must be + * called to release the {@link GlTextureInfo}. + */ + void onTextureRendered( + GlTextureInfo outputTexture, + long presentationTimeUs, + ReleaseOutputTextureCallback releaseOutputTextureCallback) throws VideoFrameProcessingException; } + /** + * Releases the output information stored for textures before and at {@code presentationTimeUs}. + */ + public interface ReleaseOutputTextureCallback { + void release(long presentationTimeUs); + } + /** A factory for {@link DefaultVideoFrameProcessor} instances. */ public static final class Factory implements VideoFrameProcessor.Factory { @@ -118,9 +131,10 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { * Sets texture output settings. * *
If set, the {@link VideoFrameProcessor} will output to OpenGL textures, accessible via - * {@link TextureOutputListener#onTextureRendered}. Textures will stop being output when - * {@code textureOutputCapacity} is reached, until they're released via {@link - * #releaseOutputFrame}. Output textures must be released using {@link #releaseOutputFrame}. + * {@link TextureOutputListener#onTextureRendered}. Textures will stop being outputted when + * the number of output textures available reaches the {@code textureOutputCapacity}. To + * regain capacity, output textures must be released using {@link + * ReleaseOutputTextureCallback}. * *
If not set, there will be no texture output. * @@ -455,21 +469,6 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { () -> finalShaderProgramWrapper.renderOutputFrame(renderTimeNs)); } - /** - * {@inheritDoc} - * - *
If a {@link TextureOutputListener} {@linkplain Factory.Builder#setTextureOutput is set},
- * this must be called to release the output information stored in the {@link GlTextureInfo}
- * instances.
- */
- @Override
- public void releaseOutputFrame(long presentationTimeUs) {
- // TODO(b/262694346): Add Compositor system tests exercising this code path after GL texture
- // input is possible.
- videoFrameProcessingTaskExecutor.submit(
- () -> finalShaderProgramWrapper.releaseOutputFrame(presentationTimeUs));
- }
-
@Override
public void signalEndOfInput() {
DebugTraceUtil.recordVideoFrameProcessorReceiveDecoderEos();
@@ -610,6 +609,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
outputColorInfo,
enableColorTransfers,
renderFramesAutomatically,
+ videoFrameProcessingTaskExecutor,
executor,
listener,
glObjectsProvider,
@@ -661,6 +661,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
ColorInfo outputColorInfo,
boolean enableColorTransfers,
boolean renderFramesAutomatically,
+ VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor,
Executor executor,
Listener listener,
GlObjectsProvider glObjectsProvider,
@@ -714,6 +715,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
outputColorInfo,
enableColorTransfers,
renderFramesAutomatically,
+ videoFrameProcessingTaskExecutor,
executor,
listener,
glObjectsProvider,
diff --git a/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java b/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java
index d78696cb99..4805fb1017 100644
--- a/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java
+++ b/libraries/effect/src/main/java/androidx/media3/effect/FinalShaderProgramWrapper.java
@@ -85,6 +85,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final ColorInfo outputColorInfo;
private final boolean enableColorTransfers;
private final boolean renderFramesAutomatically;
+ private final VideoFrameProcessingTaskExecutor videoFrameProcessingTaskExecutor;
private final Executor videoFrameProcessorListenerExecutor;
private final VideoFrameProcessor.Listener videoFrameProcessorListener;
private final Queue Throws {@link IllegalStateException} if {@code textureInfo} isn't in use.
*/
public void freeTexture(GlTextureInfo textureInfo) {
+ // TODO(b/262694346): Check before adding to freeTexture, that this texture wasn't released
+ // already.
checkState(inUseTextures.contains(textureInfo));
inUseTextures.remove(textureInfo);
freeTextures.add(textureInfo);
@@ -120,6 +122,8 @@ import java.util.Queue;
* Throws {@link IllegalStateException} if there's no textures in use to free.
*/
public void freeTexture() {
+ // TODO(b/262694346): Check before adding to freeTexture, that this texture wasn't released
+ // already.
checkState(!inUseTextures.isEmpty());
GlTextureInfo texture = inUseTextures.remove();
freeTextures.add(texture);
@@ -127,6 +131,8 @@ import java.util.Queue;
/** Free all in-use textures. */
public void freeAllTextures() {
+ // TODO(b/262694346): Check before adding to freeTexture, that this texture wasn't released
+ // already.
freeTextures.addAll(inUseTextures);
inUseTextures.clear();
}
diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java
index f6b74328e9..17d1dce682 100644
--- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java
+++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/VideoFrameProcessorTestRunner.java
@@ -288,11 +288,7 @@ public final class VideoFrameProcessorTestRunner {
boolean useHighPrecisionColorComponents = ColorInfo.isTransferHdr(outputColorInfo);
@Nullable
Surface outputSurface =
- bitmapReader.getSurface(
- width,
- height,
- useHighPrecisionColorComponents,
- checkNotNull(videoFrameProcessor)::releaseOutputFrame);
+ bitmapReader.getSurface(width, height, useHighPrecisionColorComponents);
if (outputSurface != null) {
checkNotNull(videoFrameProcessor)
.setOutputSurfaceInfo(new SurfaceInfo(outputSurface, width, height));
@@ -407,18 +403,10 @@ public final class VideoFrameProcessorTestRunner {
/** Reads a {@link Bitmap} from {@link VideoFrameProcessor} output. */
public interface BitmapReader {
- /** Wraps a callback for {@link VideoFrameProcessor#releaseOutputFrame}. */
- interface ReleaseOutputFrameListener {
- void releaseOutputFrame(long releaseTimeUs);
- }
/** Returns the {@link VideoFrameProcessor} output {@link Surface}, if one is needed. */
@Nullable
- Surface getSurface(
- int width,
- int height,
- boolean useHighPrecisionColorComponents,
- ReleaseOutputFrameListener listener);
+ Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents);
/** Returns the output {@link Bitmap}. */
Bitmap getBitmap();
@@ -438,11 +426,7 @@ public final class VideoFrameProcessorTestRunner {
@Override
@SuppressLint("WrongConstant")
@Nullable
- public Surface getSurface(
- int width,
- int height,
- boolean useHighPrecisionColorComponents,
- ReleaseOutputFrameListener listener) {
+ public Surface getSurface(int width, int height, boolean useHighPrecisionColorComponents) {
imageReader =
ImageReader.newInstance(width, height, PixelFormat.RGBA_8888, /* maxImages= */ 1);
return imageReader.getSurface();
diff --git a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/DefaultVideoFrameProcessorTextureOutputPixelTest.java b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/DefaultVideoFrameProcessorTextureOutputPixelTest.java
index 63064b4746..3aec9e33eb 100644
--- a/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/DefaultVideoFrameProcessorTextureOutputPixelTest.java
+++ b/libraries/transformer/src/androidTest/java/androidx/media3/transformer/mh/DefaultVideoFrameProcessorTextureOutputPixelTest.java
@@ -507,14 +507,15 @@ public final class DefaultVideoFrameProcessorTextureOutputPixelTest {
DefaultVideoFrameProcessor.Factory defaultVideoFrameProcessorFactory =
new DefaultVideoFrameProcessor.Factory.Builder()
.setTextureOutput(
- (outputTexture, presentationTimeUs) ->
+ (outputTexture, presentationTimeUs, releaseOutputTextureCallback) ->
inputTextureIntoVideoFrameProcessor(
testId,
consumersBitmapReader,
colorInfo,
effects,
outputTexture,
- presentationTimeUs),
+ presentationTimeUs,
+ releaseOutputTextureCallback),
/* textureOutputCapacity= */ 1)
.build();
return new VideoFrameProcessorTestRunner.Builder()
@@ -533,7 +534,8 @@ public final class DefaultVideoFrameProcessorTextureOutputPixelTest {
ColorInfo colorInfo,
List