From 80851807f2f97ed7c672374a05062862b8baf5fb Mon Sep 17 00:00:00 2001 From: hschlueter Date: Thu, 13 Jan 2022 15:32:21 +0000 Subject: [PATCH] Use specific error code for exceptions during encoding/decoding. After this change exceptions throw by MediaCodec during encoding/decoding will result in TransformationExceptions with ERROR_CODE_ENCODING_FAILED/ERROR_CODE_DECODING_FAILED. Before this change ERROR_CODE_FAILED_RUNTIME_CHECK was used. PiperOrigin-RevId: 421560396 --- .../transformer/AudioSamplePipeline.java | 22 +-- .../android/exoplayer2/transformer/Codec.java | 147 +++++++++++++++--- .../transformer/DefaultCodecFactory.java | 14 +- .../transformer/SamplePipeline.java | 10 +- .../transformer/TransformationException.java | 18 ++- .../transformer/TransformerBaseRenderer.java | 10 +- .../transformer/TransformerVideoRenderer.java | 6 +- .../transformer/VideoSamplePipeline.java | 10 +- 8 files changed, 184 insertions(+), 53 deletions(-) diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java index fb380296b9..505677d046 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioSamplePipeline.java @@ -113,17 +113,17 @@ import java.nio.ByteBuffer; @Override @Nullable - public DecoderInputBuffer dequeueInputBuffer() { + public DecoderInputBuffer dequeueInputBuffer() throws TransformationException { return decoder.maybeDequeueInputBuffer(decoderInputBuffer) ? decoderInputBuffer : null; } @Override - public void queueInputBuffer() { + public void queueInputBuffer() throws TransformationException { decoder.queueInputBuffer(decoderInputBuffer); } @Override - public boolean processData() { + public boolean processData() throws TransformationException { if (sonicAudioProcessor.isActive()) { return feedEncoderFromSonic() || feedSonicFromDecoder(); } else { @@ -133,13 +133,13 @@ import java.nio.ByteBuffer; @Override @Nullable - public Format getOutputFormat() { + public Format getOutputFormat() throws TransformationException { return encoder != null ? encoder.getOutputFormat() : null; } @Override @Nullable - public DecoderInputBuffer getOutputBuffer() { + public DecoderInputBuffer getOutputBuffer() throws TransformationException { if (encoder != null) { encoderOutputBuffer.data = encoder.getOutputBuffer(); if (encoderOutputBuffer.data != null) { @@ -152,7 +152,7 @@ import java.nio.ByteBuffer; } @Override - public void releaseOutputBuffer() { + public void releaseOutputBuffer() throws TransformationException { checkStateNotNull(encoder).releaseOutputBuffer(); } @@ -174,7 +174,7 @@ import java.nio.ByteBuffer; * Attempts to pass decoder output data to the encoder, and returns whether it may be possible to * pass more data immediately by calling this method again. */ - private boolean feedEncoderFromDecoder() { + private boolean feedEncoderFromDecoder() throws TransformationException { if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { return false; } @@ -203,7 +203,7 @@ import java.nio.ByteBuffer; * Attempts to pass audio processor output data to the encoder, and returns whether it may be * possible to pass more data immediately by calling this method again. */ - private boolean feedEncoderFromSonic() { + private boolean feedEncoderFromSonic() throws TransformationException { if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) { return false; } @@ -226,7 +226,7 @@ import java.nio.ByteBuffer; * Attempts to process decoder output data, and returns whether it may be possible to process more * data immediately by calling this method again. */ - private boolean feedSonicFromDecoder() { + private boolean feedSonicFromDecoder() throws TransformationException { if (drainingSonicForSpeedChange) { if (sonicAudioProcessor.isEnded() && !sonicOutputBuffer.hasRemaining()) { flushSonicAndSetSpeed(currentSpeed); @@ -267,7 +267,7 @@ import java.nio.ByteBuffer; * Feeds as much data as possible between the current position and limit of the specified {@link * ByteBuffer} to the encoder, and advances its position by the number of bytes fed. */ - private void feedEncoder(ByteBuffer inputBuffer) { + private void feedEncoder(ByteBuffer inputBuffer) throws TransformationException { ByteBuffer encoderInputBufferData = checkNotNull(encoderInputBuffer.data); int bufferLimit = inputBuffer.limit(); inputBuffer.limit(min(bufferLimit, inputBuffer.position() + encoderInputBufferData.capacity())); @@ -283,7 +283,7 @@ import java.nio.ByteBuffer; encoder.queueInputBuffer(encoderInputBuffer); } - private void queueEndOfStreamToEncoder() { + private void queueEndOfStreamToEncoder() throws TransformationException { checkState(checkNotNull(encoderInputBuffer.data).position() == 0); encoderInputBuffer.timeUs = nextEncoderInputBufferTimeUs; encoderInputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java index b95bc862a2..b898bb20a7 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/Codec.java @@ -107,6 +107,7 @@ public final class Codec { private final BufferInfo outputBufferInfo; private final MediaCodec mediaCodec; + private final Format configurationFormat; @Nullable private final Surface inputSurface; private @MonotonicNonNull Format outputFormat; @@ -117,15 +118,36 @@ public final class Codec { private boolean inputStreamEnded; private boolean outputStreamEnded; - /** Creates a {@code Codec} from a configured and started {@link MediaCodec}. */ - public Codec(MediaCodec mediaCodec, @Nullable Surface inputSurface) { + /** + * Creates a {@code Codec} from a configured and started {@link MediaCodec}. + * + * @param mediaCodec The configured and started {@link MediaCodec}. + * @param configurationFormat See {@link #getConfigurationFormat()}. + * @param inputSurface The input {@link Surface} if the {@link MediaCodec} receives input from a + * surface. + */ + public Codec(MediaCodec mediaCodec, Format configurationFormat, @Nullable Surface inputSurface) { this.mediaCodec = mediaCodec; + this.configurationFormat = configurationFormat; this.inputSurface = inputSurface; outputBufferInfo = new BufferInfo(); inputBufferIndex = C.INDEX_UNSET; outputBufferIndex = C.INDEX_UNSET; } + /** + * Returns the {@link Format} used for configuring the codec. + * + *

The configuration {@link Format} is the input {@link Format} used by the {@link + * DecoderFactory} or output {@link Format} used by the {@link EncoderFactory} for selecting and + * configuring the underlying {@link MediaCodec}. + */ + // TODO(b/214012830): Use this to check whether the Format passed to the factory and actual + // configuration format differ to see whether fallback was applied. + public Format getConfigurationFormat() { + return configurationFormat; + } + /** Returns the input {@link Surface}, or null if the input is not a surface. */ @Nullable public Surface getInputSurface() { @@ -137,18 +159,28 @@ public final class Codec { * * @param inputBuffer The buffer where the dequeued buffer data is stored. * @return Whether an input buffer is ready to be used. + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. */ @EnsuresNonNullIf(expression = "#1.data", result = true) - public boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) { + public boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) + throws TransformationException { if (inputStreamEnded) { return false; } if (inputBufferIndex < 0) { - inputBufferIndex = mediaCodec.dequeueInputBuffer(/* timeoutUs= */ 0); + try { + inputBufferIndex = mediaCodec.dequeueInputBuffer(/* timeoutUs= */ 0); + } catch (RuntimeException e) { + throw createTransformationException(e); + } if (inputBufferIndex < 0) { return false; } - inputBuffer.data = mediaCodec.getInputBuffer(inputBufferIndex); + try { + inputBuffer.data = mediaCodec.getInputBuffer(inputBufferIndex); + } catch (RuntimeException e) { + throw createTransformationException(e); + } inputBuffer.clear(); } checkNotNull(inputBuffer.data); @@ -158,8 +190,13 @@ public final class Codec { /** * Queues an input buffer to the decoder. No buffers may be queued after an {@link * DecoderInputBuffer#isEndOfStream() end of stream} buffer has been queued. + * + * @param inputBuffer The {@link DecoderInputBuffer input buffer}. + * @throws IllegalStateException If called again after an {@link + * DecoderInputBuffer#isEndOfStream() end of stream} buffer has been queued. + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. */ - public void queueInputBuffer(DecoderInputBuffer inputBuffer) { + public void queueInputBuffer(DecoderInputBuffer inputBuffer) throws TransformationException { checkState( !inputStreamEnded, "Input buffer can not be queued after the input stream has ended."); @@ -174,32 +211,64 @@ public final class Codec { inputStreamEnded = true; flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM; } - mediaCodec.queueInputBuffer(inputBufferIndex, offset, size, inputBuffer.timeUs, flags); + try { + mediaCodec.queueInputBuffer(inputBufferIndex, offset, size, inputBuffer.timeUs, flags); + } catch (RuntimeException e) { + throw createTransformationException(e); + } inputBufferIndex = C.INDEX_UNSET; inputBuffer.data = null; } - public void signalEndOfInputStream() { - mediaCodec.signalEndOfInputStream(); + /** + * Signals end-of-stream on input to a video encoder. + * + *

This method does not need to be called for audio/video decoders or audio encoders. For these + * the {@link MediaCodec#BUFFER_FLAG_END_OF_STREAM} flag should be set on the last input buffer + * {@link #queueInputBuffer(DecoderInputBuffer) queued}. + * + * @throws IllegalStateException If the codec is not an encoder receiving input from a {@link + * Surface}. + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. + */ + public void signalEndOfInputStream() throws TransformationException { + checkState(mediaCodec.getCodecInfo().isEncoder() && inputSurface != null); + try { + mediaCodec.signalEndOfInputStream(); + } catch (RuntimeException e) { + throw createTransformationException(e); + } } - /** Returns the current output format, if available. */ + /** + * Returns the current output format, if available. + * + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. + */ @Nullable - public Format getOutputFormat() { + public Format getOutputFormat() throws TransformationException { // The format is updated when dequeueing a 'special' buffer index, so attempt to dequeue now. maybeDequeueOutputBuffer(); return outputFormat; } - /** Returns the current output {@link ByteBuffer}, if available. */ + /** + * Returns the current output {@link ByteBuffer}, if available. + * + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. + */ @Nullable - public ByteBuffer getOutputBuffer() { + public ByteBuffer getOutputBuffer() throws TransformationException { return maybeDequeueAndSetOutputBuffer() ? outputBuffer : null; } - /** Returns the {@link BufferInfo} associated with the current output buffer, if available. */ + /** + * Returns the {@link BufferInfo} associated with the current output buffer, if available. + * + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. + */ @Nullable - public BufferInfo getOutputBufferInfo() { + public BufferInfo getOutputBufferInfo() throws TransformationException { return maybeDequeueOutputBuffer() ? outputBufferInfo : null; } @@ -208,8 +277,10 @@ public final class Codec { * *

This should be called after the buffer has been processed. The next output buffer will not * be available until the previous has been released. + * + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. */ - public void releaseOutputBuffer() { + public void releaseOutputBuffer() throws TransformationException { releaseOutputBuffer(/* render= */ false); } @@ -221,10 +292,17 @@ public final class Codec { * *

This should be called after the buffer has been processed. The next output buffer will not * be available until the previous has been released. + * + * @param render Whether the buffer needs to be sent to the output {@link Surface}. + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. */ - public void releaseOutputBuffer(boolean render) { + public void releaseOutputBuffer(boolean render) throws TransformationException { outputBuffer = null; - mediaCodec.releaseOutputBuffer(outputBufferIndex, render); + try { + mediaCodec.releaseOutputBuffer(outputBufferIndex, render); + } catch (RuntimeException e) { + throw createTransformationException(e); + } outputBufferIndex = C.INDEX_UNSET; } @@ -246,13 +324,18 @@ public final class Codec { * Tries obtaining an output buffer and sets {@link #outputBuffer} to the obtained output buffer. * * @return {@code true} if a buffer is successfully obtained, {@code false} otherwise. + * @throws TransformationException If the underlying {@link MediaCodec} encounters a problem. */ - private boolean maybeDequeueAndSetOutputBuffer() { + private boolean maybeDequeueAndSetOutputBuffer() throws TransformationException { if (!maybeDequeueOutputBuffer()) { return false; } - outputBuffer = checkNotNull(mediaCodec.getOutputBuffer(outputBufferIndex)); + try { + outputBuffer = checkNotNull(mediaCodec.getOutputBuffer(outputBufferIndex)); + } catch (RuntimeException e) { + throw createTransformationException(e); + } outputBuffer.position(outputBufferInfo.offset); outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size); return true; @@ -261,8 +344,10 @@ public final class Codec { /** * 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() { + private boolean maybeDequeueOutputBuffer() throws TransformationException { if (outputBufferIndex >= 0) { return true; } @@ -270,7 +355,11 @@ public final class Codec { return false; } - outputBufferIndex = mediaCodec.dequeueOutputBuffer(outputBufferInfo, /* timeoutUs= */ 0); + try { + outputBufferIndex = mediaCodec.dequeueOutputBuffer(outputBufferInfo, /* timeoutUs= */ 0); + } catch (RuntimeException e) { + throw createTransformationException(e); + } if (outputBufferIndex < 0) { if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { outputFormat = getFormat(mediaCodec.getOutputFormat()); @@ -292,6 +381,20 @@ public final class Codec { return true; } + private TransformationException createTransformationException(Exception cause) { + boolean isEncoder = mediaCodec.getCodecInfo().isEncoder(); + boolean isVideo = MimeTypes.isVideo(configurationFormat.sampleMimeType); + String componentName = (isVideo ? "Video" : "Audio") + (isEncoder ? "Encoder" : "Decoder"); + return TransformationException.createForCodec( + cause, + componentName, + configurationFormat, + mediaCodec.getName(), + isEncoder + ? TransformationException.ERROR_CODE_ENCODING_FAILED + : TransformationException.ERROR_CODE_DECODING_FAILED); + } + private static Format getFormat(MediaFormat mediaFormat) { ImmutableList.Builder csdBuffers = new ImmutableList.Builder<>(); int csdIndex = 0; diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodecFactory.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodecFactory.java index 80c43bd818..081e502ccf 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodecFactory.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/DefaultCodecFactory.java @@ -138,12 +138,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; if (inputSurface != null) { inputSurface.release(); } + @Nullable String mediaCodecName = null; if (mediaCodec != null) { + mediaCodecName = mediaCodec.getName(); mediaCodec.release(); } - throw createTransformationException(e, format, isVideo, isDecoder); + throw createTransformationException(e, format, isVideo, isDecoder, mediaCodecName); } - return new Codec(mediaCodec, inputSurface); + return new Codec(mediaCodec, format, inputSurface); } private static void configureCodec( @@ -167,13 +169,18 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; } private static TransformationException createTransformationException( - Exception cause, Format format, boolean isVideo, boolean isDecoder) { + Exception cause, + Format format, + boolean isVideo, + boolean isDecoder, + @Nullable String mediaCodecName) { String componentName = (isVideo ? "Video" : "Audio") + (isDecoder ? "Decoder" : "Encoder"); if (cause instanceof IOException || cause instanceof MediaCodec.CodecException) { return TransformationException.createForCodec( cause, componentName, format, + mediaCodecName, isDecoder ? TransformationException.ERROR_CODE_DECODER_INIT_FAILED : TransformationException.ERROR_CODE_ENCODER_INIT_FAILED); @@ -183,6 +190,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; cause, componentName, format, + mediaCodecName, isDecoder ? TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED : TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED); diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java index 62c94ee6c2..ebf7d1e0de 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java @@ -29,7 +29,7 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; /** Returns a buffer if the pipeline is ready to accept input, and {@code null} otherwise. */ @Nullable - DecoderInputBuffer dequeueInputBuffer(); + DecoderInputBuffer dequeueInputBuffer() throws TransformationException; /** * Informs the pipeline that its input buffer contains new input. @@ -37,7 +37,7 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; *

Should be called after filling the input buffer from {@link #dequeueInputBuffer()} with new * input. */ - void queueInputBuffer(); + void queueInputBuffer() throws TransformationException; /** * Processes the input data and returns whether more data can be processed by calling this method @@ -47,18 +47,18 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; /** Returns the output format of the pipeline if available, and {@code null} otherwise. */ @Nullable - Format getOutputFormat(); + Format getOutputFormat() throws TransformationException; /** Returns an output buffer if the pipeline has produced output, and {@code null} otherwise */ @Nullable - DecoderInputBuffer getOutputBuffer(); + DecoderInputBuffer getOutputBuffer() throws TransformationException; /** * Releases the pipeline's output buffer. * *

Should be called when the output buffer from {@link #getOutputBuffer()} is no longer needed. */ - void releaseOutputBuffer(); + void releaseOutputBuffer() throws TransformationException; /** Returns whether the pipeline has ended. */ boolean isEnded(); diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationException.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationException.java index ce93e13c39..c74901730a 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationException.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformationException.java @@ -21,6 +21,7 @@ import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.ElementType.TYPE_USE; +import android.media.MediaCodec; import android.os.SystemClock; import androidx.annotation.IntDef; import androidx.annotation.Nullable; @@ -216,14 +217,25 @@ public final class TransformationException extends Exception { * * @param cause The cause of the failure. * @param componentName The name of the component used, e.g. 'VideoEncoder'. - * @param format The {@link Format} used for the decoder/encoder. + * @param configurationFormat The {@link Format} used for configuring the decoder/encoder. + * @param mediaCodecName The name of the {@link MediaCodec} used, if known. * @param errorCode See {@link #errorCode}. * @return The created instance. */ public static TransformationException createForCodec( - Throwable cause, String componentName, Format format, int errorCode) { + Throwable cause, + String componentName, + Format configurationFormat, + @Nullable String mediaCodecName, + int errorCode) { return new TransformationException( - componentName + " error, format = " + format, cause, errorCode); + componentName + + " error, format = " + + configurationFormat + + ", mediaCodecName=" + + mediaCodecName, + cause, + errorCode); } /** diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java index 1e48226da6..eecb0cae62 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerBaseRenderer.java @@ -139,7 +139,8 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; protected abstract boolean ensureConfigured() throws TransformationException; @RequiresNonNull({"samplePipeline", "#1.data"}) - protected void maybeQueueSampleToPipeline(DecoderInputBuffer inputBuffer) { + protected void maybeQueueSampleToPipeline(DecoderInputBuffer inputBuffer) + throws TransformationException { samplePipeline.queueInputBuffer(); } @@ -147,9 +148,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * Attempts to write sample pipeline output data to the muxer. * * @return Whether it may be possible to write more data immediately by calling this method again. + * @throws Muxer.MuxerException If a muxing problem occurs. + * @throws TransformationException If a {@link SamplePipeline} problem occurs. */ @RequiresNonNull("samplePipeline") - private boolean feedMuxerFromPipeline() throws Muxer.MuxerException { + private boolean feedMuxerFromPipeline() throws Muxer.MuxerException, TransformationException { if (!muxerWrapperTrackAdded) { @Nullable Format samplePipelineOutputFormat = samplePipeline.getOutputFormat(); if (samplePipelineOutputFormat == null) { @@ -185,9 +188,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; * Attempts to read input data and pass the input data to the sample pipeline. * * @return Whether it may be possible to read more data immediately by calling this method again. + * @throws TransformationException If a {@link SamplePipeline} problem occurs. */ @RequiresNonNull("samplePipeline") - private boolean feedPipelineFromInput() { + private boolean feedPipelineFromInput() throws TransformationException { @Nullable DecoderInputBuffer samplePipelineInputBuffer = samplePipeline.dequeueInputBuffer(); if (samplePipelineInputBuffer == null) { return false; diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerVideoRenderer.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerVideoRenderer.java index a89b1cb81f..82968f888f 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerVideoRenderer.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/TransformerVideoRenderer.java @@ -122,10 +122,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull; /** * Queues the input buffer to the sample pipeline unless it should be dropped because of slow * motion flattening. + * + * @param inputBuffer The {@link DecoderInputBuffer}. + * @throws TransformationException If a {@link SamplePipeline} problem occurs. */ @Override @RequiresNonNull({"samplePipeline", "#1.data"}) - protected void maybeQueueSampleToPipeline(DecoderInputBuffer inputBuffer) { + protected void maybeQueueSampleToPipeline(DecoderInputBuffer inputBuffer) + throws TransformationException { ByteBuffer data = inputBuffer.data; boolean shouldDropSample = sefSlowMotionFlattener != null && sefSlowMotionFlattener.dropOrTransformSample(inputBuffer); diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java index c5f2f5d2a1..38e07e9d5b 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoSamplePipeline.java @@ -131,12 +131,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override @Nullable - public DecoderInputBuffer dequeueInputBuffer() { + public DecoderInputBuffer dequeueInputBuffer() throws TransformationException { return decoder.maybeDequeueInputBuffer(decoderInputBuffer) ? decoderInputBuffer : null; } @Override - public void queueInputBuffer() { + public void queueInputBuffer() throws TransformationException { decoder.queueInputBuffer(decoderInputBuffer); } @@ -217,7 +217,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override @Nullable - public Format getOutputFormat() { + public Format getOutputFormat() throws TransformationException { Format format = encoder.getOutputFormat(); return format == null ? null @@ -226,7 +226,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; @Override @Nullable - public DecoderInputBuffer getOutputBuffer() { + public DecoderInputBuffer getOutputBuffer() throws TransformationException { encoderOutputBuffer.data = encoder.getOutputBuffer(); if (encoderOutputBuffer.data == null) { return null; @@ -238,7 +238,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; } @Override - public void releaseOutputBuffer() { + public void releaseOutputBuffer() throws TransformationException { encoder.releaseOutputBuffer(); }