Commit 8ec18086 by kimvde Committed by Andrew Lewis

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
parent 8123ef5d
...@@ -111,6 +111,7 @@ ...@@ -111,6 +111,7 @@
during a transformation. during a transformation.
* Add `TransformationRequest` for specifying the transformation options. * Add `TransformationRequest` for specifying the transformation options.
* Allow multiple listeners to be registered. * Allow multiple listeners to be registered.
* Fix Transformer being stuck when the codec output is partially read.
* MediaSession extension: * MediaSession extension:
* Remove deprecated call to `onStop(/* reset= */ true)` and provide an * 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. opt-out flag for apps that don't want to clear the playlist on stop.
......
...@@ -261,7 +261,7 @@ public final class Codec { ...@@ -261,7 +261,7 @@ public final class Codec {
@Nullable @Nullable
public Format getOutputFormat() throws TransformationException { public Format getOutputFormat() throws TransformationException {
// The format is updated when dequeueing a 'special' buffer index, so attempt to dequeue now. // The format is updated when dequeueing a 'special' buffer index, so attempt to dequeue now.
maybeDequeueOutputBuffer(); maybeDequeueOutputBuffer(/* setOutputBuffer= */ false);
return outputFormat; return outputFormat;
} }
...@@ -272,7 +272,7 @@ public final class Codec { ...@@ -272,7 +272,7 @@ public final class Codec {
*/ */
@Nullable @Nullable
public ByteBuffer getOutputBuffer() throws TransformationException { public ByteBuffer getOutputBuffer() throws TransformationException {
return maybeDequeueAndSetOutputBuffer() ? outputBuffer : null; return maybeDequeueOutputBuffer(/* setOutputBuffer= */ true) ? outputBuffer : null;
} }
/** /**
...@@ -282,7 +282,7 @@ public final class Codec { ...@@ -282,7 +282,7 @@ public final class Codec {
*/ */
@Nullable @Nullable
public BufferInfo getOutputBufferInfo() throws TransformationException { public BufferInfo getOutputBufferInfo() throws TransformationException {
return maybeDequeueOutputBuffer() ? outputBufferInfo : null; return maybeDequeueOutputBuffer(/* setOutputBuffer= */ false) ? outputBufferInfo : null;
} }
/** /**
...@@ -334,33 +334,15 @@ public final class Codec { ...@@ -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. * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem.
*/ */
private boolean maybeDequeueAndSetOutputBuffer() throws TransformationException { private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) 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 {
if (outputBufferIndex >= 0) { if (outputBufferIndex >= 0) {
return true; return true;
} }
...@@ -391,6 +373,16 @@ public final class Codec { ...@@ -391,6 +373,16 @@ public final class Codec {
releaseOutputBuffer(); releaseOutputBuffer();
return false; 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; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment