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 ccf63f375b..cc648536bc 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java @@ -520,6 +520,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { private volatile @MonotonicNonNull FrameInfo nextInputFrameInfo; private volatile boolean inputStreamEnded; + private volatile boolean released; private DefaultVideoFrameProcessor( Context context, @@ -613,7 +614,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { @Override public boolean queueInputBitmap(Bitmap inputBitmap, TimestampIterator timestampIterator) { checkState(!inputStreamEnded); - if (!inputStreamRegisteredCondition.isOpen()) { + if (!inputStreamRegisteredCondition.isOpen() || released) { return false; } if (ColorInfo.isTransferHdr(outputColorInfo)) { @@ -633,7 +634,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { @Override public boolean queueInputTexture(int textureId, long presentationTimeUs) { checkState(!inputStreamEnded); - if (!inputStreamRegisteredCondition.isOpen()) { + if (!inputStreamRegisteredCondition.isOpen() || released) { return false; } @@ -714,6 +715,9 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { @Override public void registerInputStream( @InputType int inputType, Format format, List effects, long offsetToAddUs) { + if (released) { + return; + } // This method is only called after all samples in the current input stream are registered or // queued. DebugTraceUtil.logEvent( @@ -760,7 +764,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { checkState(!inputStreamEnded); checkStateNotNull( nextInputFrameInfo, "registerInputStream must be called before registering input frames"); - if (!inputStreamRegisteredCondition.isOpen()) { + if (!inputStreamRegisteredCondition.isOpen() || released) { return false; } inputSwitcher.activeTextureManager().registerInputFrame(nextInputFrameInfo); @@ -808,6 +812,9 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { DebugTraceUtil.logEvent(COMPONENT_VFP, EVENT_RECEIVE_END_OF_ALL_INPUT, C.TIME_END_OF_SOURCE); checkState(!inputStreamEnded); inputStreamEnded = true; + if (released) { + return; + } inputSwitcher.signalEndOfCurrentInputStream(); } @@ -849,6 +856,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { @Override public void release() { + released = true; try { videoFrameProcessingTaskExecutor.release(/* releaseTask= */ this::releaseGlObjects); } catch (InterruptedException e) { diff --git a/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java b/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java index 30f01c11b3..5dcc61d110 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/MultipleInputVideoGraph.java @@ -406,7 +406,6 @@ public final class MultipleInputVideoGraph implements VideoGraph { for (int i = 0; i < preProcessors.size(); i++) { preProcessors.get(preProcessors.keyAt(i)).release(); } - preProcessors.clear(); if (videoCompositor != null) { videoCompositor.release(); diff --git a/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java b/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java index 0f06cbd22b..f3ebc233dc 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/SingleInputVideoGraph.java @@ -301,10 +301,8 @@ public class SingleInputVideoGraph implements VideoGraph { if (released) { return; } - if (videoFrameProcessor != null) { videoFrameProcessor.release(); - videoFrameProcessor = null; } released = true; } diff --git a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java index b0c1123e3e..eb8d151546 100644 --- a/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java +++ b/libraries/transformer/src/main/java/androidx/media3/transformer/TransformerInternal.java @@ -629,6 +629,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Nullable @Override public SampleConsumer onOutputFormat(Format assetLoaderOutputFormat) throws ExportException { + if (released) { + return null; + } synchronized (assetLoaderLock) { if (!assetLoaderInputTracker.hasRegisteredAllTracks()) { return null;