Fix transformer stuck forever

When the decoder output buffer was partially read, a call to
Codec.getOutputBuffer() was returning the same buffer, but with the
position reset to 0. The reason was that, in
Codec.maybeDequeueAndSetOutputBuffer(), mediaCodec.getOutputBuffer()
was called with the same buffer index (L350 in old rev), even though
there was already a buffer available (outputBufferIndex >=0). This
change avoids calling mediaCodec.getOutputBuffer() if the previous
buffer has not been released.

#minor-release

PiperOrigin-RevId: 424612197
This commit is contained in:
kimvde 2022-01-27 15:59:22 +00:00 committed by Andrew Lewis
parent 8123ef5d71
commit 8ec18086f2
2 changed files with 20 additions and 27 deletions

View File

@ -111,6 +111,7 @@
during a transformation.
* Add `TransformationRequest` for specifying the transformation options.
* Allow multiple listeners to be registered.
* Fix Transformer being stuck when the codec output is partially read.
* MediaSession extension:
* Remove deprecated call to `onStop(/* reset= */ true)` and provide an
opt-out flag for apps that don't want to clear the playlist on stop.

View File

@ -261,7 +261,7 @@ public final class Codec {
@Nullable
public Format getOutputFormat() throws TransformationException {
// The format is updated when dequeueing a 'special' buffer index, so attempt to dequeue now.
maybeDequeueOutputBuffer();
maybeDequeueOutputBuffer(/* setOutputBuffer= */ false);
return outputFormat;
}
@ -272,7 +272,7 @@ public final class Codec {
*/
@Nullable
public ByteBuffer getOutputBuffer() throws TransformationException {
return maybeDequeueAndSetOutputBuffer() ? outputBuffer : null;
return maybeDequeueOutputBuffer(/* setOutputBuffer= */ true) ? outputBuffer : null;
}
/**
@ -282,7 +282,7 @@ public final class Codec {
*/
@Nullable
public BufferInfo getOutputBufferInfo() throws TransformationException {
return maybeDequeueOutputBuffer() ? outputBufferInfo : null;
return maybeDequeueOutputBuffer(/* setOutputBuffer= */ false) ? outputBufferInfo : null;
}
/**
@ -334,33 +334,15 @@ public final class Codec {
}
/**
* Tries obtaining an output buffer and sets {@link #outputBuffer} to the obtained output buffer.
* Attempts to dequeue an output buffer if there is no output buffer pending. Does nothing
* otherwise.
*
* @return {@code true} if a buffer is successfully obtained, {@code false} otherwise.
* @param setOutputBuffer Whether to read the bytes of the dequeued output buffer and copy them
* into {@link #outputBuffer}.
* @return Whether there is an output buffer available.
* @throws TransformationException If the underlying {@link MediaCodec} encounters a problem.
*/
private boolean maybeDequeueAndSetOutputBuffer() throws TransformationException {
if (!maybeDequeueOutputBuffer()) {
return false;
}
try {
outputBuffer = checkNotNull(mediaCodec.getOutputBuffer(outputBufferIndex));
} catch (RuntimeException e) {
throw createTransformationException(e);
}
outputBuffer.position(outputBufferInfo.offset);
outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size);
return true;
}
/**
* Returns true if there is already an output buffer pending. Otherwise attempts to dequeue an
* output buffer and returns whether there is a new output buffer.
*
* @throws TransformationException If the underlying {@link MediaCodec} encounters a problem.
*/
private boolean maybeDequeueOutputBuffer() throws TransformationException {
private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) throws TransformationException {
if (outputBufferIndex >= 0) {
return true;
}
@ -391,6 +373,16 @@ public final class Codec {
releaseOutputBuffer();
return false;
}
if (setOutputBuffer) {
try {
outputBuffer = checkNotNull(mediaCodec.getOutputBuffer(outputBufferIndex));
} catch (RuntimeException e) {
throw createTransformationException(e);
}
outputBuffer.position(outputBufferInfo.offset);
outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size);
}
return true;
}