Flush: VideoFrameProcessor texture output
PiperOrigin-RevId: 576928149
This commit is contained in:
parent
841b4fba9a
commit
346b9257ba
@ -547,6 +547,16 @@ public final class DefaultVideoFrameProcessor implements VideoFrameProcessor {
|
|||||||
inputSwitcher.signalEndOfInputStream();
|
inputSwitcher.signalEndOfInputStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* <p>The downstream frame consumer must be flushed before this instance is flushed, and stop
|
||||||
|
* accepting input until this DefaultVideoFrameProcessor instance finishes flushing.
|
||||||
|
*
|
||||||
|
* <p>After this method is called, any object consuming {@linkplain
|
||||||
|
* Factory.Builder#setTextureOutput texture output} must not access any output textures that were
|
||||||
|
* {@link GlTextureProducer.Listener#onTextureRendered rendered} before calling this method.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void flush() {
|
public void flush() {
|
||||||
if (!inputSwitcher.hasActiveInput()) {
|
if (!inputSwitcher.hasActiveInput()) {
|
||||||
|
@ -155,11 +155,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
@Override
|
@Override
|
||||||
public void setInputListener(InputListener inputListener) {
|
public void setInputListener(InputListener inputListener) {
|
||||||
this.inputListener = inputListener;
|
this.inputListener = inputListener;
|
||||||
int inputCapacity =
|
for (int i = 0; i < getInputCapacity(); i++) {
|
||||||
textureOutputListener == null
|
|
||||||
? SURFACE_INPUT_CAPACITY
|
|
||||||
: outputTexturePool.freeTextureCount();
|
|
||||||
for (int i = 0; i < inputCapacity; i++) {
|
|
||||||
inputListener.onReadyToAcceptInputFrame();
|
inputListener.onReadyToAcceptInputFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -254,20 +250,35 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void flush() {
|
public void flush() {
|
||||||
|
// The downstream consumer must already have been flushed, so the textureOutputListener
|
||||||
|
// implementation does not access its previously output textures, per its contract. However, the
|
||||||
|
// downstream consumer may not have called releaseOutputTexture on all these textures. Release
|
||||||
|
// all output textures that aren't already released.
|
||||||
|
if (textureOutputListener != null) {
|
||||||
|
outputTexturePool.freeAllTextures();
|
||||||
|
outputTextureTimestamps.clear();
|
||||||
|
syncObjects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Drops all frames that aren't rendered yet.
|
// Drops all frames that aren't rendered yet.
|
||||||
availableFrames.clear();
|
availableFrames.clear();
|
||||||
if (defaultShaderProgram != null) {
|
if (defaultShaderProgram != null) {
|
||||||
defaultShaderProgram.flush();
|
defaultShaderProgram.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signal flush upstream.
|
||||||
inputListener.onFlush();
|
inputListener.onFlush();
|
||||||
if (textureOutputListener == null) {
|
for (int i = 0; i < getInputCapacity(); i++) {
|
||||||
// TODO: b/293572152 - Add texture output flush() support, propagating the flush() signal to
|
|
||||||
// downstream components so that they can release TexturePool resources and FinalWrapper can
|
|
||||||
// call onReadyToAcceptInputFrame().
|
|
||||||
inputListener.onReadyToAcceptInputFrame();
|
inputListener.onReadyToAcceptInputFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getInputCapacity() {
|
||||||
|
return textureOutputListener == null
|
||||||
|
? SURFACE_INPUT_CAPACITY
|
||||||
|
: outputTexturePool.freeTextureCount();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void release() throws VideoFrameProcessingException {
|
public synchronized void release() throws VideoFrameProcessingException {
|
||||||
if (defaultShaderProgram != null) {
|
if (defaultShaderProgram != null) {
|
||||||
|
@ -119,6 +119,32 @@ public class DefaultVideoFrameProcessorMultipleTextureOutputPixelTest {
|
|||||||
.isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE_DIFFERENT_DEVICE);
|
.isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE_DIFFERENT_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This tests a condition that is difficult to synchronize, and is subject to a race
|
||||||
|
// condition. It may flake/fail if any queued frames are processed in the VideoFrameProcessor
|
||||||
|
// thread, before flush begins and cancels these pending frames. However, this is better than not
|
||||||
|
// testing this behavior at all, and in practice has succeeded every time on a 1000-time run.
|
||||||
|
// TODO: b/302695659 - Make this test more deterministic.
|
||||||
|
@Test
|
||||||
|
public void textureOutput_queueFiveBitmapsAndFlush_outputsOnlyAfterFlush() throws Exception {
|
||||||
|
String testId = "textureOutput_queueFiveBitmapsAndFlush_outputsOnlyAfterFlush";
|
||||||
|
videoFrameProcessorTestRunner = getFrameProcessorTestRunnerBuilder(testId).build();
|
||||||
|
ImmutableList<Long> inputTimestamps1 = ImmutableList.of(1_000_000L, 2_000_000L, 3_000_000L);
|
||||||
|
ImmutableList<Long> inputTimestamps2 = ImmutableList.of(4_000_000L, 5_000_000L, 6_000_000L);
|
||||||
|
|
||||||
|
queueBitmaps(videoFrameProcessorTestRunner, ORIGINAL_PNG_ASSET_PATH, inputTimestamps1);
|
||||||
|
videoFrameProcessorTestRunner.flush();
|
||||||
|
queueBitmaps(videoFrameProcessorTestRunner, MEDIA3_TEST_PNG_ASSET_PATH, inputTimestamps2);
|
||||||
|
videoFrameProcessorTestRunner.endFrameProcessing();
|
||||||
|
|
||||||
|
TextureBitmapReader textureBitmapReader = checkNotNull(this.textureBitmapReader);
|
||||||
|
Set<Long> actualOutputTimestamps = textureBitmapReader.getOutputTimestamps();
|
||||||
|
assertThat(actualOutputTimestamps).containsAtLeastElementsIn(inputTimestamps2).inOrder();
|
||||||
|
// This assertion is subject to flaking, per test comments. If it flakes, consider increasing
|
||||||
|
// the number of elements in inputTimestamps2.
|
||||||
|
assertThat(actualOutputTimestamps.size())
|
||||||
|
.isLessThan(inputTimestamps1.size() + inputTimestamps2.size());
|
||||||
|
}
|
||||||
|
|
||||||
private void queueBitmaps(
|
private void queueBitmaps(
|
||||||
VideoFrameProcessorTestRunner videoFrameProcessorTestRunner,
|
VideoFrameProcessorTestRunner videoFrameProcessorTestRunner,
|
||||||
String bitmapAssetPath,
|
String bitmapAssetPath,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user