[go: nahoru, domu]

Skip to content

Commit

Permalink
Ensure single-frame videos are correctly exported
Browse files Browse the repository at this point in the history
Add a wait in DefaultCodec.signalEndOfInputStream when no
video encoder output has been seen. This avoids a thread synchronization problem
between writing frames to video surface, and signaling end of stream,
which was hit for video input of only one frame on some devices.

PiperOrigin-RevId: 637844690
  • Loading branch information
ychaparov authored and Copybara-Service committed May 28, 2024
1 parent 67b799c commit aadcbe3
Showing 1 changed file with 19 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import org.checkerframework.checker.initialization.qual.UnknownInitialization;
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
Expand All @@ -76,6 +77,9 @@ public final class DefaultCodec implements Codec {
private final int maxPendingFrameCount;
private final boolean isDecoder;
private final boolean isVideo;
// Accessed concurrently by playback thread when reading output, and video effects thread
// when signaling end of stream.
private final AtomicBoolean videoOutputStarted;

private @MonotonicNonNull Format outputFormat;
@Nullable private ByteBuffer outputBuffer;
Expand Down Expand Up @@ -112,6 +116,7 @@ public DefaultCodec(
outputBufferInfo = new BufferInfo();
inputBufferIndex = C.INDEX_UNSET;
outputBufferIndex = C.INDEX_UNSET;
videoOutputStarted = new AtomicBoolean();
DebugTraceUtil.logCodecEvent(
isDecoder, isVideo, EVENT_INPUT_FORMAT, C.TIME_UNSET, "%s", configurationFormat);

Expand Down Expand Up @@ -248,6 +253,17 @@ public void queueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportExcept

@Override
public void signalEndOfInputStream() throws ExportException {
if (!videoOutputStarted.get()) {
// When encoding a 1-frame video, there is a synchronization problem between feeding the frame
// to the encoder input surface and signaling end of stream. On some devices, sometimes,
// the frame gets lost and an empty output is produced. Waiting before signaling end of stream
// seems to resolve this issue. See b/301603935.
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
debugTraceLogEvent(EVENT_INPUT_ENDED, C.TIME_END_OF_SOURCE);
try {
mediaCodec.signalEndOfInputStream();
Expand Down Expand Up @@ -387,6 +403,9 @@ private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) throws ExportE
.setPcmEncoding(configurationFormat.pcmEncoding)
.build();
}
if (!isDecoder && isVideo) {
videoOutputStarted.set(true);
}
debugTraceLogEvent(
EVENT_OUTPUT_FORMAT, outputBufferInfo.presentationTimeUs, "%s", outputFormat);
}
Expand Down

0 comments on commit aadcbe3

Please sign in to comment.