From 52dfe25542facce7f3e3b9af46a6f345ac42fd77 Mon Sep 17 00:00:00 2001 From: kimvde Date: Thu, 21 Nov 2024 04:57:24 -0800 Subject: [PATCH] Fix flushing issue in DefaultVideoFrameProcessor Before this CL, the following scenario could happen: - A new input stream is registered to the DefaultVideoFrameProcessor. - Before the pipeline is reconfigured, a seek is issued andd the DefaultVideoFrameProcessor is flushed. - As a result, the new input stream registration is never taken into account. As a result: - If an input stream is registered after the seek (before queueing any frame), registerInputStream will block indefinitely because inputStreamRegisteredCondition will be closed. - If a frame is queued after the seek, it will be linked to the input stream information of the previous frames. This CL makes sure that any pending input stream is registered after a flush. PiperOrigin-RevId: 698736866 --- .../effect/DefaultVideoFrameProcessor.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) 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 5459677180..c991bd5414 100644 --- a/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java +++ b/libraries/effect/src/main/java/androidx/media3/effect/DefaultVideoFrameProcessor.java @@ -516,14 +516,7 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { listenerExecutor.execute(listener::onEnded); DebugTraceUtil.logEvent(COMPONENT_VFP, EVENT_SIGNAL_ENDED, C.TIME_END_OF_SOURCE); } else { - synchronized (lock) { - if (pendingInputStreamInfo != null) { - InputStreamInfo pendingInputStreamInfo = this.pendingInputStreamInfo; - videoFrameProcessingTaskExecutor.submit( - () -> configure(pendingInputStreamInfo, /* forceReconfigure= */ false)); - this.pendingInputStreamInfo = null; - } - } + submitPendingInputStream(); } }); } @@ -762,6 +755,8 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { } catch (InterruptedException e) { Thread.currentThread().interrupt(); } + // Make sure any pending input stream is not swallowed. + submitPendingInputStream(); } @Override @@ -796,6 +791,17 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor { } } + private void submitPendingInputStream() { + synchronized (lock) { + if (pendingInputStreamInfo != null) { + InputStreamInfo pendingInputStreamInfo = this.pendingInputStreamInfo; + videoFrameProcessingTaskExecutor.submit( + () -> configure(pendingInputStreamInfo, /* forceReconfigure= */ false)); + this.pendingInputStreamInfo = null; + } + } + } + // Methods that must be called on the GL thread. /**