Rename TransformationException to ExportException

PiperOrigin-RevId: 510062674
This commit is contained in:
kimvde 2023-02-16 08:26:48 +00:00 committed by christosts
parent 5410286955
commit c2fdab847f
38 changed files with 665 additions and 320 deletions

View File

@ -79,9 +79,9 @@ import androidx.media3.transformer.DefaultEncoderFactory;
import androidx.media3.transformer.DefaultMuxer;
import androidx.media3.transformer.EditedMediaItem;
import androidx.media3.transformer.Effects;
import androidx.media3.transformer.ExportException;
import androidx.media3.transformer.ExportResult;
import androidx.media3.transformer.ProgressHolder;
import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.Transformer;
import androidx.media3.ui.AspectRatioFrameLayout;
@ -311,15 +311,15 @@ public final class TransformerActivity extends AppCompatActivity {
public void onCompleted(Composition composition, ExportResult exportResult) {
MediaItem mediaItem =
composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
TransformerActivity.this.onTransformationCompleted(filePath, mediaItem);
TransformerActivity.this.onCompleted(filePath, mediaItem);
}
@Override
public void onError(
Composition composition,
ExportResult exportResult,
TransformationException exception) {
TransformerActivity.this.onTransformationError(exception);
ExportException exportException) {
TransformerActivity.this.onError(exportException);
}
})
.build();
@ -602,16 +602,16 @@ public final class TransformerActivity extends AppCompatActivity {
"debugFrame",
"transformationStopwatch",
})
private void onTransformationError(TransformationException exception) {
private void onError(ExportException exportException) {
if (transformationStopwatch.isRunning()) {
transformationStopwatch.stop();
}
informationTextView.setText(R.string.transformation_error);
progressViewGroup.setVisibility(View.GONE);
debugFrame.removeAllViews();
Toast.makeText(getApplicationContext(), "Transformation error: " + exception, Toast.LENGTH_LONG)
Toast.makeText(getApplicationContext(), "Export error: " + exportException, Toast.LENGTH_LONG)
.show();
Log.e(TAG, "Transformation error", exception);
Log.e(TAG, "Export error", exportException);
}
@RequiresNonNull({
@ -625,7 +625,7 @@ public final class TransformerActivity extends AppCompatActivity {
"debugFrame",
"transformationStopwatch",
})
private void onTransformationCompleted(String filePath, MediaItem inputMediaItem) {
private void onCompleted(String filePath, MediaItem inputMediaItem) {
transformationStopwatch.stop();
informationTextView.setText(
getString(

View File

@ -471,12 +471,12 @@ public final class AndroidTestUtil {
}
@Override
public Codec createForAudioEncoding(Format format) throws TransformationException {
public Codec createForAudioEncoding(Format format) throws ExportException {
return encoderFactory.createForAudioEncoding(format);
}
@Override
public Codec createForVideoEncoding(Format format) throws TransformationException {
public Codec createForVideoEncoding(Format format) throws ExportException {
return encoderFactory.createForVideoEncoding(format);
}
@ -531,7 +531,7 @@ public final class AndroidTestUtil {
/**
* Creates a {@link JSONObject} from the {@link Exception}.
*
* <p>If the exception is a {@link TransformationException}, {@code errorCode} is included.
* <p>If the exception is an {@link ExportException}, {@code errorCode} is included.
*
* @param exception The {@link Exception}.
* @return The {@link JSONObject} containing the exception details, or {@code null} if the
@ -546,8 +546,8 @@ public final class AndroidTestUtil {
JSONObject exceptionJson = new JSONObject();
exceptionJson.put("message", exception.getMessage());
exceptionJson.put("type", exception.getClass());
if (exception instanceof TransformationException) {
exceptionJson.put("errorCode", ((TransformationException) exception).errorCode);
if (exception instanceof ExportException) {
exceptionJson.put("errorCode", ((ExportException) exception).errorCode);
}
exceptionJson.put("stackTrace", Log.getThrowableString(exception));
return exceptionJson;

View File

@ -163,7 +163,7 @@ public class ExportTestResult {
.putOpt("filePath", filePath)
.putOpt("colorInfo", exportResult.colorInfo)
.putOpt("videoEncoderName", exportResult.videoEncoderName)
.putOpt("testException", exceptionAsJsonObject(exportResult.transformationException))
.putOpt("testException", exceptionAsJsonObject(exportResult.exportException))
.putOpt("analysisException", exceptionAsJsonObject(analysisException));
if (!exportResult.processedInputs.isEmpty()) {

View File

@ -189,8 +189,8 @@ public class TransformerAndroidTestRunner {
try {
ExportTestResult exportTestResult = runInternal(testId, editedMediaItem);
resultJson.put("exportResult", exportTestResult.asJsonObject());
if (exportTestResult.exportResult.transformationException != null) {
throw exportTestResult.exportResult.transformationException;
if (exportTestResult.exportResult.exportException != null) {
throw exportTestResult.exportResult.exportException;
}
if (!suppressAnalysisExceptions && exportTestResult.analysisException != null) {
throw exportTestResult.analysisException;
@ -274,7 +274,7 @@ public class TransformerAndroidTestRunner {
public void onError(
Composition composition,
ExportResult exportResult,
TransformationException exception) {
ExportException exportException) {
exportResultReference.set(exportResult);
countDownLatch.countDown();
}
@ -330,7 +330,7 @@ public class TransformerAndroidTestRunner {
@Nullable FallbackDetails fallbackDetails = fallbackDetailsReference.get();
ExportResult exportResult = checkNotNull(exportResultReference.get());
if (exportResult.transformationException != null) {
if (exportResult.exportException != null) {
return new ExportTestResult.Builder(exportResult)
.setElapsedTimeMs(elapsedTimeMs)
.setFallbackDetails(fallbackDetails)

View File

@ -121,9 +121,9 @@ public class TransformerEndToEndTest {
.setRemoveAudio(true)
.build();
TransformationException exception =
ExportException exception =
assertThrows(
TransformationException.class,
ExportException.class,
() ->
new TransformerAndroidTestRunner.Builder(context, transformer)
.build()
@ -132,8 +132,7 @@ public class TransformerEndToEndTest {
editedMediaItem));
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_ENCODER_INIT_FAILED);
assertThat(exception.errorCode).isEqualTo(ExportException.ERROR_CODE_ENCODER_INIT_FAILED);
assertThat(exception).hasMessageThat().contains("video");
}
@ -146,15 +145,15 @@ public class TransformerEndToEndTest {
}
@Override
public Codec createForAudioEncoding(Format format) throws TransformationException {
public Codec createForAudioEncoding(Format format) throws ExportException {
return encoderFactory.createForAudioEncoding(format);
}
@Override
public Codec createForVideoEncoding(Format format) throws TransformationException {
throw TransformationException.createForCodec(
public Codec createForVideoEncoding(Format format) throws ExportException {
throw ExportException.createForCodec(
new IllegalArgumentException(),
TransformationException.ERROR_CODE_ENCODER_INIT_FAILED,
ExportException.ERROR_CODE_ENCODER_INIT_FAILED,
/* isVideo= */ true,
/* isDecoder= */ false,
format);

View File

@ -27,8 +27,8 @@ import androidx.media3.common.C;
import androidx.media3.common.MediaItem;
import androidx.media3.common.util.Log;
import androidx.media3.transformer.AndroidTestUtil;
import androidx.media3.transformer.ExportException;
import androidx.media3.transformer.ExportTestResult;
import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.Transformer;
import androidx.media3.transformer.TransformerAndroidTestRunner;
@ -75,8 +75,8 @@ public class ForceInterpretHdrVideoAsSdrTest {
.run(testId, mediaItem);
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
Log.i(TAG, "Transformed.");
} catch (TransformationException exception) {
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
} catch (ExportException exception) {
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
throw exception;
}
}
@ -111,8 +111,8 @@ public class ForceInterpretHdrVideoAsSdrTest {
.run(testId, mediaItem);
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
Log.i(TAG, "Transformed.");
} catch (TransformationException exception) {
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
} catch (ExportException exception) {
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
throw exception;
}
}

View File

@ -36,8 +36,8 @@ import androidx.media3.effect.ScaleToFitTransformation;
import androidx.media3.transformer.EditedMediaItem;
import androidx.media3.transformer.Effects;
import androidx.media3.transformer.EncoderUtil;
import androidx.media3.transformer.ExportException;
import androidx.media3.transformer.ExportTestResult;
import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.Transformer;
import androidx.media3.transformer.TransformerAndroidTestRunner;
@ -83,13 +83,13 @@ public class HdrEditingTest {
.run(testId, mediaItem);
Log.i(TAG, "Transformed.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_ST2084);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isAnyOf(
TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
}
@ -108,13 +108,13 @@ public class HdrEditingTest {
.run(testId, mediaItem);
Log.i(TAG, "Transformed.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_HLG);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isAnyOf(
TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
}
@ -213,11 +213,11 @@ public class HdrEditingTest {
Log.i(TAG, "Tone mapped.");
assertThat(isToneMappingFallbackApplied.get()).isTrue();
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
assertThat(isFallbackListenerInvoked.get()).isFalse();
}
}
@ -267,11 +267,11 @@ public class HdrEditingTest {
Log.i(TAG, "Tone mapped.");
assertThat(isToneMappingFallbackApplied.get()).isTrue();
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
assertThat(isFallbackListenerInvoked.get()).isFalse();
}
}

View File

@ -30,8 +30,8 @@ import androidx.media3.common.util.Log;
import androidx.media3.effect.ScaleToFitTransformation;
import androidx.media3.transformer.EditedMediaItem;
import androidx.media3.transformer.Effects;
import androidx.media3.transformer.ExportException;
import androidx.media3.transformer.ExportTestResult;
import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.Transformer;
import androidx.media3.transformer.TransformerAndroidTestRunner;
@ -84,11 +84,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
.run(testId, mediaItem);
Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
}
@ -126,11 +126,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
.run(testId, mediaItem);
Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
}
@ -173,11 +173,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
.run(testId, editedMediaItem);
Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
}
@ -220,11 +220,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
.run(testId, editedMediaItem);
Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
} catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
}
}

View File

@ -31,8 +31,8 @@ import androidx.media3.common.util.GlUtil;
import androidx.media3.common.util.Log;
import androidx.media3.common.util.Util;
import androidx.media3.transformer.AndroidTestUtil;
import androidx.media3.transformer.ExportException;
import androidx.media3.transformer.ExportTestResult;
import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.Transformer;
import androidx.media3.transformer.TransformerAndroidTestRunner;
@ -91,9 +91,9 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
.build()
.run(testId, mediaItem);
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
Log.e(TAG, "Error during transformation.", exception);
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
} catch (ExportException exception) {
Log.e(TAG, "Error during export.", exception);
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
throw exception;
}
}
@ -141,9 +141,9 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
.build()
.run(testId, mediaItem);
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) {
Log.e(TAG, "Error during transformation.", exception);
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
} catch (ExportException exception) {
Log.e(TAG, "Error during export.", exception);
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
throw exception;
}
}

View File

@ -97,20 +97,20 @@ public interface AssetLoader {
* non-negative, in microseconds.
* @return The {@link SampleConsumer} describing the type of sample data expected, and to which
* to pass this data.
* @throws TransformationException If an error occurs configuring the {@link SampleConsumer}.
* @throws ExportException If an error occurs configuring the {@link SampleConsumer}.
*/
SampleConsumer onTrackAdded(
Format format,
@SupportedOutputTypes int supportedOutputTypes,
long streamStartPositionUs,
long streamOffsetUs)
throws TransformationException;
throws ExportException;
/**
* Called if an error occurs in the asset loader. In this case, the asset loader will be
* {@linkplain #release() released} automatically.
*/
void onError(TransformationException exception);
void onError(ExportException exportException);
}
/**

View File

@ -70,7 +70,7 @@ import org.checkerframework.dataflow.qual.Pure;
Codec.EncoderFactory encoderFactory,
MuxerWrapper muxerWrapper,
FallbackListener fallbackListener)
throws TransformationException {
throws ExportException {
super(firstInputFormat, streamStartPositionUs, muxerWrapper);
if (generateSilentAudioDurationUs != C.TIME_UNSET) {
@ -112,7 +112,7 @@ import org.checkerframework.dataflow.qual.Pure;
try {
encoderInputAudioFormat = audioProcessingPipeline.configure(pipelineInputAudioFormat);
} catch (AudioProcessor.UnhandledAudioFormatException unhandledAudioFormatException) {
throw TransformationException.createForAudioProcessing(
throw ExportException.createForAudioProcessing(
unhandledAudioFormatException, pipelineInputAudioFormat);
}
@ -175,7 +175,7 @@ import org.checkerframework.dataflow.qual.Pure;
}
@Override
protected boolean processDataUpToMuxer() throws TransformationException {
protected boolean processDataUpToMuxer() throws ExportException {
if (!audioProcessingPipeline.isOperational()) {
return feedEncoderFromInput();
}
@ -185,13 +185,13 @@ import org.checkerframework.dataflow.qual.Pure;
@Override
@Nullable
protected Format getMuxerInputFormat() throws TransformationException {
protected Format getMuxerInputFormat() throws ExportException {
return encoder.getOutputFormat();
}
@Override
@Nullable
protected DecoderInputBuffer getMuxerInputBuffer() throws TransformationException {
protected DecoderInputBuffer getMuxerInputBuffer() throws ExportException {
encoderOutputBuffer.data = encoder.getOutputBuffer();
if (encoderOutputBuffer.data == null) {
return null;
@ -202,7 +202,7 @@ import org.checkerframework.dataflow.qual.Pure;
}
@Override
protected void releaseMuxerInputBuffer() throws TransformationException {
protected void releaseMuxerInputBuffer() throws ExportException {
encoder.releaseOutputBuffer(/* render= */ false);
}
@ -216,7 +216,7 @@ import org.checkerframework.dataflow.qual.Pure;
*
* @return Whether it may be possible to feed more data immediately by calling this method again.
*/
private boolean feedEncoderFromInput() throws TransformationException {
private boolean feedEncoderFromInput() throws ExportException {
if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) {
return false;
}
@ -254,7 +254,7 @@ import org.checkerframework.dataflow.qual.Pure;
*
* @return Whether it may be possible to feed more data immediately by calling this method again.
*/
private boolean feedEncoderFromProcessingPipeline() throws TransformationException {
private boolean feedEncoderFromProcessingPipeline() throws ExportException {
if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) {
return false;
}
@ -320,7 +320,7 @@ import org.checkerframework.dataflow.qual.Pure;
* 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) throws TransformationException {
private void feedEncoder(ByteBuffer inputBuffer) throws ExportException {
ByteBuffer encoderInputBufferData = checkNotNull(encoderInputBuffer.data);
int bufferLimit = inputBuffer.limit();
inputBuffer.limit(min(bufferLimit, inputBuffer.position() + encoderInputBufferData.capacity()));
@ -336,7 +336,7 @@ import org.checkerframework.dataflow.qual.Pure;
encoder.queueInputBuffer(encoderInputBuffer);
}
private void queueEndOfStreamToEncoder() throws TransformationException {
private void queueEndOfStreamToEncoder() throws ExportException {
checkState(checkNotNull(encoderInputBuffer.data).position() == 0);
encoderInputBuffer.timeUs = nextEncoderInputBufferTimeUs;
encoderInputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);

View File

@ -31,7 +31,7 @@ import androidx.media3.common.Format;
}
@Override
public Codec createForAudioDecoding(Format format) throws TransformationException {
public Codec createForAudioDecoding(Format format) throws ExportException {
Codec audioDecoder = decoderFactory.createForAudioDecoding(format);
audioDecoderName = audioDecoder.getName();
return audioDecoder;
@ -39,8 +39,7 @@ import androidx.media3.common.Format;
@Override
public Codec createForVideoDecoding(
Format format, Surface outputSurface, boolean requestSdrToneMapping)
throws TransformationException {
Format format, Surface outputSurface, boolean requestSdrToneMapping) throws ExportException {
Codec videoDecoder =
decoderFactory.createForVideoDecoding(format, outputSurface, requestSdrToneMapping);
videoDecoderName = videoDecoder.getName();

View File

@ -30,14 +30,14 @@ import androidx.media3.common.Format;
}
@Override
public Codec createForAudioEncoding(Format format) throws TransformationException {
public Codec createForAudioEncoding(Format format) throws ExportException {
Codec audioEncoder = encoderFactory.createForAudioEncoding(format);
audioEncoderName = audioEncoder.getName();
return audioEncoder;
}
@Override
public Codec createForVideoEncoding(Format format) throws TransformationException {
public Codec createForVideoEncoding(Format format) throws ExportException {
Codec videoEncoder = encoderFactory.createForVideoEncoding(format);
videoEncoderName = videoEncoder.getName();
return videoEncoder;

View File

@ -42,9 +42,9 @@ public interface Codec {
* @param format The {@link Format} (of the input data) used to determine the underlying decoder
* and its configuration values.
* @return A {@link Codec} for audio decoding.
* @throws TransformationException If no suitable {@link Codec} can be created.
* @throws ExportException If no suitable {@link Codec} can be created.
*/
Codec createForAudioDecoding(Format format) throws TransformationException;
Codec createForAudioDecoding(Format format) throws ExportException;
/**
* Returns a {@link Codec} for video decoding.
@ -54,11 +54,10 @@ public interface Codec {
* @param outputSurface The {@link Surface} to which the decoder output is rendered.
* @param requestSdrToneMapping Whether to request tone-mapping to SDR.
* @return A {@link Codec} for video decoding.
* @throws TransformationException If no suitable {@link Codec} can be created.
* @throws ExportException If no suitable {@link Codec} can be created.
*/
Codec createForVideoDecoding(
Format format, Surface outputSurface, boolean requestSdrToneMapping)
throws TransformationException;
Format format, Surface outputSurface, boolean requestSdrToneMapping) throws ExportException;
}
/** A factory for {@linkplain Codec encoder} instances. */
@ -76,9 +75,9 @@ public interface Codec {
* those of the desired output video format.
* @return A {@link Codec} for encoding audio to the requested {@link Format#sampleMimeType MIME
* type}.
* @throws TransformationException If no suitable {@link Codec} can be created.
* @throws ExportException If no suitable {@link Codec} can be created.
*/
Codec createForAudioEncoding(Format format) throws TransformationException;
Codec createForAudioEncoding(Format format) throws ExportException;
/**
* Returns a {@link Codec} for video encoding.
@ -96,9 +95,9 @@ public interface Codec {
* Format#height}, therefore the video is always in landscape orientation.
* @return A {@link Codec} for encoding video to the requested {@linkplain Format#sampleMimeType
* MIME type}.
* @throws TransformationException If no suitable {@link Codec} can be created.
* @throws ExportException If no suitable {@link Codec} can be created.
*/
Codec createForVideoEncoding(Format format) throws TransformationException;
Codec createForVideoEncoding(Format format) throws ExportException;
/** Returns whether the audio needs to be encoded because of encoder specific configuration. */
default boolean audioNeedsEncoding() {
@ -148,9 +147,9 @@ public interface Codec {
* @param inputBuffer The buffer where the dequeued buffer data is stored, at {@link
* DecoderInputBuffer#data inputBuffer.data}.
* @return Whether an input buffer is ready to be used.
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
* @throws ExportException If the underlying decoder or encoder encounters a problem.
*/
boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) throws TransformationException;
boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException;
/**
* Queues an input buffer to the {@code Codec}. No buffers may be queued after {@linkplain
@ -160,9 +159,9 @@ public interface Codec {
* to receive input.
*
* @param inputBuffer The {@linkplain DecoderInputBuffer input buffer}.
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
* @throws ExportException If the underlying decoder or encoder encounters a problem.
*/
void queueInputBuffer(DecoderInputBuffer inputBuffer) throws TransformationException;
void queueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException;
/**
* Signals end-of-stream on input to a video encoder.
@ -172,17 +171,17 @@ public interface Codec {
* should be set on the last input buffer {@linkplain #queueInputBuffer(DecoderInputBuffer)
* queued}.
*
* @throws TransformationException If the underlying video encoder encounters a problem.
* @throws ExportException If the underlying video encoder encounters a problem.
*/
void signalEndOfInputStream() throws TransformationException;
void signalEndOfInputStream() throws ExportException;
/**
* Returns the current output format, or {@code null} if unavailable.
*
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
* @throws ExportException If the underlying decoder or encoder encounters a problem.
*/
@Nullable
Format getOutputFormat() throws TransformationException;
Format getOutputFormat() throws ExportException;
/**
* Returns the current output {@link ByteBuffer}, or {@code null} if unavailable.
@ -190,10 +189,10 @@ public interface Codec {
* <p>This method must not be called on video decoders because they must output to a {@link
* Surface}.
*
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
* @throws ExportException If the underlying decoder or encoder encounters a problem.
*/
@Nullable
ByteBuffer getOutputBuffer() throws TransformationException;
ByteBuffer getOutputBuffer() throws ExportException;
/**
* Returns the {@link BufferInfo} associated with the current output buffer, or {@code null} if
@ -201,10 +200,10 @@ public interface Codec {
*
* <p>This method returns {@code null} if and only if {@link #getOutputBuffer()} returns null.
*
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
* @throws ExportException If the underlying decoder or encoder encounters a problem.
*/
@Nullable
BufferInfo getOutputBufferInfo() throws TransformationException;
BufferInfo getOutputBufferInfo() throws ExportException;
/**
* Releases the current output buffer.
@ -218,9 +217,9 @@ public interface Codec {
* be available until the current output buffer has been released.
*
* @param render Whether the buffer needs to be rendered to the output {@link Surface}.
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
* @throws ExportException If the underlying decoder or encoder encounters a problem.
*/
void releaseOutputBuffer(boolean render) throws TransformationException;
void releaseOutputBuffer(boolean render) throws ExportException;
/**
* Returns whether the {@code Codec}'s output stream has ended, and no more data can be dequeued.

View File

@ -173,7 +173,7 @@ import java.util.concurrent.atomic.AtomicLong;
@SupportedOutputTypes int supportedOutputTypes,
long streamStartPositionUs,
long streamOffsetUs)
throws TransformationException {
throws ExportException {
int trackType = MimeTypes.getTrackType(format.sampleMimeType);
SampleConsumer sampleConsumer;
if (currentMediaItemIndex.get() == 0) {
@ -201,8 +201,8 @@ import java.util.concurrent.atomic.AtomicLong;
}
@Override
public void onError(TransformationException exception) {
compositeAssetLoaderListener.onError(exception);
public void onError(ExportException exportException) {
compositeAssetLoaderListener.onError(exportException);
}
private void addCurrentProcessedInput() {

View File

@ -98,7 +98,7 @@ public final class DefaultCodec implements Codec {
String mediaCodecName,
boolean isDecoder,
@Nullable Surface outputSurface)
throws TransformationException {
throws ExportException {
this.configurationFormat = configurationFormat;
this.configurationMediaFormat = configurationMediaFormat;
this.isDecoder = isDecoder;
@ -135,21 +135,21 @@ public final class DefaultCodec implements Codec {
mediaCodec.release();
}
@TransformationException.ErrorCode int errorCode;
@ExportException.ErrorCode int errorCode;
if (e instanceof IOException || e instanceof MediaCodec.CodecException) {
errorCode =
isDecoder
? TransformationException.ERROR_CODE_DECODER_INIT_FAILED
: TransformationException.ERROR_CODE_ENCODER_INIT_FAILED;
? ExportException.ERROR_CODE_DECODER_INIT_FAILED
: ExportException.ERROR_CODE_ENCODER_INIT_FAILED;
} else if (e instanceof IllegalArgumentException) {
errorCode =
isDecoder
? TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
: TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
? ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
: ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
} else {
errorCode = TransformationException.ERROR_CODE_FAILED_RUNTIME_CHECK;
errorCode = ExportException.ERROR_CODE_FAILED_RUNTIME_CHECK;
}
throw createTransformationException(e, errorCode, mediaCodecName);
throw createExportException(e, errorCode, mediaCodecName);
}
this.mediaCodec = mediaCodec;
this.inputSurface = inputSurface;
@ -175,8 +175,7 @@ public final class DefaultCodec implements Codec {
@Override
@EnsuresNonNullIf(expression = "#1.data", result = true)
public boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer)
throws TransformationException {
public boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException {
if (inputStreamEnded) {
return false;
}
@ -184,7 +183,7 @@ public final class DefaultCodec implements Codec {
try {
inputBufferIndex = mediaCodec.dequeueInputBuffer(/* timeoutUs= */ 0);
} catch (RuntimeException e) {
throw createTransformationException(e);
throw createExportException(e);
}
if (inputBufferIndex < 0) {
return false;
@ -192,7 +191,7 @@ public final class DefaultCodec implements Codec {
try {
inputBuffer.data = mediaCodec.getInputBuffer(inputBufferIndex);
} catch (RuntimeException e) {
throw createTransformationException(e);
throw createExportException(e);
}
inputBuffer.clear();
}
@ -201,7 +200,7 @@ public final class DefaultCodec implements Codec {
}
@Override
public void queueInputBuffer(DecoderInputBuffer inputBuffer) throws TransformationException {
public void queueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException {
checkState(
!inputStreamEnded, "Input buffer can not be queued after the input stream has ended.");
@ -219,24 +218,24 @@ public final class DefaultCodec implements Codec {
try {
mediaCodec.queueInputBuffer(inputBufferIndex, offset, size, inputBuffer.timeUs, flags);
} catch (RuntimeException e) {
throw createTransformationException(e);
throw createExportException(e);
}
inputBufferIndex = C.INDEX_UNSET;
inputBuffer.data = null;
}
@Override
public void signalEndOfInputStream() throws TransformationException {
public void signalEndOfInputStream() throws ExportException {
try {
mediaCodec.signalEndOfInputStream();
} catch (RuntimeException e) {
throw createTransformationException(e);
throw createExportException(e);
}
}
@Override
@Nullable
public Format getOutputFormat() throws TransformationException {
public Format getOutputFormat() throws ExportException {
// The format is updated when dequeueing a 'special' buffer index, so attempt to dequeue now.
maybeDequeueOutputBuffer(/* setOutputBuffer= */ false);
return outputFormat;
@ -244,18 +243,18 @@ public final class DefaultCodec implements Codec {
@Override
@Nullable
public ByteBuffer getOutputBuffer() throws TransformationException {
public ByteBuffer getOutputBuffer() throws ExportException {
return maybeDequeueOutputBuffer(/* setOutputBuffer= */ true) ? outputBuffer : null;
}
@Override
@Nullable
public BufferInfo getOutputBufferInfo() throws TransformationException {
public BufferInfo getOutputBufferInfo() throws ExportException {
return maybeDequeueOutputBuffer(/* setOutputBuffer= */ false) ? outputBufferInfo : null;
}
@Override
public void releaseOutputBuffer(boolean render) throws TransformationException {
public void releaseOutputBuffer(boolean render) throws ExportException {
outputBuffer = null;
try {
if (render) {
@ -266,7 +265,7 @@ public final class DefaultCodec implements Codec {
mediaCodec.releaseOutputBuffer(outputBufferIndex, /* render= */ false);
}
} catch (RuntimeException e) {
throw createTransformationException(e);
throw createExportException(e);
}
outputBufferIndex = C.INDEX_UNSET;
}
@ -310,9 +309,9 @@ public final class DefaultCodec implements Codec {
* @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 ExportException If the underlying {@link MediaCodec} encounters a problem.
*/
private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) throws TransformationException {
private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) throws ExportException {
if (outputBufferIndex >= 0) {
return true;
}
@ -323,7 +322,7 @@ public final class DefaultCodec implements Codec {
try {
outputBufferIndex = mediaCodec.dequeueOutputBuffer(outputBufferInfo, /* timeoutUs= */ 0);
} catch (RuntimeException e) {
throw createTransformationException(e);
throw createExportException(e);
}
if (outputBufferIndex < 0) {
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
@ -363,7 +362,7 @@ public final class DefaultCodec implements Codec {
try {
outputBuffer = checkNotNull(mediaCodec.getOutputBuffer(outputBufferIndex));
} catch (RuntimeException e) {
throw createTransformationException(e);
throw createExportException(e);
}
outputBuffer.position(outputBufferInfo.offset);
outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size);
@ -371,25 +370,24 @@ public final class DefaultCodec implements Codec {
return true;
}
private TransformationException createTransformationException(Exception cause) {
return createTransformationException(
private ExportException createExportException(Exception cause) {
return createExportException(
cause,
isDecoder
? TransformationException.ERROR_CODE_DECODING_FAILED
: TransformationException.ERROR_CODE_ENCODING_FAILED,
? ExportException.ERROR_CODE_DECODING_FAILED
: ExportException.ERROR_CODE_ENCODING_FAILED,
getName());
}
/** Creates a {@link TransformationException} with specific {@link MediaCodec} details. */
private TransformationException createTransformationException(
/** Creates an {@link ExportException} with specific {@link MediaCodec} details. */
private ExportException createExportException(
@UnknownInitialization DefaultCodec this,
Exception cause,
@TransformationException.ErrorCode int errorCode,
@ExportException.ErrorCode int errorCode,
String mediaCodecName) {
String codecDetails =
"mediaFormat=" + configurationMediaFormat + ", mediaCodecName=" + mediaCodecName;
return TransformationException.createForCodec(
cause, errorCode, isVideo, isDecoder, codecDetails);
return ExportException.createForCodec(cause, errorCode, isVideo, isDecoder, codecDetails);
}
private static boolean areColorTransfersEqual(

View File

@ -51,14 +51,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
@Override
public Codec createForAudioDecoding(Format format) throws TransformationException {
public Codec createForAudioDecoding(Format format) throws ExportException {
checkNotNull(format.sampleMimeType);
MediaFormat mediaFormat = createMediaFormatFromFormat(format);
@Nullable
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
if (mediaCodecName == null) {
throw createTransformationException(
throw createExportException(
format, /* reason= */ "The requested decoding format is not supported.");
}
return new DefaultCodec(
@ -73,18 +73,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@SuppressLint("InlinedApi")
@Override
public Codec createForVideoDecoding(
Format format, Surface outputSurface, boolean requestSdrToneMapping)
throws TransformationException {
Format format, Surface outputSurface, boolean requestSdrToneMapping) throws ExportException {
checkNotNull(format.sampleMimeType);
if (ColorInfo.isTransferHdr(format.colorInfo)) {
if (requestSdrToneMapping && (SDK_INT < 31 || deviceNeedsNoToneMappingWorkaround())) {
throw createTransformationException(
throw createExportException(
format, /* reason= */ "Tone-mapping HDR is not supported on this device.");
}
if (SDK_INT < 29) {
// TODO(b/266837571, b/267171669): Remove API version restriction after fixing linked bugs.
throw createTransformationException(
throw createExportException(
format, /* reason= */ "Decoding HDR is not supported on this device.");
}
}
@ -111,7 +110,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@Nullable
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
if (mediaCodecName == null) {
throw createTransformationException(
throw createExportException(
format, /* reason= */ "The requested video decoding format is not supported.");
}
return new DefaultCodec(
@ -127,11 +126,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
@RequiresNonNull("#1.sampleMimeType")
private static TransformationException createTransformationException(
Format format, String reason) {
return TransformationException.createForCodec(
private static ExportException createExportException(Format format, String reason) {
return ExportException.createForCodec(
new IllegalArgumentException(reason),
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
MimeTypes.isVideo(format.sampleMimeType),
/* isDecoder= */ true,
format);

View File

@ -173,14 +173,14 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
}
@Override
public DefaultCodec createForAudioEncoding(Format format) throws TransformationException {
public DefaultCodec createForAudioEncoding(Format format) throws ExportException {
checkNotNull(format.sampleMimeType);
MediaFormat mediaFormat = createMediaFormatFromFormat(format);
@Nullable
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ false);
if (mediaCodecName == null) {
throw createTransformationException(
throw createExportException(
format, /* errorString= */ "The requested audio encoding format is not supported.");
}
return new DefaultCodec(
@ -201,7 +201,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
* VideoEncoderSettings#enableHighQualityTargeting} is set.
*/
@Override
public DefaultCodec createForVideoEncoding(Format format) throws TransformationException {
public DefaultCodec createForVideoEncoding(Format format) throws ExportException {
if (format.frameRate == Format.NO_VALUE) {
format = format.buildUpon().setFrameRate(DEFAULT_FRAME_RATE).build();
}
@ -220,7 +220,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
format, requestedVideoEncoderSettings, videoEncoderSelector, enableFallback);
if (encoderAndClosestFormatSupport == null) {
throw createTransformationException(
throw createExportException(
format, /* errorString= */ "The requested video encoding format is not supported.");
}
@ -286,7 +286,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010);
} else {
throw createTransformationException(
throw createExportException(
format, /* errorString= */ "Encoding HDR is not supported on this device.");
}
} else {
@ -664,11 +664,10 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
}
@RequiresNonNull("#1.sampleMimeType")
private static TransformationException createTransformationException(
Format format, String errorString) {
return TransformationException.createForCodec(
private static ExportException createExportException(Format format, String errorString) {
return ExportException.createForCodec(
new IllegalArgumentException(errorString),
TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
MimeTypes.isVideo(format.sampleMimeType),
/* isDecoder= */ false,
format);

View File

@ -45,7 +45,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
@Override
protected void initDecoder(Format inputFormat) throws TransformationException {
protected void initDecoder(Format inputFormat) throws ExportException {
decoder = decoderFactory.createForAudioDecoding(inputFormat);
}
@ -53,11 +53,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* Attempts to get decoded audio data and pass it to the sample consumer.
*
* @return Whether it may be possible to read more data immediately by calling this method again.
* @throws TransformationException If an error occurs in the decoder.
* @throws ExportException If an error occurs in the decoder.
*/
@Override
@RequiresNonNull("sampleConsumer")
protected boolean feedConsumerFromDecoder() throws TransformationException {
protected boolean feedConsumerFromDecoder() throws ExportException {
@Nullable DecoderInputBuffer sampleConsumerInputBuffer = sampleConsumer.getInputBuffer();
if (sampleConsumerInputBuffer == null) {
return false;

View File

@ -101,7 +101,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} else {
while (feedConsumerFromInput()) {}
}
} catch (TransformationException e) {
} catch (ExportException e) {
isTransformationRunning = false;
assetLoaderListener.onError(e);
}
@ -140,7 +140,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** Initializes {@link #decoder} with an appropriate {@linkplain Codec decoder}. */
@RequiresNonNull("sampleConsumer")
protected abstract void initDecoder(Format inputFormat) throws TransformationException;
protected abstract void initDecoder(Format inputFormat) throws ExportException;
/**
* Preprocesses an encoded {@linkplain DecoderInputBuffer input buffer} and returns whether it
@ -159,13 +159,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* Attempts to get decoded data and pass it to the sample consumer.
*
* @return Whether it may be possible to read more data immediately by calling this method again.
* @throws TransformationException If an error occurs in the decoder.
* @throws ExportException If an error occurs in the decoder.
*/
@RequiresNonNull("sampleConsumer")
protected abstract boolean feedConsumerFromDecoder() throws TransformationException;
protected abstract boolean feedConsumerFromDecoder() throws ExportException;
@EnsuresNonNullIf(expression = "sampleConsumer", result = true)
private boolean ensureConfigured() throws TransformationException {
private boolean ensureConfigured() throws ExportException {
if (sampleConsumer != null) {
return true;
}
@ -193,9 +193,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* Attempts to read input data and pass it to the decoder.
*
* @return Whether it may be possible to read more data immediately by calling this method again.
* @throws TransformationException If an error occurs in the decoder.
* @throws ExportException If an error occurs in the decoder.
*/
private boolean feedDecoderFromInput() throws TransformationException {
private boolean feedDecoderFromInput() throws ExportException {
Codec decoder = checkNotNull(this.decoder);
if (!decoder.maybeDequeueInputBuffer(decoderInputBuffer)) {
return false;

View File

@ -65,7 +65,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@Override
@RequiresNonNull("sampleConsumer")
protected void initDecoder(Format inputFormat) throws TransformationException {
protected void initDecoder(Format inputFormat) throws ExportException {
boolean isDecoderToneMappingRequired =
ColorInfo.isTransferHdr(inputFormat.colorInfo)
&& !ColorInfo.isTransferHdr(sampleConsumer.getExpectedInputColorInfo());
@ -106,7 +106,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@Override
@RequiresNonNull("sampleConsumer")
protected boolean feedConsumerFromDecoder() throws TransformationException {
protected boolean feedConsumerFromDecoder() throws ExportException {
Codec decoder = checkNotNull(this.decoder);
if (decoder.isEnded()) {
sampleConsumer.signalEndOfVideoInput();

View File

@ -21,8 +21,8 @@ import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_BUFFER_FOR_PL
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_FAILED_RUNTIME_CHECK;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_UNSPECIFIED;
import static androidx.media3.transformer.ExportException.ERROR_CODE_FAILED_RUNTIME_CHECK;
import static androidx.media3.transformer.ExportException.ERROR_CODE_UNSPECIFIED;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE;
@ -309,7 +309,7 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
player.play();
} else {
assetLoaderListener.onError(
TransformationException.createForAssetLoader(
ExportException.createForAssetLoader(
new IllegalStateException("The asset loader has no track to output."),
ERROR_CODE_FAILED_RUNTIME_CHECK));
}
@ -317,12 +317,12 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
@Override
public void onPlayerError(PlaybackException error) {
@TransformationException.ErrorCode
@ExportException.ErrorCode
int errorCode =
checkNotNull(
TransformationException.NAME_TO_ERROR_CODE.getOrDefault(
ExportException.NAME_TO_ERROR_CODE.getOrDefault(
error.getErrorCodeName(), ERROR_CODE_UNSPECIFIED));
assetLoaderListener.onError(TransformationException.createForAssetLoader(error, errorCode));
assetLoaderListener.onError(ExportException.createForAssetLoader(error, errorCode));
}
}
}

View File

@ -0,0 +1,363 @@
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.media3.transformer;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.os.SystemClock;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.media3.common.Format;
import androidx.media3.common.VideoFrameProcessingException;
import androidx.media3.common.VideoFrameProcessor;
import androidx.media3.common.audio.AudioProcessor.AudioFormat;
import androidx.media3.common.util.Clock;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util;
import com.google.common.collect.ImmutableBiMap;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** Thrown when a non-locally recoverable export failure occurs. */
@UnstableApi
public final class ExportException extends Exception {
/**
* Error codes that identify causes of {@link Transformer} errors.
*
* <p>This list of errors may be extended in future versions. The underlying values may also
* change, so it is best to avoid relying on them directly without using the constants.
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
@Target(TYPE_USE)
@IntDef(
open = true,
value = {
ERROR_CODE_UNSPECIFIED,
ERROR_CODE_FAILED_RUNTIME_CHECK,
ERROR_CODE_IO_UNSPECIFIED,
ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT,
ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE,
ERROR_CODE_IO_BAD_HTTP_STATUS,
ERROR_CODE_IO_FILE_NOT_FOUND,
ERROR_CODE_IO_NO_PERMISSION,
ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED,
ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE,
ERROR_CODE_DECODER_INIT_FAILED,
ERROR_CODE_DECODING_FAILED,
ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
ERROR_CODE_ENCODER_INIT_FAILED,
ERROR_CODE_ENCODING_FAILED,
ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED,
ERROR_CODE_AUDIO_PROCESSING_FAILED,
ERROR_CODE_MUXING_FAILED,
})
public @interface ErrorCode {}
// Miscellaneous errors (1xxx).
/** Caused by an error whose cause could not be identified. */
public static final int ERROR_CODE_UNSPECIFIED = 1000;
/**
* Caused by a failed runtime check.
*
* <p>This can happen when transformer reaches an invalid state.
*/
public static final int ERROR_CODE_FAILED_RUNTIME_CHECK = 1001;
// Input/Output errors (2xxx).
/** Caused by an Input/Output error which could not be identified. */
public static final int ERROR_CODE_IO_UNSPECIFIED = 2000;
/**
* Caused by a network connection failure.
*
* <p>The following is a non-exhaustive list of possible reasons:
*
* <ul>
* <li>There is no network connectivity.
* <li>The URL's domain is misspelled or does not exist.
* <li>The target host is unreachable.
* <li>The server unexpectedly closes the connection.
* </ul>
*/
public static final int ERROR_CODE_IO_NETWORK_CONNECTION_FAILED = 2001;
/** Caused by a network timeout, meaning the server is taking too long to fulfill a request. */
public static final int ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT = 2002;
/**
* Caused by a server returning a resource with an invalid "Content-Type" HTTP header value.
*
* <p>For example, this can happen when the {@link AssetLoader} is expecting a piece of media, but
* the server returns a paywall HTML page, with content type "text/html".
*/
public static final int ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE = 2003;
/** Caused by an HTTP server returning an unexpected HTTP response status code. */
public static final int ERROR_CODE_IO_BAD_HTTP_STATUS = 2004;
/** Caused by a non-existent file. */
public static final int ERROR_CODE_IO_FILE_NOT_FOUND = 2005;
/**
* Caused by lack of permission to perform an IO operation. For example, lack of permission to
* access internet or external storage.
*/
public static final int ERROR_CODE_IO_NO_PERMISSION = 2006;
/**
* Caused by the {@link AssetLoader} trying to access cleartext HTTP traffic (meaning http://
* rather than https://) when the app's Network Security Configuration does not permit it.
*/
public static final int ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED = 2007;
/** Caused by reading data out of the data bound. */
public static final int ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE = 2008;
// Decoding errors (3xxx).
/** Caused by a decoder initialization failure. */
public static final int ERROR_CODE_DECODER_INIT_FAILED = 3001;
/** Caused by a failure while trying to decode media samples. */
public static final int ERROR_CODE_DECODING_FAILED = 3002;
/** Caused by trying to decode content whose format is not supported. */
public static final int ERROR_CODE_DECODING_FORMAT_UNSUPPORTED = 3003;
// Encoding errors (4xxx).
/** Caused by an encoder initialization failure. */
public static final int ERROR_CODE_ENCODER_INIT_FAILED = 4001;
/** Caused by a failure while trying to encode media samples. */
public static final int ERROR_CODE_ENCODING_FAILED = 4002;
/**
* Caused by trying to encode content whose format is not supported. *
*
* <p>Supported output formats are limited by the {@linkplain Codec.DecoderFactory encoders}
* available.
*/
public static final int ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED = 4003;
// Video editing errors (5xxx).
/** Caused by a video frame processing failure. */
public static final int ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED = 5001;
// Audio processing errors (6xxx).
/** Caused by an audio processing failure. */
public static final int ERROR_CODE_AUDIO_PROCESSING_FAILED = 6001;
// Muxing errors (7xxx).
/** Caused by a failure while muxing media samples. */
public static final int ERROR_CODE_MUXING_FAILED = 7001;
/* package */ static final ImmutableBiMap<String, @ErrorCode Integer> NAME_TO_ERROR_CODE =
new ImmutableBiMap.Builder<String, @ErrorCode Integer>()
.put("ERROR_CODE_FAILED_RUNTIME_CHECK", ERROR_CODE_FAILED_RUNTIME_CHECK)
.put("ERROR_CODE_IO_UNSPECIFIED", ERROR_CODE_IO_UNSPECIFIED)
.put("ERROR_CODE_IO_NETWORK_CONNECTION_FAILED", ERROR_CODE_IO_NETWORK_CONNECTION_FAILED)
.put("ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT", ERROR_CODE_IO_NETWORK_CONNECTION_TIMEOUT)
.put("ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE", ERROR_CODE_IO_INVALID_HTTP_CONTENT_TYPE)
.put("ERROR_CODE_IO_BAD_HTTP_STATUS", ERROR_CODE_IO_BAD_HTTP_STATUS)
.put("ERROR_CODE_IO_FILE_NOT_FOUND", ERROR_CODE_IO_FILE_NOT_FOUND)
.put("ERROR_CODE_IO_NO_PERMISSION", ERROR_CODE_IO_NO_PERMISSION)
.put("ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED", ERROR_CODE_IO_CLEARTEXT_NOT_PERMITTED)
.put("ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE", ERROR_CODE_IO_READ_POSITION_OUT_OF_RANGE)
.put("ERROR_CODE_DECODER_INIT_FAILED", ERROR_CODE_DECODER_INIT_FAILED)
.put("ERROR_CODE_DECODING_FAILED", ERROR_CODE_DECODING_FAILED)
.put("ERROR_CODE_DECODING_FORMAT_UNSUPPORTED", ERROR_CODE_DECODING_FORMAT_UNSUPPORTED)
.put("ERROR_CODE_ENCODER_INIT_FAILED", ERROR_CODE_ENCODER_INIT_FAILED)
.put("ERROR_CODE_ENCODING_FAILED", ERROR_CODE_ENCODING_FAILED)
.put("ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED", ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED)
.put("ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED", ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED)
.put("ERROR_CODE_AUDIO_PROCESSING_FAILED", ERROR_CODE_AUDIO_PROCESSING_FAILED)
.put("ERROR_CODE_MUXING_FAILED", ERROR_CODE_MUXING_FAILED)
.buildOrThrow();
/** Returns the name of a given {@code errorCode}. */
public static String getErrorCodeName(@ErrorCode int errorCode) {
return NAME_TO_ERROR_CODE.inverse().getOrDefault(errorCode, "invalid error code");
}
/**
* Equivalent to {@link ExportException#getErrorCodeName(int)
* ExportException.getErrorCodeName(this.errorCode)}.
*/
public String getErrorCodeName() {
return getErrorCodeName(errorCode);
}
/**
* Creates an instance for an {@link AssetLoader} related exception.
*
* @param cause The cause of the failure.
* @param errorCode See {@link #errorCode}.
* @return The created instance.
*/
public static ExportException createForAssetLoader(Throwable cause, int errorCode) {
return new ExportException("Asset loader error", cause, errorCode);
}
/**
* Creates an instance for a {@link Codec} related exception.
*
* <p>This method should be used when the {@code cause} occurs before the {@link Codec} is
* initialized.
*
* @param cause The cause of the failure.
* @param errorCode See {@link #errorCode}.
* @param isVideo Whether the {@link Codec} is configured for video.
* @param isDecoder Whether the exception is created for a decoder.
* @param format The {@link Format} used for configuring the {@link Codec}.
* @return The created instance.
*/
public static ExportException createForCodec(
Throwable cause,
@ErrorCode int errorCode,
boolean isVideo,
boolean isDecoder,
Format format) {
String details = "format=" + format;
return createForCodec(cause, errorCode, isVideo, isDecoder, details);
}
/**
* Creates an instance for a {@link Codec} related exception.
*
* @param cause The cause of the failure.
* @param errorCode See {@link #errorCode}.
* @param isVideo Whether the {@link Codec} is configured for video.
* @param isDecoder Whether the exception is created for a decoder.
* @param details The details associated with this exception.
* @return The created instance.
*/
public static ExportException createForCodec(
Throwable cause,
@ErrorCode int errorCode,
boolean isVideo,
boolean isDecoder,
String details) {
String componentName = (isVideo ? "Video" : "Audio") + (isDecoder ? "Decoder" : "Encoder");
String errorMessage = componentName + " error: " + details;
return new ExportException(errorMessage, cause, errorCode);
}
/**
* Creates an instance for an audio processing related exception.
*
* @param cause The cause of the failure.
* @param audioFormat The {@link AudioFormat} used.
* @return The created instance.
*/
public static ExportException createForAudioProcessing(Throwable cause, AudioFormat audioFormat) {
return new ExportException(
"Audio processing error, audio_format = " + audioFormat,
cause,
ERROR_CODE_AUDIO_PROCESSING_FAILED);
}
/**
* Creates an instance for a {@link VideoFrameProcessor} related exception.
*
* @param cause The cause of the failure.
* @param errorCode See {@link #errorCode}.
* @return The created instance.
*/
/* package */ static ExportException createForVideoFrameProcessingException(
VideoFrameProcessingException cause, int errorCode) {
return new ExportException("Video frame processing error", cause, errorCode);
}
/**
* Creates an instance for a muxer related exception.
*
* @param cause The cause of the failure.
* @param errorCode See {@link #errorCode}.
* @return The created instance.
*/
/* package */ static ExportException createForMuxer(Throwable cause, int errorCode) {
return new ExportException("Muxer error", cause, errorCode);
}
/**
* Creates an instance for an unexpected exception.
*
* <p>If the exception is a runtime exception, error code {@link #ERROR_CODE_FAILED_RUNTIME_CHECK}
* is used. Otherwise, the created instance has error code {@link #ERROR_CODE_UNSPECIFIED}.
*
* @param cause The cause of the failure.
* @return The created instance.
*/
public static ExportException createForUnexpected(Exception cause) {
if (cause instanceof RuntimeException) {
return new ExportException(
"Unexpected runtime error", cause, ERROR_CODE_FAILED_RUNTIME_CHECK);
}
return new ExportException("Unexpected error", cause, ERROR_CODE_UNSPECIFIED);
}
/** An error code which identifies the cause of the export failure. */
public final @ErrorCode int errorCode;
/** The value of {@link SystemClock#elapsedRealtime()} when this exception was created. */
public final long timestampMs;
/**
* Creates an instance.
*
* @param message See {@link #getMessage()}.
* @param cause See {@link #getCause()}.
* @param errorCode A number which identifies the cause of the error. May be one of the {@link
* ErrorCode ErrorCodes}.
*/
private ExportException(
@Nullable String message, @Nullable Throwable cause, @ErrorCode int errorCode) {
super(message, cause);
this.errorCode = errorCode;
this.timestampMs = Clock.DEFAULT.elapsedRealtime();
}
/**
* Returns whether the error data associated to this exception equals the error data associated to
* {@code other}.
*
* <p>Note that this method does not compare the exceptions' stack traces.
*/
public boolean errorInfoEquals(@Nullable ExportException other) {
if (this == other) {
return true;
}
if (other == null || getClass() != other.getClass()) {
return false;
}
@Nullable Throwable thisCause = getCause();
@Nullable Throwable thatCause = other.getCause();
if (thisCause != null && thatCause != null) {
if (!Util.areEqual(thisCause.getMessage(), thatCause.getMessage())) {
return false;
}
if (!Util.areEqual(thisCause.getClass(), thatCause.getClass())) {
return false;
}
} else if (thisCause != null || thatCause != null) {
return false;
}
return errorCode == other.errorCode
&& Util.areEqual(getMessage(), other.getMessage())
&& timestampMs == other.timestampMs;
}
}

View File

@ -47,7 +47,7 @@ public final class ExportResult {
private int width;
private int videoFrameCount;
@Nullable private String videoEncoderName;
@Nullable private TransformationException transformationException;
@Nullable private ExportException exportException;
/** Creates a builder. */
public Builder() {
@ -206,11 +206,10 @@ public final class ExportResult {
return this;
}
/** Sets the {@link TransformationException} that caused the export to fail. */
/** Sets the {@link ExportException} that caused the export to fail. */
@CanIgnoreReturnValue
public Builder setTransformationException(
@Nullable TransformationException transformationException) {
this.transformationException = transformationException;
public Builder setExportException(@Nullable ExportException exportException) {
this.exportException = exportException;
return this;
}
@ -231,7 +230,7 @@ public final class ExportResult {
width,
videoFrameCount,
videoEncoderName,
transformationException);
exportException);
}
}
@ -296,10 +295,10 @@ public final class ExportResult {
@Nullable public final String videoEncoderName;
/**
* The {@link TransformationException} that caused the export to fail, or {@code null} if the
* export was a success.
* The {@link ExportException} that caused the export to fail, or {@code null} if the export was a
* success.
*/
@Nullable public final TransformationException transformationException;
@Nullable public final ExportException exportException;
private ExportResult(
ImmutableList<ProcessedInput> processedInputs,
@ -316,7 +315,7 @@ public final class ExportResult {
int width,
int videoFrameCount,
@Nullable String videoEncoderName,
@Nullable TransformationException transformationException) {
@Nullable ExportException exportException) {
this.processedInputs = processedInputs;
this.durationMs = durationMs;
this.fileSizeBytes = fileSizeBytes;
@ -331,7 +330,7 @@ public final class ExportResult {
this.width = width;
this.videoFrameCount = videoFrameCount;
this.videoEncoderName = videoEncoderName;
this.transformationException = transformationException;
this.exportException = exportException;
}
public Builder buildUpon() {
@ -350,7 +349,7 @@ public final class ExportResult {
.setWidth(width)
.setVideoFrameCount(videoFrameCount)
.setVideoEncoderName(videoEncoderName)
.setTransformationException(transformationException);
.setExportException(exportException);
}
@Override
@ -376,7 +375,7 @@ public final class ExportResult {
&& width == result.width
&& videoFrameCount == result.videoFrameCount
&& Objects.equals(videoEncoderName, result.videoEncoderName)
&& Objects.equals(transformationException, result.transformationException);
&& Objects.equals(exportException, result.exportException);
}
@Override
@ -395,7 +394,7 @@ public final class ExportResult {
result = 31 * result + width;
result = 31 * result + videoFrameCount;
result = 31 * result + Objects.hashCode(videoEncoderName);
result = 31 * result + Objects.hashCode(transformationException);
result = 31 * result + Objects.hashCode(exportException);
return result;
}
}

View File

@ -18,8 +18,8 @@ package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_IO_UNSPECIFIED;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_UNSPECIFIED;
import static androidx.media3.transformer.ExportException.ERROR_CODE_IO_UNSPECIFIED;
import static androidx.media3.transformer.ExportException.ERROR_CODE_UNSPECIFIED;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
@ -101,19 +101,17 @@ public final class ImageAssetLoader implements AssetLoader {
sampleConsumer.queueInputBitmap(
bitmap, editedMediaItem.durationUs, editedMediaItem.frameRate);
sampleConsumer.signalEndOfVideoInput();
} catch (TransformationException e) {
} catch (ExportException e) {
listener.onError(e);
} catch (RuntimeException e) {
listener.onError(
TransformationException.createForAssetLoader(e, ERROR_CODE_UNSPECIFIED));
listener.onError(ExportException.createForAssetLoader(e, ERROR_CODE_UNSPECIFIED));
}
progress = 100;
}
@Override
public void onFailure(Throwable t) {
listener.onError(
TransformationException.createForAssetLoader(t, ERROR_CODE_IO_UNSPECIFIED));
listener.onError(ExportException.createForAssetLoader(t, ERROR_CODE_IO_UNSPECIFIED));
}
},
MoreExecutors.directExecutor());

View File

@ -53,7 +53,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
void onEnded(long durationMs, long fileSizeBytes);
void onError(TransformationException transformationException);
void onError(ExportException exportException);
}
/**
@ -277,12 +277,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
}
isAborted = true;
listener.onError(
TransformationException.createForMuxer(
ExportException.createForMuxer(
new IllegalStateException(
"No output sample written in the last "
+ maxDelayBetweenSamplesMs
+ " milliseconds. Aborting transformation."),
TransformationException.ERROR_CODE_MUXING_FAILED));
ExportException.ERROR_CODE_MUXING_FAILED));
},
maxDelayBetweenSamplesMs,
MILLISECONDS);

View File

@ -64,24 +64,24 @@ import java.util.List;
* Processes the input data and returns whether it may be possible to process more data by calling
* this method again.
*/
public final boolean processData() throws TransformationException {
public final boolean processData() throws ExportException {
return feedMuxer() || processDataUpToMuxer();
}
/** Releases all resources held by the pipeline. */
public abstract void release();
protected boolean processDataUpToMuxer() throws TransformationException {
protected boolean processDataUpToMuxer() throws ExportException {
return false;
}
@Nullable
protected abstract Format getMuxerInputFormat() throws TransformationException;
protected abstract Format getMuxerInputFormat() throws ExportException;
@Nullable
protected abstract DecoderInputBuffer getMuxerInputBuffer() throws TransformationException;
protected abstract DecoderInputBuffer getMuxerInputBuffer() throws ExportException;
protected abstract void releaseMuxerInputBuffer() throws TransformationException;
protected abstract void releaseMuxerInputBuffer() throws ExportException;
protected abstract boolean isMuxerInputEnded();
@ -89,7 +89,7 @@ import java.util.List;
* Attempts to pass encoded data to the muxer, and returns whether it may be possible to pass more
* data immediately by calling this method again.
*/
private boolean feedMuxer() throws TransformationException {
private boolean feedMuxer() throws ExportException {
if (!muxerWrapperTrackAdded) {
@Nullable Format inputFormat = getMuxerInputFormat();
if (inputFormat == null) {
@ -98,8 +98,7 @@ import java.util.List;
try {
muxerWrapper.addTrackFormat(inputFormat);
} catch (Muxer.MuxerException e) {
throw TransformationException.createForMuxer(
e, TransformationException.ERROR_CODE_MUXING_FAILED);
throw ExportException.createForMuxer(e, ExportException.ERROR_CODE_MUXING_FAILED);
}
muxerWrapperTrackAdded = true;
}
@ -126,8 +125,7 @@ import java.util.List;
return false;
}
} catch (Muxer.MuxerException e) {
throw TransformationException.createForMuxer(
e, TransformationException.ERROR_CODE_MUXING_FAILED);
throw ExportException.createForMuxer(e, ExportException.ERROR_CODE_MUXING_FAILED);
}
releaseMuxerInputBuffer();
@ -152,10 +150,10 @@ import java.util.List;
* @param muxerSupportedMimeTypes The list of sample {@linkplain MimeTypes MIME types} that the
* muxer supports.
* @return A supported {@linkplain MimeTypes MIME type}.
* @throws TransformationException If there are no supported {@linkplain MimeTypes MIME types}.
* @throws ExportException If there are no supported {@linkplain MimeTypes MIME types}.
*/
protected static String findSupportedMimeTypeForEncoderAndMuxer(
Format requestedFormat, List<String> muxerSupportedMimeTypes) throws TransformationException {
Format requestedFormat, List<String> muxerSupportedMimeTypes) throws ExportException {
boolean isVideo = MimeTypes.isVideo(checkNotNull(requestedFormat.sampleMimeType));
ImmutableSet.Builder<String> mimeTypesToCheckSetBuilder =
@ -185,16 +183,16 @@ import java.util.List;
throw createNoSupportedMimeTypeException(requestedFormat);
}
private static TransformationException createNoSupportedMimeTypeException(Format format) {
private static ExportException createNoSupportedMimeTypeException(Format format) {
String errorMessage = "No MIME type is supported by both encoder and muxer.";
int errorCode = TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
int errorCode = ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
boolean isVideo = MimeTypes.isVideo(format.sampleMimeType);
if (isVideo && isTransferHdr(format.colorInfo)) {
errorMessage += " Requested HDR colorInfo: " + format.colorInfo;
}
return TransformationException.createForCodec(
return ExportException.createForCodec(
new IllegalArgumentException(errorMessage),
errorCode,
isVideo,

View File

@ -33,7 +33,10 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/** Thrown when a non-locally recoverable transformation failure occurs. */
/**
* @deprecated Use {@link ExportException} instead.
*/
@Deprecated
@UnstableApi
public final class TransformationException extends Exception {
@ -331,6 +334,12 @@ public final class TransformationException extends Exception {
this.timestampMs = Clock.DEFAULT.elapsedRealtime();
}
/* package */ TransformationException(ExportException exportException) {
super(exportException.getMessage(), exportException.getCause());
errorCode = exportException.errorCode;
timestampMs = exportException.timestampMs;
}
/**
* Returns whether the error data associated to this exception equals the error data associated to
* {@code other}.

View File

@ -70,7 +70,7 @@ public final class TransformationRequest {
* <p>Supported on API 31+, by some device and HDR format combinations. Tone-mapping is only
* guaranteed to be supported from Android T onwards.
*
* <p>If not supported, {@link Transformer} throws a {@link TransformationException}.
* <p>If not supported, {@link Transformer} throws an {@link ExportException}.
*/
public static final int HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_MEDIACODEC = 1;
/**
@ -84,7 +84,7 @@ public final class TransformationRequest {
* implementation, but should have much wider support and have more consistent results across
* devices.
*
* <p>If not supported, {@link Transformer} throws a {@link TransformationException}.
* <p>If not supported, {@link Transformer} throws an {@link ExportException}.
*/
public static final int HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL = 2;
/**

View File

@ -94,7 +94,9 @@ public final class TransformationResult {
width = exportResult.width;
videoFrameCount = exportResult.videoFrameCount;
videoEncoderName = exportResult.videoEncoderName;
transformationException = exportResult.transformationException;
if (exportResult.exportException != null) {
transformationException = new TransformationException(exportResult.exportException);
}
}
/** Sets the {@linkplain ProcessedInput processed inputs}. */

View File

@ -498,13 +498,13 @@ public final class Transformer {
}
/**
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
* @deprecated Use {@link #onError(Composition, ExportResult, ExportException)} instead.
*/
@Deprecated
default void onTransformationError(MediaItem inputMediaItem, Exception exception) {}
/**
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
* @deprecated Use {@link #onError(Composition, ExportResult, ExportException)} instead.
*/
@Deprecated
default void onTransformationError(
@ -513,7 +513,7 @@ public final class Transformer {
}
/**
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
* @deprecated Use {@link #onError(Composition, ExportResult, ExportException)} instead.
*/
@Deprecated
default void onTransformationError(
@ -526,16 +526,17 @@ public final class Transformer {
*
* @param composition The {@link Composition} for which the exception occurs.
* @param exportResult The {@link ExportResult} of the export.
* @param exception The {@link TransformationException} describing the exception. This is the
* same instance as the {@linkplain ExportResult#transformationException exception} in
* {@code result}.
* @param exportException The {@link ExportException} describing the exception. This is the same
* instance as the {@linkplain ExportResult#exportException exception} in {@code result}.
*/
@SuppressWarnings("deprecation") // Calling deprecated listener method.
default void onError(
Composition composition, ExportResult exportResult, TransformationException exception) {
Composition composition, ExportResult exportResult, ExportException exportException) {
MediaItem mediaItem = composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
onTransformationError(
mediaItem, new TransformationResult.Builder(exportResult).build(), exception);
mediaItem,
new TransformationResult.Builder(exportResult).build(),
new TransformationException(exportException));
}
/**
@ -751,7 +752,7 @@ public final class Transformer {
checkArgument(composition.sequences.size() == 1);
checkArgument(composition.effects == Effects.EMPTY);
verifyApplicationThread();
checkState(transformerInternal == null, "There is already a export in progress.");
checkState(transformerInternal == null, "There is already an export in progress.");
TransformerInternalListener transformerInternalListener =
new TransformerInternalListener(composition);
@ -928,11 +929,11 @@ public final class Transformer {
}
@Override
public void onError(ExportResult exportResult, TransformationException exception) {
public void onError(ExportResult exportResult, ExportException exportException) {
transformerInternal = null;
listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET,
listener -> listener.onError(composition, exportResult, exception));
listener -> listener.onError(composition, exportResult, exportException));
listeners.flushEvents();
}
}

View File

@ -19,8 +19,8 @@ package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_DECODED;
import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_ENCODED;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_FAILED_RUNTIME_CHECK;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_MUXING_FAILED;
import static androidx.media3.transformer.ExportException.ERROR_CODE_FAILED_RUNTIME_CHECK;
import static androidx.media3.transformer.ExportException.ERROR_CODE_MUXING_FAILED;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
import static java.lang.annotation.ElementType.TYPE_USE;
@ -57,7 +57,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
void onCompleted(ExportResult exportResult);
void onError(ExportResult exportResult, TransformationException exception);
void onError(ExportResult exportResult, ExportException exportException);
}
/**
@ -170,8 +170,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return;
}
internalHandler
.obtainMessage(
MSG_END, END_REASON_CANCELLED, /* unused */ 0, /* transformationException */ null)
.obtainMessage(MSG_END, END_REASON_CANCELLED, /* unused */ 0, /* exportException */ null)
.sendToTarget();
clock.onThreadBlocked();
transformerConditionVariable.blockUninterruptible();
@ -201,9 +200,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
drainPipelinesInternal();
break;
case MSG_END:
endInternal(
/* endReason= */ msg.arg1,
/* transformationException= */ (TransformationException) msg.obj);
endInternal(/* endReason= */ msg.arg1, /* exportException= */ (ExportException) msg.obj);
break;
case MSG_UPDATE_PROGRESS:
updateProgressInternal(/* progressHolder= */ (ProgressHolder) msg.obj);
@ -211,10 +208,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
default:
return false;
}
} catch (TransformationException e) {
} catch (ExportException e) {
endInternal(END_REASON_ERROR, e);
} catch (RuntimeException e) {
endInternal(END_REASON_ERROR, TransformationException.createForUnexpected(e));
endInternal(END_REASON_ERROR, ExportException.createForUnexpected(e));
}
return true;
}
@ -231,7 +228,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
}
private void drainPipelinesInternal() throws TransformationException {
private void drainPipelinesInternal() throws ExportException {
for (int i = 0; i < samplePipelines.size(); i++) {
while (samplePipelines.get(i).processData()) {}
}
@ -241,8 +238,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
}
private void endInternal(
@EndReason int endReason, @Nullable TransformationException transformationException) {
private void endInternal(@EndReason int endReason, @Nullable ExportException exportException) {
ImmutableList<ExportResult.ProcessedInput> processedInputs =
compositeAssetLoader.getProcessedInputs();
exportResultBuilder
@ -251,7 +247,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
.setVideoEncoderName(encoderFactory.getVideoEncoderName());
boolean forCancellation = endReason == END_REASON_CANCELLED;
@Nullable TransformationException releaseTransformationException = null;
@Nullable ExportException releaseExportException = null;
if (!released) {
released = true;
@ -268,10 +264,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
}
}
} catch (Muxer.MuxerException e) {
releaseTransformationException =
TransformationException.createForMuxer(e, ERROR_CODE_MUXING_FAILED);
releaseExportException = ExportException.createForMuxer(e, ERROR_CODE_MUXING_FAILED);
} catch (RuntimeException e) {
releaseTransformationException = TransformationException.createForUnexpected(e);
releaseExportException = ExportException.createForUnexpected(e);
// cancelException is not reported through a listener. It is thrown in cancel(), as this
// method is blocking.
cancelException = e;
@ -286,22 +281,21 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
return;
}
TransformationException exception = transformationException;
ExportException exception = exportException;
if (exception == null) {
// We only report the exception caused by releasing the resources if there is no other
// exception. It is more intuitive to call the error callback only once and reporting the
// exception caused by releasing the resources can be confusing if it is a consequence of the
// first exception.
exception = releaseTransformationException;
exception = releaseExportException;
}
if (exception != null) {
TransformationException finalException = exception;
ExportException finalException = exception;
applicationHandler.post(
() ->
listener.onError(
exportResultBuilder.setTransformationException(finalException).build(),
finalException));
exportResultBuilder.setExportException(finalException).build(), finalException));
} else {
applicationHandler.post(() -> listener.onCompleted(exportResultBuilder.build()));
}
@ -338,9 +332,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
// AssetLoader.Listener and MuxerWrapper.Listener implementation.
@Override
public void onError(TransformationException transformationException) {
public void onError(ExportException exportException) {
internalHandler
.obtainMessage(MSG_END, END_REASON_ERROR, /* unused */ 0, transformationException)
.obtainMessage(MSG_END, END_REASON_ERROR, /* unused */ 0, exportException)
.sendToTarget();
}
@ -355,7 +349,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public void onTrackCount(int trackCount) {
if (trackCount <= 0) {
onError(
TransformationException.createForAssetLoader(
ExportException.createForAssetLoader(
new IllegalStateException("AssetLoader instances must provide at least 1 track."),
ERROR_CODE_FAILED_RUNTIME_CHECK));
return;
@ -369,7 +363,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@AssetLoader.SupportedOutputTypes int supportedOutputTypes,
long streamStartPositionUs,
long streamOffsetUs)
throws TransformationException {
throws ExportException {
int trackType = MimeTypes.getTrackType(firstInputFormat.sampleMimeType);
if (!trackAdded) {
if (generateSilentAudio) {
@ -449,8 +443,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
exportResultBuilder.setDurationMs(durationMs).setFileSizeBytes(fileSizeBytes);
internalHandler
.obtainMessage(
MSG_END, END_REASON_COMPLETED, /* unused */ 0, /* transformationException */ null)
.obtainMessage(MSG_END, END_REASON_COMPLETED, /* unused */ 0, /* exportException */ null)
.sendToTarget();
}
@ -461,7 +454,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@AssetLoader.SupportedOutputTypes int supportedOutputTypes,
long streamStartPositionUs,
long streamOffsetUs)
throws TransformationException {
throws ExportException {
checkState(supportedOutputTypes != 0);
boolean isAudio = MimeTypes.isAudio(firstInputFormat.sampleMimeType);
boolean shouldTranscode;

View File

@ -81,20 +81,20 @@ import org.checkerframework.dataflow.qual.Pure;
VideoFrameProcessor.Factory videoFrameProcessorFactory,
Codec.EncoderFactory encoderFactory,
MuxerWrapper muxerWrapper,
Consumer<TransformationException> errorConsumer,
Consumer<ExportException> errorConsumer,
FallbackListener fallbackListener,
DebugViewProvider debugViewProvider)
throws TransformationException {
throws ExportException {
super(firstInputFormat, streamStartPositionUs, muxerWrapper);
boolean isGlToneMapping = false;
if (isTransferHdr(firstInputFormat.colorInfo)) {
if (transformationRequest.hdrMode == HDR_MODE_EXPERIMENTAL_FORCE_INTERPRET_HDR_AS_SDR) {
if (SDK_INT < 29) {
throw TransformationException.createForCodec(
throw ExportException.createForCodec(
new IllegalArgumentException(
"Interpreting HDR video as SDR is not supported on this device."),
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
/* isVideo= */ true,
/* isDecoder= */ true,
firstInputFormat);
@ -154,7 +154,7 @@ import org.checkerframework.dataflow.qual.Pure;
try {
checkNotNull(videoFrameProcessor)
.setOutputSurfaceInfo(encoderWrapper.getSurfaceInfo(width, height));
} catch (TransformationException exception) {
} catch (ExportException exception) {
errorConsumer.accept(exception);
}
}
@ -168,9 +168,8 @@ import org.checkerframework.dataflow.qual.Pure;
@Override
public void onError(VideoFrameProcessingException exception) {
errorConsumer.accept(
TransformationException.createForVideoFrameProcessingException(
exception,
TransformationException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED));
ExportException.createForVideoFrameProcessingException(
exception, ExportException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED));
}
@Override
@ -179,14 +178,14 @@ import org.checkerframework.dataflow.qual.Pure;
lastProcessedFramePresentationTimeUs;
try {
encoderWrapper.signalEndOfInputStream();
} catch (TransformationException exception) {
} catch (ExportException exception) {
errorConsumer.accept(exception);
}
}
});
} catch (VideoFrameProcessingException e) {
throw TransformationException.createForVideoFrameProcessingException(
e, TransformationException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED);
throw ExportException.createForVideoFrameProcessingException(
e, ExportException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED);
}
// The decoder rotates encoded frames for display by firstInputFormat.rotationDegrees.
int decodedWidth =
@ -249,13 +248,13 @@ import org.checkerframework.dataflow.qual.Pure;
@Override
@Nullable
protected Format getMuxerInputFormat() throws TransformationException {
protected Format getMuxerInputFormat() throws ExportException {
return encoderWrapper.getOutputFormat();
}
@Override
@Nullable
protected DecoderInputBuffer getMuxerInputBuffer() throws TransformationException {
protected DecoderInputBuffer getMuxerInputBuffer() throws ExportException {
encoderOutputBuffer.data = encoderWrapper.getOutputBuffer();
if (encoderOutputBuffer.data == null) {
return null;
@ -277,7 +276,7 @@ import org.checkerframework.dataflow.qual.Pure;
}
@Override
protected void releaseMuxerInputBuffer() throws TransformationException {
protected void releaseMuxerInputBuffer() throws ExportException {
encoderWrapper.releaseOutputBuffer(/* render= */ false);
}
@ -398,7 +397,7 @@ import org.checkerframework.dataflow.qual.Pure;
@Nullable
public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight)
throws TransformationException {
throws ExportException {
if (releaseEncoder) {
return null;
}
@ -470,14 +469,14 @@ import org.checkerframework.dataflow.qual.Pure;
return encoderSurfaceInfo;
}
public void signalEndOfInputStream() throws TransformationException {
public void signalEndOfInputStream() throws ExportException {
if (encoder != null) {
encoder.signalEndOfInputStream();
}
}
@Nullable
public Format getOutputFormat() throws TransformationException {
public Format getOutputFormat() throws ExportException {
if (encoder == null) {
return null;
}
@ -489,16 +488,16 @@ import org.checkerframework.dataflow.qual.Pure;
}
@Nullable
public ByteBuffer getOutputBuffer() throws TransformationException {
public ByteBuffer getOutputBuffer() throws ExportException {
return encoder != null ? encoder.getOutputBuffer() : null;
}
@Nullable
public MediaCodec.BufferInfo getOutputBufferInfo() throws TransformationException {
public MediaCodec.BufferInfo getOutputBufferInfo() throws ExportException {
return encoder != null ? encoder.getOutputBufferInfo() : null;
}
public void releaseOutputBuffer(boolean render) throws TransformationException {
public void releaseOutputBuffer(boolean render) throws ExportException {
if (encoder != null) {
encoder.releaseOutputBuffer(render);
}

View File

@ -16,7 +16,7 @@
package androidx.media3.transformer;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
import static androidx.media3.transformer.ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
@ -109,11 +109,11 @@ public class DefaultEncoderFactoryTest {
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H265, 1920, 1080, 30);
DefaultEncoderFactory encoderFactory = new DefaultEncoderFactory.Builder(context).build();
TransformationException transformationException =
ExportException exportException =
assertThrows(
TransformationException.class,
ExportException.class,
() -> encoderFactory.createForVideoEncoding(requestedVideoFormat));
assertThat(transformationException.errorCode).isEqualTo(ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
assertThat(exportException.errorCode).isEqualTo(ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
}
@Test
@ -239,7 +239,7 @@ public class DefaultEncoderFactoryTest {
public void createForVideoEncoding_withNoAvailableEncoderFromEncoderSelector_throws() {
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
assertThrows(
TransformationException.class,
ExportException.class,
() ->
new DefaultEncoderFactory.Builder(context)
.setVideoEncoderSelector((mimeType) -> ImmutableList.of())

View File

@ -85,7 +85,7 @@ public class ExoPlayerAssetLoaderTest {
}
@Override
public void onError(TransformationException e) {
public void onError(ExportException e) {
exceptionRef.set(e);
}

View File

@ -507,9 +507,8 @@ public final class TransformerEndToEndTest {
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_DECODER);
transformer.start(mediaItem, outputPath);
TransformationException exception =
assertThrows(
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
ExportException exception =
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
verify(mockListener1).onError(compositionArgumentCaptor.capture(), any(), eq(exception));
Composition composition = compositionArgumentCaptor.getValue();
@ -620,7 +619,7 @@ public final class TransformerEndToEndTest {
transformer.start(mediaItem, outputPath);
try {
TransformerTestRunner.runLooper(transformer);
} catch (TransformationException transformationException) {
} catch (ExportException exportException) {
// Ignore exception thrown.
}
@ -715,12 +714,11 @@ public final class TransformerEndToEndTest {
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_MUXER);
transformer.start(mediaItem, outputPath);
TransformationException exception =
assertThrows(
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
ExportException exception =
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
}
@Test
@ -735,12 +733,11 @@ public final class TransformerEndToEndTest {
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_DECODER);
transformer.start(mediaItem, outputPath);
TransformationException exception =
assertThrows(
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
ExportException exception =
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode)
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
}
@Test
@ -749,11 +746,10 @@ public final class TransformerEndToEndTest {
MediaItem mediaItem = MediaItem.fromUri("asset:///non-existing-path.mp4");
transformer.start(mediaItem, outputPath);
TransformationException exception =
assertThrows(
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
ExportException exception =
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
assertThat(exception).hasCauseThat().hasCauseThat().isInstanceOf(IOException.class);
assertThat(exception.errorCode).isEqualTo(TransformationException.ERROR_CODE_IO_FILE_NOT_FOUND);
assertThat(exception.errorCode).isEqualTo(ExportException.ERROR_CODE_IO_FILE_NOT_FOUND);
}
@Test
@ -822,11 +818,10 @@ public final class TransformerEndToEndTest {
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);
transformer.start(mediaItem, outputPath);
TransformationException exception =
assertThrows(
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
ExportException exception =
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
assertThat(exception).hasCauseThat().isInstanceOf(IllegalStateException.class);
assertThat(exception.errorCode).isEqualTo(TransformationException.ERROR_CODE_MUXING_FAILED);
assertThat(exception.errorCode).isEqualTo(ExportException.ERROR_CODE_MUXING_FAILED);
}
@Test
@ -857,7 +852,7 @@ public final class TransformerEndToEndTest {
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
// TODO(b/264974805): Make transformation output deterministic and check it against dump file.
assertThat(exportResult.transformationException).isNull();
assertThat(exportResult.exportException).isNull();
}
@Test
@ -946,11 +941,10 @@ public final class TransformerEndToEndTest {
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
transformer.start(editedMediaItem, outputPath);
TransformationException transformationException =
assertThrows(
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
ExportException exportException =
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
assertThat(transformationException).hasCauseThat().isInstanceOf(IllegalStateException.class);
assertThat(exportException).hasCauseThat().isInstanceOf(IllegalStateException.class);
}
@Test
@ -1427,7 +1421,7 @@ public final class TransformerEndToEndTest {
if (sampleConsumerRef != null) {
sampleConsumerRef.set(sampleConsumer);
}
} catch (TransformationException e) {
} catch (ExportException e) {
throw new IllegalStateException(e);
}
}

View File

@ -36,13 +36,13 @@ public final class TransformerTestRunner {
*
* @param transformer The {@link Transformer}.
* @return The {@link ExportResult}.
* @throws TransformationException If the transformation threw an exception.
* @throws ExportException If the transformation threw an exception.
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
* @throws IllegalStateException If the method is not called from the main thread.
*/
public static ExportResult runLooper(Transformer transformer)
throws TransformationException, TimeoutException {
throws ExportException, TimeoutException {
AtomicReference<@NullableType ExportResult> exportResultRef = new AtomicReference<>();
transformer.addListener(
@ -54,11 +54,9 @@ public final class TransformerTestRunner {
@Override
public void onError(
Composition composition,
ExportResult exportResult,
TransformationException exception) {
if (!Objects.equals(exportResult.transformationException, exception)) {
exportResult = exportResult.buildUpon().setTransformationException(exception).build();
Composition composition, ExportResult exportResult, ExportException exportException) {
if (!Objects.equals(exportResult.exportException, exportException)) {
exportResult = exportResult.buildUpon().setExportException(exportException).build();
}
exportResultRef.set(exportResult);
}
@ -66,8 +64,8 @@ public final class TransformerTestRunner {
runLooperUntil(transformer.getApplicationLooper(), () -> exportResultRef.get() != null);
ExportResult exportResult = checkNotNull(exportResultRef.get());
if (exportResult.transformationException != null) {
throw exportResult.transformationException;
if (exportResult.exportException != null) {
throw exportResult.exportException;
}
return exportResult;

View File

@ -118,8 +118,7 @@ public final class VideoEncoderWrapperTest {
}
@Test
public void getSurfaceInfo_withEncoderFallback_usesFallbackResolution()
throws TransformationException {
public void getSurfaceInfo_withEncoderFallback_usesFallbackResolution() throws Exception {
int inputWidth = 200;
int inputHeight = 150;
int fallbackWidth = 100;