Replace FrameProcessorChain#isEnded with listener method.
PiperOrigin-RevId: 455114693
This commit is contained in:
parent
ea7f1ca1e3
commit
fdfca88019
@ -89,9 +89,10 @@ public final class FrameProcessorChainPixelTest {
|
|||||||
private final AtomicReference<FrameProcessingException> frameProcessingException =
|
private final AtomicReference<FrameProcessingException> frameProcessingException =
|
||||||
new AtomicReference<>();
|
new AtomicReference<>();
|
||||||
|
|
||||||
|
private @MonotonicNonNull MediaFormat mediaFormat;
|
||||||
private @MonotonicNonNull FrameProcessorChain frameProcessorChain;
|
private @MonotonicNonNull FrameProcessorChain frameProcessorChain;
|
||||||
private volatile @MonotonicNonNull ImageReader outputImageReader;
|
private volatile @MonotonicNonNull ImageReader outputImageReader;
|
||||||
private @MonotonicNonNull MediaFormat mediaFormat;
|
private volatile boolean frameProcessingEnded;
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void release() {
|
public void release() {
|
||||||
@ -354,7 +355,17 @@ public final class FrameProcessorChainPixelTest {
|
|||||||
checkNotNull(
|
checkNotNull(
|
||||||
FrameProcessorChain.create(
|
FrameProcessorChain.create(
|
||||||
context,
|
context,
|
||||||
/* listener= */ this.frameProcessingException::set,
|
new FrameProcessorChain.Listener() {
|
||||||
|
@Override
|
||||||
|
public void onFrameProcessingError(FrameProcessingException exception) {
|
||||||
|
frameProcessingException.set(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFrameProcessingEnded() {
|
||||||
|
frameProcessingEnded = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
pixelWidthHeightRatio,
|
pixelWidthHeightRatio,
|
||||||
inputWidth,
|
inputWidth,
|
||||||
inputHeight,
|
inputHeight,
|
||||||
@ -421,7 +432,7 @@ public final class FrameProcessorChainPixelTest {
|
|||||||
private Bitmap processFirstFrameAndEnd() throws InterruptedException {
|
private Bitmap processFirstFrameAndEnd() throws InterruptedException {
|
||||||
checkNotNull(frameProcessorChain).signalEndOfInputStream();
|
checkNotNull(frameProcessorChain).signalEndOfInputStream();
|
||||||
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
Thread.sleep(FRAME_PROCESSING_WAIT_MS);
|
||||||
assertThat(frameProcessorChain.isEnded()).isTrue();
|
assertThat(frameProcessingEnded).isTrue();
|
||||||
assertThat(frameProcessingException.get()).isNull();
|
assertThat(frameProcessingException.get()).isNull();
|
||||||
|
|
||||||
Image frameProcessorChainOutputImage = checkNotNull(outputImageReader).acquireLatestImage();
|
Image frameProcessorChainOutputImage = checkNotNull(outputImageReader).acquireLatestImage();
|
||||||
|
@ -71,8 +71,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
* <p>This listener is only called from the {@link FrameProcessorChain}'s background thread.
|
* <p>This listener is only called from the {@link FrameProcessorChain}'s background thread.
|
||||||
*/
|
*/
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
/** Called when an exception occurs during asynchronous frame processing. */
|
/**
|
||||||
|
* Called when an exception occurs during asynchronous frame processing.
|
||||||
|
*
|
||||||
|
* <p>If an error occurred, consuming and producing further frames will not work as expected and
|
||||||
|
* the {@link FrameProcessorChain} should be released.
|
||||||
|
*/
|
||||||
void onFrameProcessingError(FrameProcessingException exception);
|
void onFrameProcessingError(FrameProcessingException exception);
|
||||||
|
|
||||||
|
/** Called after the frame processor has produced its final output frame. */
|
||||||
|
void onFrameProcessingEnded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -454,22 +462,24 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
return pendingFrameCount.get();
|
return pendingFrameCount.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Informs the {@code FrameProcessorChain} that no further input frames should be accepted. */
|
/**
|
||||||
|
* Informs the {@code FrameProcessorChain} that no further input frames should be accepted.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException If called more than once.
|
||||||
|
*/
|
||||||
public void signalEndOfInputStream() {
|
public void signalEndOfInputStream() {
|
||||||
|
checkState(!inputStreamEnded);
|
||||||
inputStreamEnded = true;
|
inputStreamEnded = true;
|
||||||
}
|
futures.add(singleThreadExecutorService.submit(this::signalEndOfOutputStream));
|
||||||
|
|
||||||
/** Returns whether all frames have been processed. */
|
|
||||||
public boolean isEnded() {
|
|
||||||
return inputStreamEnded && getPendingFrameCount() == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases all resources.
|
* Releases all resources.
|
||||||
*
|
*
|
||||||
* <p>If the frame processor chain is released before it has {@linkplain #isEnded() ended}, it
|
* <p>If the frame processor chain is released before it has {@linkplain
|
||||||
* will attempt to cancel processing any input frames that have already become available. Input
|
* Listener#onFrameProcessingEnded() ended}, it will attempt to cancel processing any input frames
|
||||||
* frames that become available after release are ignored.
|
* that have already become available. Input frames that become available after release are
|
||||||
|
* ignored.
|
||||||
*
|
*
|
||||||
* <p>This method blocks until all OpenGL resources are released or releasing times out.
|
* <p>This method blocks until all OpenGL resources are released or releasing times out.
|
||||||
*/
|
*/
|
||||||
@ -563,6 +573,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Calls {@link Listener#onFrameProcessingEnded()} once no more frames are pending. */
|
||||||
|
@WorkerThread
|
||||||
|
private void signalEndOfOutputStream() {
|
||||||
|
if (getPendingFrameCount() == 0) {
|
||||||
|
listener.onFrameProcessingEnded();
|
||||||
|
} else {
|
||||||
|
futures.add(singleThreadExecutorService.submit(this::signalEndOfOutputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Releases the {@link SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} and destroys
|
* Releases the {@link SingleFrameGlTextureProcessor SingleFrameGlTextureProcessors} and destroys
|
||||||
* the OpenGL context.
|
* the OpenGL context.
|
||||||
|
@ -51,8 +51,6 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
private final EncoderWrapper encoderWrapper;
|
private final EncoderWrapper encoderWrapper;
|
||||||
private final DecoderInputBuffer encoderOutputBuffer;
|
private final DecoderInputBuffer encoderOutputBuffer;
|
||||||
|
|
||||||
private boolean signaledEndOfStreamToEncoder;
|
|
||||||
|
|
||||||
public VideoTranscodingSamplePipeline(
|
public VideoTranscodingSamplePipeline(
|
||||||
Context context,
|
Context context,
|
||||||
Format inputFormat,
|
Format inputFormat,
|
||||||
@ -110,10 +108,23 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
frameProcessorChain =
|
frameProcessorChain =
|
||||||
FrameProcessorChain.create(
|
FrameProcessorChain.create(
|
||||||
context,
|
context,
|
||||||
/* listener= */ exception ->
|
new FrameProcessorChain.Listener() {
|
||||||
|
@Override
|
||||||
|
public void onFrameProcessingError(FrameProcessingException exception) {
|
||||||
asyncErrorListener.onTransformationException(
|
asyncErrorListener.onTransformationException(
|
||||||
TransformationException.createForFrameProcessorChain(
|
TransformationException.createForFrameProcessorChain(
|
||||||
exception, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED)),
|
exception, TransformationException.ERROR_CODE_GL_PROCESSING_FAILED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFrameProcessingEnded() {
|
||||||
|
try {
|
||||||
|
encoderWrapper.signalEndOfInputStream();
|
||||||
|
} catch (TransformationException exception) {
|
||||||
|
asyncErrorListener.onTransformationException(exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
inputFormat.pixelWidthHeightRatio,
|
inputFormat.pixelWidthHeightRatio,
|
||||||
/* inputWidth= */ decodedWidth,
|
/* inputWidth= */ decodedWidth,
|
||||||
/* inputHeight= */ decodedHeight,
|
/* inputHeight= */ decodedHeight,
|
||||||
@ -157,13 +168,6 @@ import org.checkerframework.dataflow.qual.Pure;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processData() throws TransformationException {
|
public boolean processData() throws TransformationException {
|
||||||
if (frameProcessorChain.isEnded()) {
|
|
||||||
if (!signaledEndOfStreamToEncoder) {
|
|
||||||
encoderWrapper.signalEndOfInputStream();
|
|
||||||
signaledEndOfStreamToEncoder = true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (decoder.isEnded()) {
|
if (decoder.isEnded()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user