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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,8 +30,8 @@ import androidx.media3.common.util.Log;
import androidx.media3.effect.ScaleToFitTransformation; import androidx.media3.effect.ScaleToFitTransformation;
import androidx.media3.transformer.EditedMediaItem; import androidx.media3.transformer.EditedMediaItem;
import androidx.media3.transformer.Effects; import androidx.media3.transformer.Effects;
import androidx.media3.transformer.ExportException;
import androidx.media3.transformer.ExportTestResult; import androidx.media3.transformer.ExportTestResult;
import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest; import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.Transformer; import androidx.media3.transformer.Transformer;
import androidx.media3.transformer.TransformerAndroidTestRunner; import androidx.media3.transformer.TransformerAndroidTestRunner;
@ -84,11 +84,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
.run(testId, mediaItem); .run(testId, mediaItem);
Log.i(TAG, "Tone mapped."); Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) { } catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString()); Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode) 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); .run(testId, mediaItem);
Log.i(TAG, "Tone mapped."); Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) { } catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString()); Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode) 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); .run(testId, editedMediaItem);
Log.i(TAG, "Tone mapped."); Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) { } catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString()); Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode) 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); .run(testId, editedMediaItem);
Log.i(TAG, "Tone mapped."); Log.i(TAG, "Tone mapped.");
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) { } catch (ExportException exception) {
Log.i(TAG, checkNotNull(exception.getCause()).toString()); Log.i(TAG, checkNotNull(exception.getCause()).toString());
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class); assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode) 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.Log;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.transformer.AndroidTestUtil; import androidx.media3.transformer.AndroidTestUtil;
import androidx.media3.transformer.ExportException;
import androidx.media3.transformer.ExportTestResult; import androidx.media3.transformer.ExportTestResult;
import androidx.media3.transformer.TransformationException;
import androidx.media3.transformer.TransformationRequest; import androidx.media3.transformer.TransformationRequest;
import androidx.media3.transformer.Transformer; import androidx.media3.transformer.Transformer;
import androidx.media3.transformer.TransformerAndroidTestRunner; import androidx.media3.transformer.TransformerAndroidTestRunner;
@ -91,9 +91,9 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
.build() .build()
.run(testId, mediaItem); .run(testId, mediaItem);
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) { } catch (ExportException exception) {
Log.e(TAG, "Error during transformation.", exception); Log.e(TAG, "Error during export.", exception);
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) { if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
throw exception; throw exception;
} }
} }
@ -141,9 +141,9 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
.build() .build()
.run(testId, mediaItem); .run(testId, mediaItem);
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR); assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
} catch (TransformationException exception) { } catch (ExportException exception) {
Log.e(TAG, "Error during transformation.", exception); Log.e(TAG, "Error during export.", exception);
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) { if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
throw exception; throw exception;
} }
} }

View File

@ -97,20 +97,20 @@ public interface AssetLoader {
* non-negative, in microseconds. * non-negative, in microseconds.
* @return The {@link SampleConsumer} describing the type of sample data expected, and to which * @return The {@link SampleConsumer} describing the type of sample data expected, and to which
* to pass this data. * 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( SampleConsumer onTrackAdded(
Format format, Format format,
@SupportedOutputTypes int supportedOutputTypes, @SupportedOutputTypes int supportedOutputTypes,
long streamStartPositionUs, long streamStartPositionUs,
long streamOffsetUs) long streamOffsetUs)
throws TransformationException; throws ExportException;
/** /**
* Called if an error occurs in the asset loader. In this case, the asset loader will be * Called if an error occurs in the asset loader. In this case, the asset loader will be
* {@linkplain #release() released} automatically. * {@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, Codec.EncoderFactory encoderFactory,
MuxerWrapper muxerWrapper, MuxerWrapper muxerWrapper,
FallbackListener fallbackListener) FallbackListener fallbackListener)
throws TransformationException { throws ExportException {
super(firstInputFormat, streamStartPositionUs, muxerWrapper); super(firstInputFormat, streamStartPositionUs, muxerWrapper);
if (generateSilentAudioDurationUs != C.TIME_UNSET) { if (generateSilentAudioDurationUs != C.TIME_UNSET) {
@ -112,7 +112,7 @@ import org.checkerframework.dataflow.qual.Pure;
try { try {
encoderInputAudioFormat = audioProcessingPipeline.configure(pipelineInputAudioFormat); encoderInputAudioFormat = audioProcessingPipeline.configure(pipelineInputAudioFormat);
} catch (AudioProcessor.UnhandledAudioFormatException unhandledAudioFormatException) { } catch (AudioProcessor.UnhandledAudioFormatException unhandledAudioFormatException) {
throw TransformationException.createForAudioProcessing( throw ExportException.createForAudioProcessing(
unhandledAudioFormatException, pipelineInputAudioFormat); unhandledAudioFormatException, pipelineInputAudioFormat);
} }
@ -175,7 +175,7 @@ import org.checkerframework.dataflow.qual.Pure;
} }
@Override @Override
protected boolean processDataUpToMuxer() throws TransformationException { protected boolean processDataUpToMuxer() throws ExportException {
if (!audioProcessingPipeline.isOperational()) { if (!audioProcessingPipeline.isOperational()) {
return feedEncoderFromInput(); return feedEncoderFromInput();
} }
@ -185,13 +185,13 @@ import org.checkerframework.dataflow.qual.Pure;
@Override @Override
@Nullable @Nullable
protected Format getMuxerInputFormat() throws TransformationException { protected Format getMuxerInputFormat() throws ExportException {
return encoder.getOutputFormat(); return encoder.getOutputFormat();
} }
@Override @Override
@Nullable @Nullable
protected DecoderInputBuffer getMuxerInputBuffer() throws TransformationException { protected DecoderInputBuffer getMuxerInputBuffer() throws ExportException {
encoderOutputBuffer.data = encoder.getOutputBuffer(); encoderOutputBuffer.data = encoder.getOutputBuffer();
if (encoderOutputBuffer.data == null) { if (encoderOutputBuffer.data == null) {
return null; return null;
@ -202,7 +202,7 @@ import org.checkerframework.dataflow.qual.Pure;
} }
@Override @Override
protected void releaseMuxerInputBuffer() throws TransformationException { protected void releaseMuxerInputBuffer() throws ExportException {
encoder.releaseOutputBuffer(/* render= */ false); 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. * @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)) { if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) {
return false; 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. * @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)) { if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) {
return false; 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 * 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. * 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); ByteBuffer encoderInputBufferData = checkNotNull(encoderInputBuffer.data);
int bufferLimit = inputBuffer.limit(); int bufferLimit = inputBuffer.limit();
inputBuffer.limit(min(bufferLimit, inputBuffer.position() + encoderInputBufferData.capacity())); inputBuffer.limit(min(bufferLimit, inputBuffer.position() + encoderInputBufferData.capacity()));
@ -336,7 +336,7 @@ import org.checkerframework.dataflow.qual.Pure;
encoder.queueInputBuffer(encoderInputBuffer); encoder.queueInputBuffer(encoderInputBuffer);
} }
private void queueEndOfStreamToEncoder() throws TransformationException { private void queueEndOfStreamToEncoder() throws ExportException {
checkState(checkNotNull(encoderInputBuffer.data).position() == 0); checkState(checkNotNull(encoderInputBuffer.data).position() == 0);
encoderInputBuffer.timeUs = nextEncoderInputBufferTimeUs; encoderInputBuffer.timeUs = nextEncoderInputBufferTimeUs;
encoderInputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM); encoderInputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);

View File

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

View File

@ -30,14 +30,14 @@ import androidx.media3.common.Format;
} }
@Override @Override
public Codec createForAudioEncoding(Format format) throws TransformationException { public Codec createForAudioEncoding(Format format) throws ExportException {
Codec audioEncoder = encoderFactory.createForAudioEncoding(format); Codec audioEncoder = encoderFactory.createForAudioEncoding(format);
audioEncoderName = audioEncoder.getName(); audioEncoderName = audioEncoder.getName();
return audioEncoder; return audioEncoder;
} }
@Override @Override
public Codec createForVideoEncoding(Format format) throws TransformationException { public Codec createForVideoEncoding(Format format) throws ExportException {
Codec videoEncoder = encoderFactory.createForVideoEncoding(format); Codec videoEncoder = encoderFactory.createForVideoEncoding(format);
videoEncoderName = videoEncoder.getName(); videoEncoderName = videoEncoder.getName();
return videoEncoder; 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 * @param format The {@link Format} (of the input data) used to determine the underlying decoder
* and its configuration values. * and its configuration values.
* @return A {@link Codec} for audio decoding. * @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. * 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 outputSurface The {@link Surface} to which the decoder output is rendered.
* @param requestSdrToneMapping Whether to request tone-mapping to SDR. * @param requestSdrToneMapping Whether to request tone-mapping to SDR.
* @return A {@link Codec} for video decoding. * @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( Codec createForVideoDecoding(
Format format, Surface outputSurface, boolean requestSdrToneMapping) Format format, Surface outputSurface, boolean requestSdrToneMapping) throws ExportException;
throws TransformationException;
} }
/** A factory for {@linkplain Codec encoder} instances. */ /** A factory for {@linkplain Codec encoder} instances. */
@ -76,9 +75,9 @@ public interface Codec {
* those of the desired output video format. * those of the desired output video format.
* @return A {@link Codec} for encoding audio to the requested {@link Format#sampleMimeType MIME * @return A {@link Codec} for encoding audio to the requested {@link Format#sampleMimeType MIME
* type}. * 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. * Returns a {@link Codec} for video encoding.
@ -96,9 +95,9 @@ public interface Codec {
* Format#height}, therefore the video is always in landscape orientation. * Format#height}, therefore the video is always in landscape orientation.
* @return A {@link Codec} for encoding video to the requested {@linkplain Format#sampleMimeType * @return A {@link Codec} for encoding video to the requested {@linkplain Format#sampleMimeType
* MIME type}. * 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. */ /** Returns whether the audio needs to be encoded because of encoder specific configuration. */
default boolean audioNeedsEncoding() { default boolean audioNeedsEncoding() {
@ -148,9 +147,9 @@ public interface Codec {
* @param inputBuffer The buffer where the dequeued buffer data is stored, at {@link * @param inputBuffer The buffer where the dequeued buffer data is stored, at {@link
* DecoderInputBuffer#data inputBuffer.data}. * DecoderInputBuffer#data inputBuffer.data}.
* @return Whether an input buffer is ready to be used. * @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 * 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. * to receive input.
* *
* @param inputBuffer The {@linkplain DecoderInputBuffer input buffer}. * @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. * 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) * should be set on the last input buffer {@linkplain #queueInputBuffer(DecoderInputBuffer)
* queued}. * 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. * 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 @Nullable
Format getOutputFormat() throws TransformationException; Format getOutputFormat() throws ExportException;
/** /**
* Returns the current output {@link ByteBuffer}, or {@code null} if unavailable. * 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 * <p>This method must not be called on video decoders because they must output to a {@link
* Surface}. * Surface}.
* *
* @throws TransformationException If the underlying decoder or encoder encounters a problem. * @throws ExportException If the underlying decoder or encoder encounters a problem.
*/ */
@Nullable @Nullable
ByteBuffer getOutputBuffer() throws TransformationException; ByteBuffer getOutputBuffer() throws ExportException;
/** /**
* Returns the {@link BufferInfo} associated with the current output buffer, or {@code null} if * 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. * <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 @Nullable
BufferInfo getOutputBufferInfo() throws TransformationException; BufferInfo getOutputBufferInfo() throws ExportException;
/** /**
* Releases the current output buffer. * Releases the current output buffer.
@ -218,9 +217,9 @@ public interface Codec {
* be available until the current output buffer has been released. * be available until the current output buffer has been released.
* *
* @param render Whether the buffer needs to be rendered to the output {@link Surface}. * @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. * 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, @SupportedOutputTypes int supportedOutputTypes,
long streamStartPositionUs, long streamStartPositionUs,
long streamOffsetUs) long streamOffsetUs)
throws TransformationException { throws ExportException {
int trackType = MimeTypes.getTrackType(format.sampleMimeType); int trackType = MimeTypes.getTrackType(format.sampleMimeType);
SampleConsumer sampleConsumer; SampleConsumer sampleConsumer;
if (currentMediaItemIndex.get() == 0) { if (currentMediaItemIndex.get() == 0) {
@ -201,8 +201,8 @@ import java.util.concurrent.atomic.AtomicLong;
} }
@Override @Override
public void onError(TransformationException exception) { public void onError(ExportException exportException) {
compositeAssetLoaderListener.onError(exception); compositeAssetLoaderListener.onError(exportException);
} }
private void addCurrentProcessedInput() { private void addCurrentProcessedInput() {

View File

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

View File

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

View File

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

View File

@ -45,7 +45,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} }
@Override @Override
protected void initDecoder(Format inputFormat) throws TransformationException { protected void initDecoder(Format inputFormat) throws ExportException {
decoder = decoderFactory.createForAudioDecoding(inputFormat); 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. * 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. * @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 @Override
@RequiresNonNull("sampleConsumer") @RequiresNonNull("sampleConsumer")
protected boolean feedConsumerFromDecoder() throws TransformationException { protected boolean feedConsumerFromDecoder() throws ExportException {
@Nullable DecoderInputBuffer sampleConsumerInputBuffer = sampleConsumer.getInputBuffer(); @Nullable DecoderInputBuffer sampleConsumerInputBuffer = sampleConsumer.getInputBuffer();
if (sampleConsumerInputBuffer == null) { if (sampleConsumerInputBuffer == null) {
return false; return false;

View File

@ -101,7 +101,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
} else { } else {
while (feedConsumerFromInput()) {} while (feedConsumerFromInput()) {}
} }
} catch (TransformationException e) { } catch (ExportException e) {
isTransformationRunning = false; isTransformationRunning = false;
assetLoaderListener.onError(e); assetLoaderListener.onError(e);
} }
@ -140,7 +140,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
/** Initializes {@link #decoder} with an appropriate {@linkplain Codec decoder}. */ /** Initializes {@link #decoder} with an appropriate {@linkplain Codec decoder}. */
@RequiresNonNull("sampleConsumer") @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 * 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. * 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. * @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") @RequiresNonNull("sampleConsumer")
protected abstract boolean feedConsumerFromDecoder() throws TransformationException; protected abstract boolean feedConsumerFromDecoder() throws ExportException;
@EnsuresNonNullIf(expression = "sampleConsumer", result = true) @EnsuresNonNullIf(expression = "sampleConsumer", result = true)
private boolean ensureConfigured() throws TransformationException { private boolean ensureConfigured() throws ExportException {
if (sampleConsumer != null) { if (sampleConsumer != null) {
return true; return true;
} }
@ -193,9 +193,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
* Attempts to read input data and pass it to the decoder. * 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. * @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); Codec decoder = checkNotNull(this.decoder);
if (!decoder.maybeDequeueInputBuffer(decoderInputBuffer)) { if (!decoder.maybeDequeueInputBuffer(decoderInputBuffer)) {
return false; return false;

View File

@ -65,7 +65,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@Override @Override
@RequiresNonNull("sampleConsumer") @RequiresNonNull("sampleConsumer")
protected void initDecoder(Format inputFormat) throws TransformationException { protected void initDecoder(Format inputFormat) throws ExportException {
boolean isDecoderToneMappingRequired = boolean isDecoderToneMappingRequired =
ColorInfo.isTransferHdr(inputFormat.colorInfo) ColorInfo.isTransferHdr(inputFormat.colorInfo)
&& !ColorInfo.isTransferHdr(sampleConsumer.getExpectedInputColorInfo()); && !ColorInfo.isTransferHdr(sampleConsumer.getExpectedInputColorInfo());
@ -106,7 +106,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
@Override @Override
@RequiresNonNull("sampleConsumer") @RequiresNonNull("sampleConsumer")
protected boolean feedConsumerFromDecoder() throws TransformationException { protected boolean feedConsumerFromDecoder() throws ExportException {
Codec decoder = checkNotNull(this.decoder); Codec decoder = checkNotNull(this.decoder);
if (decoder.isEnded()) { if (decoder.isEnded()) {
sampleConsumer.signalEndOfVideoInput(); 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_BUFFER_FOR_PLAYBACK_MS;
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_MAX_BUFFER_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.exoplayer.DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_FAILED_RUNTIME_CHECK; import static androidx.media3.transformer.ExportException.ERROR_CODE_FAILED_RUNTIME_CHECK;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_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_AVAILABLE;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE;
@ -309,7 +309,7 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
player.play(); player.play();
} else { } else {
assetLoaderListener.onError( assetLoaderListener.onError(
TransformationException.createForAssetLoader( ExportException.createForAssetLoader(
new IllegalStateException("The asset loader has no track to output."), new IllegalStateException("The asset loader has no track to output."),
ERROR_CODE_FAILED_RUNTIME_CHECK)); ERROR_CODE_FAILED_RUNTIME_CHECK));
} }
@ -317,12 +317,12 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
@Override @Override
public void onPlayerError(PlaybackException error) { public void onPlayerError(PlaybackException error) {
@TransformationException.ErrorCode @ExportException.ErrorCode
int errorCode = int errorCode =
checkNotNull( checkNotNull(
TransformationException.NAME_TO_ERROR_CODE.getOrDefault( ExportException.NAME_TO_ERROR_CODE.getOrDefault(
error.getErrorCodeName(), ERROR_CODE_UNSPECIFIED)); 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 width;
private int videoFrameCount; private int videoFrameCount;
@Nullable private String videoEncoderName; @Nullable private String videoEncoderName;
@Nullable private TransformationException transformationException; @Nullable private ExportException exportException;
/** Creates a builder. */ /** Creates a builder. */
public Builder() { public Builder() {
@ -206,11 +206,10 @@ public final class ExportResult {
return this; return this;
} }
/** Sets the {@link TransformationException} that caused the export to fail. */ /** Sets the {@link ExportException} that caused the export to fail. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setTransformationException( public Builder setExportException(@Nullable ExportException exportException) {
@Nullable TransformationException transformationException) { this.exportException = exportException;
this.transformationException = transformationException;
return this; return this;
} }
@ -231,7 +230,7 @@ public final class ExportResult {
width, width,
videoFrameCount, videoFrameCount,
videoEncoderName, videoEncoderName,
transformationException); exportException);
} }
} }
@ -296,10 +295,10 @@ public final class ExportResult {
@Nullable public final String videoEncoderName; @Nullable public final String videoEncoderName;
/** /**
* The {@link TransformationException} that caused the export to fail, or {@code null} if the * The {@link ExportException} that caused the export to fail, or {@code null} if the export was a
* export was a success. * success.
*/ */
@Nullable public final TransformationException transformationException; @Nullable public final ExportException exportException;
private ExportResult( private ExportResult(
ImmutableList<ProcessedInput> processedInputs, ImmutableList<ProcessedInput> processedInputs,
@ -316,7 +315,7 @@ public final class ExportResult {
int width, int width,
int videoFrameCount, int videoFrameCount,
@Nullable String videoEncoderName, @Nullable String videoEncoderName,
@Nullable TransformationException transformationException) { @Nullable ExportException exportException) {
this.processedInputs = processedInputs; this.processedInputs = processedInputs;
this.durationMs = durationMs; this.durationMs = durationMs;
this.fileSizeBytes = fileSizeBytes; this.fileSizeBytes = fileSizeBytes;
@ -331,7 +330,7 @@ public final class ExportResult {
this.width = width; this.width = width;
this.videoFrameCount = videoFrameCount; this.videoFrameCount = videoFrameCount;
this.videoEncoderName = videoEncoderName; this.videoEncoderName = videoEncoderName;
this.transformationException = transformationException; this.exportException = exportException;
} }
public Builder buildUpon() { public Builder buildUpon() {
@ -350,7 +349,7 @@ public final class ExportResult {
.setWidth(width) .setWidth(width)
.setVideoFrameCount(videoFrameCount) .setVideoFrameCount(videoFrameCount)
.setVideoEncoderName(videoEncoderName) .setVideoEncoderName(videoEncoderName)
.setTransformationException(transformationException); .setExportException(exportException);
} }
@Override @Override
@ -376,7 +375,7 @@ public final class ExportResult {
&& width == result.width && width == result.width
&& videoFrameCount == result.videoFrameCount && videoFrameCount == result.videoFrameCount
&& Objects.equals(videoEncoderName, result.videoEncoderName) && Objects.equals(videoEncoderName, result.videoEncoderName)
&& Objects.equals(transformationException, result.transformationException); && Objects.equals(exportException, result.exportException);
} }
@Override @Override
@ -395,7 +394,7 @@ public final class ExportResult {
result = 31 * result + width; result = 31 * result + width;
result = 31 * result + videoFrameCount; result = 31 * result + videoFrameCount;
result = 31 * result + Objects.hashCode(videoEncoderName); result = 31 * result + Objects.hashCode(videoEncoderName);
result = 31 * result + Objects.hashCode(transformationException); result = 31 * result + Objects.hashCode(exportException);
return result; 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.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_IO_UNSPECIFIED; import static androidx.media3.transformer.ExportException.ERROR_CODE_IO_UNSPECIFIED;
import static androidx.media3.transformer.TransformationException.ERROR_CODE_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_AVAILABLE;
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED; import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
@ -101,19 +101,17 @@ public final class ImageAssetLoader implements AssetLoader {
sampleConsumer.queueInputBitmap( sampleConsumer.queueInputBitmap(
bitmap, editedMediaItem.durationUs, editedMediaItem.frameRate); bitmap, editedMediaItem.durationUs, editedMediaItem.frameRate);
sampleConsumer.signalEndOfVideoInput(); sampleConsumer.signalEndOfVideoInput();
} catch (TransformationException e) { } catch (ExportException e) {
listener.onError(e); listener.onError(e);
} catch (RuntimeException e) { } catch (RuntimeException e) {
listener.onError( listener.onError(ExportException.createForAssetLoader(e, ERROR_CODE_UNSPECIFIED));
TransformationException.createForAssetLoader(e, ERROR_CODE_UNSPECIFIED));
} }
progress = 100; progress = 100;
} }
@Override @Override
public void onFailure(Throwable t) { public void onFailure(Throwable t) {
listener.onError( listener.onError(ExportException.createForAssetLoader(t, ERROR_CODE_IO_UNSPECIFIED));
TransformationException.createForAssetLoader(t, ERROR_CODE_IO_UNSPECIFIED));
} }
}, },
MoreExecutors.directExecutor()); MoreExecutors.directExecutor());

View File

@ -53,7 +53,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
void onEnded(long durationMs, long fileSizeBytes); 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; isAborted = true;
listener.onError( listener.onError(
TransformationException.createForMuxer( ExportException.createForMuxer(
new IllegalStateException( new IllegalStateException(
"No output sample written in the last " "No output sample written in the last "
+ maxDelayBetweenSamplesMs + maxDelayBetweenSamplesMs
+ " milliseconds. Aborting transformation."), + " milliseconds. Aborting transformation."),
TransformationException.ERROR_CODE_MUXING_FAILED)); ExportException.ERROR_CODE_MUXING_FAILED));
}, },
maxDelayBetweenSamplesMs, maxDelayBetweenSamplesMs,
MILLISECONDS); 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 * Processes the input data and returns whether it may be possible to process more data by calling
* this method again. * this method again.
*/ */
public final boolean processData() throws TransformationException { public final boolean processData() throws ExportException {
return feedMuxer() || processDataUpToMuxer(); return feedMuxer() || processDataUpToMuxer();
} }
/** Releases all resources held by the pipeline. */ /** Releases all resources held by the pipeline. */
public abstract void release(); public abstract void release();
protected boolean processDataUpToMuxer() throws TransformationException { protected boolean processDataUpToMuxer() throws ExportException {
return false; return false;
} }
@Nullable @Nullable
protected abstract Format getMuxerInputFormat() throws TransformationException; protected abstract Format getMuxerInputFormat() throws ExportException;
@Nullable @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(); 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 * 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. * data immediately by calling this method again.
*/ */
private boolean feedMuxer() throws TransformationException { private boolean feedMuxer() throws ExportException {
if (!muxerWrapperTrackAdded) { if (!muxerWrapperTrackAdded) {
@Nullable Format inputFormat = getMuxerInputFormat(); @Nullable Format inputFormat = getMuxerInputFormat();
if (inputFormat == null) { if (inputFormat == null) {
@ -98,8 +98,7 @@ import java.util.List;
try { try {
muxerWrapper.addTrackFormat(inputFormat); muxerWrapper.addTrackFormat(inputFormat);
} catch (Muxer.MuxerException e) { } catch (Muxer.MuxerException e) {
throw TransformationException.createForMuxer( throw ExportException.createForMuxer(e, ExportException.ERROR_CODE_MUXING_FAILED);
e, TransformationException.ERROR_CODE_MUXING_FAILED);
} }
muxerWrapperTrackAdded = true; muxerWrapperTrackAdded = true;
} }
@ -126,8 +125,7 @@ import java.util.List;
return false; return false;
} }
} catch (Muxer.MuxerException e) { } catch (Muxer.MuxerException e) {
throw TransformationException.createForMuxer( throw ExportException.createForMuxer(e, ExportException.ERROR_CODE_MUXING_FAILED);
e, TransformationException.ERROR_CODE_MUXING_FAILED);
} }
releaseMuxerInputBuffer(); releaseMuxerInputBuffer();
@ -152,10 +150,10 @@ import java.util.List;
* @param muxerSupportedMimeTypes The list of sample {@linkplain MimeTypes MIME types} that the * @param muxerSupportedMimeTypes The list of sample {@linkplain MimeTypes MIME types} that the
* muxer supports. * muxer supports.
* @return A supported {@linkplain MimeTypes MIME type}. * @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( 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)); boolean isVideo = MimeTypes.isVideo(checkNotNull(requestedFormat.sampleMimeType));
ImmutableSet.Builder<String> mimeTypesToCheckSetBuilder = ImmutableSet.Builder<String> mimeTypesToCheckSetBuilder =
@ -185,16 +183,16 @@ import java.util.List;
throw createNoSupportedMimeTypeException(requestedFormat); 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."; 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); boolean isVideo = MimeTypes.isVideo(format.sampleMimeType);
if (isVideo && isTransferHdr(format.colorInfo)) { if (isVideo && isTransferHdr(format.colorInfo)) {
errorMessage += " Requested HDR colorInfo: " + format.colorInfo; errorMessage += " Requested HDR colorInfo: " + format.colorInfo;
} }
return TransformationException.createForCodec( return ExportException.createForCodec(
new IllegalArgumentException(errorMessage), new IllegalArgumentException(errorMessage),
errorCode, errorCode,
isVideo, isVideo,

View File

@ -33,7 +33,10 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** Thrown when a non-locally recoverable transformation failure occurs. */ /**
* @deprecated Use {@link ExportException} instead.
*/
@Deprecated
@UnstableApi @UnstableApi
public final class TransformationException extends Exception { public final class TransformationException extends Exception {
@ -331,6 +334,12 @@ public final class TransformationException extends Exception {
this.timestampMs = Clock.DEFAULT.elapsedRealtime(); 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 * Returns whether the error data associated to this exception equals the error data associated to
* {@code other}. * {@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 * <p>Supported on API 31+, by some device and HDR format combinations. Tone-mapping is only
* guaranteed to be supported from Android T onwards. * 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; 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 * implementation, but should have much wider support and have more consistent results across
* devices. * 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; 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; width = exportResult.width;
videoFrameCount = exportResult.videoFrameCount; videoFrameCount = exportResult.videoFrameCount;
videoEncoderName = exportResult.videoEncoderName; videoEncoderName = exportResult.videoEncoderName;
transformationException = exportResult.transformationException; if (exportResult.exportException != null) {
transformationException = new TransformationException(exportResult.exportException);
}
} }
/** Sets the {@linkplain ProcessedInput processed inputs}. */ /** 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 @Deprecated
default void onTransformationError(MediaItem inputMediaItem, Exception exception) {} default void onTransformationError(MediaItem inputMediaItem, Exception exception) {}
/** /**
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead. * @deprecated Use {@link #onError(Composition, ExportResult, ExportException)} instead.
*/ */
@Deprecated @Deprecated
default void onTransformationError( 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 @Deprecated
default void onTransformationError( default void onTransformationError(
@ -526,16 +526,17 @@ public final class Transformer {
* *
* @param composition The {@link Composition} for which the exception occurs. * @param composition The {@link Composition} for which the exception occurs.
* @param exportResult The {@link ExportResult} of the export. * @param exportResult The {@link ExportResult} of the export.
* @param exception The {@link TransformationException} describing the exception. This is the * @param exportException The {@link ExportException} describing the exception. This is the same
* same instance as the {@linkplain ExportResult#transformationException exception} in * instance as the {@linkplain ExportResult#exportException exception} in {@code result}.
* {@code result}.
*/ */
@SuppressWarnings("deprecation") // Calling deprecated listener method. @SuppressWarnings("deprecation") // Calling deprecated listener method.
default void onError( 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; MediaItem mediaItem = composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
onTransformationError( 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.sequences.size() == 1);
checkArgument(composition.effects == Effects.EMPTY); checkArgument(composition.effects == Effects.EMPTY);
verifyApplicationThread(); verifyApplicationThread();
checkState(transformerInternal == null, "There is already a export in progress."); checkState(transformerInternal == null, "There is already an export in progress.");
TransformerInternalListener transformerInternalListener = TransformerInternalListener transformerInternalListener =
new TransformerInternalListener(composition); new TransformerInternalListener(composition);
@ -928,11 +929,11 @@ public final class Transformer {
} }
@Override @Override
public void onError(ExportResult exportResult, TransformationException exception) { public void onError(ExportResult exportResult, ExportException exportException) {
transformerInternal = null; transformerInternal = null;
listeners.queueEvent( listeners.queueEvent(
/* eventFlag= */ C.INDEX_UNSET, /* eventFlag= */ C.INDEX_UNSET,
listener -> listener.onError(composition, exportResult, exception)); listener -> listener.onError(composition, exportResult, exportException));
listeners.flushEvents(); listeners.flushEvents();
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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