Rename TransformationException to ExportException
PiperOrigin-RevId: 510062674
This commit is contained in:
parent
5410286955
commit
c2fdab847f
@ -79,9 +79,9 @@ import androidx.media3.transformer.DefaultEncoderFactory;
|
||||
import androidx.media3.transformer.DefaultMuxer;
|
||||
import androidx.media3.transformer.EditedMediaItem;
|
||||
import androidx.media3.transformer.Effects;
|
||||
import androidx.media3.transformer.ExportException;
|
||||
import androidx.media3.transformer.ExportResult;
|
||||
import androidx.media3.transformer.ProgressHolder;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.ui.AspectRatioFrameLayout;
|
||||
@ -311,15 +311,15 @@ public final class TransformerActivity extends AppCompatActivity {
|
||||
public void onCompleted(Composition composition, ExportResult exportResult) {
|
||||
MediaItem mediaItem =
|
||||
composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
|
||||
TransformerActivity.this.onTransformationCompleted(filePath, mediaItem);
|
||||
TransformerActivity.this.onCompleted(filePath, mediaItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(
|
||||
Composition composition,
|
||||
ExportResult exportResult,
|
||||
TransformationException exception) {
|
||||
TransformerActivity.this.onTransformationError(exception);
|
||||
ExportException exportException) {
|
||||
TransformerActivity.this.onError(exportException);
|
||||
}
|
||||
})
|
||||
.build();
|
||||
@ -602,16 +602,16 @@ public final class TransformerActivity extends AppCompatActivity {
|
||||
"debugFrame",
|
||||
"transformationStopwatch",
|
||||
})
|
||||
private void onTransformationError(TransformationException exception) {
|
||||
private void onError(ExportException exportException) {
|
||||
if (transformationStopwatch.isRunning()) {
|
||||
transformationStopwatch.stop();
|
||||
}
|
||||
informationTextView.setText(R.string.transformation_error);
|
||||
progressViewGroup.setVisibility(View.GONE);
|
||||
debugFrame.removeAllViews();
|
||||
Toast.makeText(getApplicationContext(), "Transformation error: " + exception, Toast.LENGTH_LONG)
|
||||
Toast.makeText(getApplicationContext(), "Export error: " + exportException, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
Log.e(TAG, "Transformation error", exception);
|
||||
Log.e(TAG, "Export error", exportException);
|
||||
}
|
||||
|
||||
@RequiresNonNull({
|
||||
@ -625,7 +625,7 @@ public final class TransformerActivity extends AppCompatActivity {
|
||||
"debugFrame",
|
||||
"transformationStopwatch",
|
||||
})
|
||||
private void onTransformationCompleted(String filePath, MediaItem inputMediaItem) {
|
||||
private void onCompleted(String filePath, MediaItem inputMediaItem) {
|
||||
transformationStopwatch.stop();
|
||||
informationTextView.setText(
|
||||
getString(
|
||||
|
@ -471,12 +471,12 @@ public final class AndroidTestUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForAudioEncoding(Format format) throws TransformationException {
|
||||
public Codec createForAudioEncoding(Format format) throws ExportException {
|
||||
return encoderFactory.createForAudioEncoding(format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForVideoEncoding(Format format) throws TransformationException {
|
||||
public Codec createForVideoEncoding(Format format) throws ExportException {
|
||||
return encoderFactory.createForVideoEncoding(format);
|
||||
}
|
||||
|
||||
@ -531,7 +531,7 @@ public final class AndroidTestUtil {
|
||||
/**
|
||||
* Creates a {@link JSONObject} from the {@link Exception}.
|
||||
*
|
||||
* <p>If the exception is a {@link TransformationException}, {@code errorCode} is included.
|
||||
* <p>If the exception is an {@link ExportException}, {@code errorCode} is included.
|
||||
*
|
||||
* @param exception The {@link Exception}.
|
||||
* @return The {@link JSONObject} containing the exception details, or {@code null} if the
|
||||
@ -546,8 +546,8 @@ public final class AndroidTestUtil {
|
||||
JSONObject exceptionJson = new JSONObject();
|
||||
exceptionJson.put("message", exception.getMessage());
|
||||
exceptionJson.put("type", exception.getClass());
|
||||
if (exception instanceof TransformationException) {
|
||||
exceptionJson.put("errorCode", ((TransformationException) exception).errorCode);
|
||||
if (exception instanceof ExportException) {
|
||||
exceptionJson.put("errorCode", ((ExportException) exception).errorCode);
|
||||
}
|
||||
exceptionJson.put("stackTrace", Log.getThrowableString(exception));
|
||||
return exceptionJson;
|
||||
|
@ -163,7 +163,7 @@ public class ExportTestResult {
|
||||
.putOpt("filePath", filePath)
|
||||
.putOpt("colorInfo", exportResult.colorInfo)
|
||||
.putOpt("videoEncoderName", exportResult.videoEncoderName)
|
||||
.putOpt("testException", exceptionAsJsonObject(exportResult.transformationException))
|
||||
.putOpt("testException", exceptionAsJsonObject(exportResult.exportException))
|
||||
.putOpt("analysisException", exceptionAsJsonObject(analysisException));
|
||||
|
||||
if (!exportResult.processedInputs.isEmpty()) {
|
||||
|
@ -189,8 +189,8 @@ public class TransformerAndroidTestRunner {
|
||||
try {
|
||||
ExportTestResult exportTestResult = runInternal(testId, editedMediaItem);
|
||||
resultJson.put("exportResult", exportTestResult.asJsonObject());
|
||||
if (exportTestResult.exportResult.transformationException != null) {
|
||||
throw exportTestResult.exportResult.transformationException;
|
||||
if (exportTestResult.exportResult.exportException != null) {
|
||||
throw exportTestResult.exportResult.exportException;
|
||||
}
|
||||
if (!suppressAnalysisExceptions && exportTestResult.analysisException != null) {
|
||||
throw exportTestResult.analysisException;
|
||||
@ -274,7 +274,7 @@ public class TransformerAndroidTestRunner {
|
||||
public void onError(
|
||||
Composition composition,
|
||||
ExportResult exportResult,
|
||||
TransformationException exception) {
|
||||
ExportException exportException) {
|
||||
exportResultReference.set(exportResult);
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
@ -330,7 +330,7 @@ public class TransformerAndroidTestRunner {
|
||||
@Nullable FallbackDetails fallbackDetails = fallbackDetailsReference.get();
|
||||
ExportResult exportResult = checkNotNull(exportResultReference.get());
|
||||
|
||||
if (exportResult.transformationException != null) {
|
||||
if (exportResult.exportException != null) {
|
||||
return new ExportTestResult.Builder(exportResult)
|
||||
.setElapsedTimeMs(elapsedTimeMs)
|
||||
.setFallbackDetails(fallbackDetails)
|
||||
|
@ -121,9 +121,9 @@ public class TransformerEndToEndTest {
|
||||
.setRemoveAudio(true)
|
||||
.build();
|
||||
|
||||
TransformationException exception =
|
||||
ExportException exception =
|
||||
assertThrows(
|
||||
TransformationException.class,
|
||||
ExportException.class,
|
||||
() ->
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
@ -132,8 +132,7 @@ public class TransformerEndToEndTest {
|
||||
editedMediaItem));
|
||||
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_ENCODER_INIT_FAILED);
|
||||
assertThat(exception.errorCode).isEqualTo(ExportException.ERROR_CODE_ENCODER_INIT_FAILED);
|
||||
assertThat(exception).hasMessageThat().contains("video");
|
||||
}
|
||||
|
||||
@ -146,15 +145,15 @@ public class TransformerEndToEndTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForAudioEncoding(Format format) throws TransformationException {
|
||||
public Codec createForAudioEncoding(Format format) throws ExportException {
|
||||
return encoderFactory.createForAudioEncoding(format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForVideoEncoding(Format format) throws TransformationException {
|
||||
throw TransformationException.createForCodec(
|
||||
public Codec createForVideoEncoding(Format format) throws ExportException {
|
||||
throw ExportException.createForCodec(
|
||||
new IllegalArgumentException(),
|
||||
TransformationException.ERROR_CODE_ENCODER_INIT_FAILED,
|
||||
ExportException.ERROR_CODE_ENCODER_INIT_FAILED,
|
||||
/* isVideo= */ true,
|
||||
/* isDecoder= */ false,
|
||||
format);
|
||||
|
@ -27,8 +27,8 @@ import androidx.media3.common.C;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.transformer.AndroidTestUtil;
|
||||
import androidx.media3.transformer.ExportException;
|
||||
import androidx.media3.transformer.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
@ -75,8 +75,8 @@ public class ForceInterpretHdrVideoAsSdrTest {
|
||||
.run(testId, mediaItem);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
Log.i(TAG, "Transformed.");
|
||||
} catch (TransformationException exception) {
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
} catch (ExportException exception) {
|
||||
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
@ -111,8 +111,8 @@ public class ForceInterpretHdrVideoAsSdrTest {
|
||||
.run(testId, mediaItem);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
Log.i(TAG, "Transformed.");
|
||||
} catch (TransformationException exception) {
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
} catch (ExportException exception) {
|
||||
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
@ -36,8 +36,8 @@ import androidx.media3.effect.ScaleToFitTransformation;
|
||||
import androidx.media3.transformer.EditedMediaItem;
|
||||
import androidx.media3.transformer.Effects;
|
||||
import androidx.media3.transformer.EncoderUtil;
|
||||
import androidx.media3.transformer.ExportException;
|
||||
import androidx.media3.transformer.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
@ -83,13 +83,13 @@ public class HdrEditingTest {
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Transformed.");
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_ST2084);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isAnyOf(
|
||||
TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
|
||||
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
|
||||
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,13 +108,13 @@ public class HdrEditingTest {
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Transformed.");
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_HLG);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isAnyOf(
|
||||
TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
|
||||
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
|
||||
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -213,11 +213,11 @@ public class HdrEditingTest {
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
assertThat(isFallbackListenerInvoked.get()).isFalse();
|
||||
}
|
||||
}
|
||||
@ -267,11 +267,11 @@ public class HdrEditingTest {
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
assertThat(isFallbackListenerInvoked.get()).isFalse();
|
||||
}
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ import androidx.media3.common.util.Log;
|
||||
import androidx.media3.effect.ScaleToFitTransformation;
|
||||
import androidx.media3.transformer.EditedMediaItem;
|
||||
import androidx.media3.transformer.Effects;
|
||||
import androidx.media3.transformer.ExportException;
|
||||
import androidx.media3.transformer.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
@ -84,11 +84,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,11 +126,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,11 +173,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
.run(testId, editedMediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,11 +220,11 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
.run(testId, editedMediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ import androidx.media3.common.util.GlUtil;
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.media3.common.util.Util;
|
||||
import androidx.media3.transformer.AndroidTestUtil;
|
||||
import androidx.media3.transformer.ExportException;
|
||||
import androidx.media3.transformer.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
@ -91,9 +91,9 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.e(TAG, "Error during transformation.", exception);
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
} catch (ExportException exception) {
|
||||
Log.e(TAG, "Error during export.", exception);
|
||||
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
@ -141,9 +141,9 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.e(TAG, "Error during transformation.", exception);
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
} catch (ExportException exception) {
|
||||
Log.e(TAG, "Error during export.", exception);
|
||||
if (exception.errorCode != ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
@ -97,20 +97,20 @@ public interface AssetLoader {
|
||||
* non-negative, in microseconds.
|
||||
* @return The {@link SampleConsumer} describing the type of sample data expected, and to which
|
||||
* to pass this data.
|
||||
* @throws TransformationException If an error occurs configuring the {@link SampleConsumer}.
|
||||
* @throws ExportException If an error occurs configuring the {@link SampleConsumer}.
|
||||
*/
|
||||
SampleConsumer onTrackAdded(
|
||||
Format format,
|
||||
@SupportedOutputTypes int supportedOutputTypes,
|
||||
long streamStartPositionUs,
|
||||
long streamOffsetUs)
|
||||
throws TransformationException;
|
||||
throws ExportException;
|
||||
|
||||
/**
|
||||
* Called if an error occurs in the asset loader. In this case, the asset loader will be
|
||||
* {@linkplain #release() released} automatically.
|
||||
*/
|
||||
void onError(TransformationException exception);
|
||||
void onError(ExportException exportException);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,7 +70,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
Codec.EncoderFactory encoderFactory,
|
||||
MuxerWrapper muxerWrapper,
|
||||
FallbackListener fallbackListener)
|
||||
throws TransformationException {
|
||||
throws ExportException {
|
||||
super(firstInputFormat, streamStartPositionUs, muxerWrapper);
|
||||
|
||||
if (generateSilentAudioDurationUs != C.TIME_UNSET) {
|
||||
@ -112,7 +112,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
try {
|
||||
encoderInputAudioFormat = audioProcessingPipeline.configure(pipelineInputAudioFormat);
|
||||
} catch (AudioProcessor.UnhandledAudioFormatException unhandledAudioFormatException) {
|
||||
throw TransformationException.createForAudioProcessing(
|
||||
throw ExportException.createForAudioProcessing(
|
||||
unhandledAudioFormatException, pipelineInputAudioFormat);
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean processDataUpToMuxer() throws TransformationException {
|
||||
protected boolean processDataUpToMuxer() throws ExportException {
|
||||
if (!audioProcessingPipeline.isOperational()) {
|
||||
return feedEncoderFromInput();
|
||||
}
|
||||
@ -185,13 +185,13 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected Format getMuxerInputFormat() throws TransformationException {
|
||||
protected Format getMuxerInputFormat() throws ExportException {
|
||||
return encoder.getOutputFormat();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected DecoderInputBuffer getMuxerInputBuffer() throws TransformationException {
|
||||
protected DecoderInputBuffer getMuxerInputBuffer() throws ExportException {
|
||||
encoderOutputBuffer.data = encoder.getOutputBuffer();
|
||||
if (encoderOutputBuffer.data == null) {
|
||||
return null;
|
||||
@ -202,7 +202,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseMuxerInputBuffer() throws TransformationException {
|
||||
protected void releaseMuxerInputBuffer() throws ExportException {
|
||||
encoder.releaseOutputBuffer(/* render= */ false);
|
||||
}
|
||||
|
||||
@ -216,7 +216,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
*
|
||||
* @return Whether it may be possible to feed more data immediately by calling this method again.
|
||||
*/
|
||||
private boolean feedEncoderFromInput() throws TransformationException {
|
||||
private boolean feedEncoderFromInput() throws ExportException {
|
||||
if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) {
|
||||
return false;
|
||||
}
|
||||
@ -254,7 +254,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
*
|
||||
* @return Whether it may be possible to feed more data immediately by calling this method again.
|
||||
*/
|
||||
private boolean feedEncoderFromProcessingPipeline() throws TransformationException {
|
||||
private boolean feedEncoderFromProcessingPipeline() throws ExportException {
|
||||
if (!encoder.maybeDequeueInputBuffer(encoderInputBuffer)) {
|
||||
return false;
|
||||
}
|
||||
@ -320,7 +320,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
* Feeds as much data as possible between the current position and limit of the specified {@link
|
||||
* ByteBuffer} to the encoder, and advances its position by the number of bytes fed.
|
||||
*/
|
||||
private void feedEncoder(ByteBuffer inputBuffer) throws TransformationException {
|
||||
private void feedEncoder(ByteBuffer inputBuffer) throws ExportException {
|
||||
ByteBuffer encoderInputBufferData = checkNotNull(encoderInputBuffer.data);
|
||||
int bufferLimit = inputBuffer.limit();
|
||||
inputBuffer.limit(min(bufferLimit, inputBuffer.position() + encoderInputBufferData.capacity()));
|
||||
@ -336,7 +336,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
encoder.queueInputBuffer(encoderInputBuffer);
|
||||
}
|
||||
|
||||
private void queueEndOfStreamToEncoder() throws TransformationException {
|
||||
private void queueEndOfStreamToEncoder() throws ExportException {
|
||||
checkState(checkNotNull(encoderInputBuffer.data).position() == 0);
|
||||
encoderInputBuffer.timeUs = nextEncoderInputBufferTimeUs;
|
||||
encoderInputBuffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
|
||||
|
@ -31,7 +31,7 @@ import androidx.media3.common.Format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForAudioDecoding(Format format) throws TransformationException {
|
||||
public Codec createForAudioDecoding(Format format) throws ExportException {
|
||||
Codec audioDecoder = decoderFactory.createForAudioDecoding(format);
|
||||
audioDecoderName = audioDecoder.getName();
|
||||
return audioDecoder;
|
||||
@ -39,8 +39,7 @@ import androidx.media3.common.Format;
|
||||
|
||||
@Override
|
||||
public Codec createForVideoDecoding(
|
||||
Format format, Surface outputSurface, boolean requestSdrToneMapping)
|
||||
throws TransformationException {
|
||||
Format format, Surface outputSurface, boolean requestSdrToneMapping) throws ExportException {
|
||||
Codec videoDecoder =
|
||||
decoderFactory.createForVideoDecoding(format, outputSurface, requestSdrToneMapping);
|
||||
videoDecoderName = videoDecoder.getName();
|
||||
|
@ -30,14 +30,14 @@ import androidx.media3.common.Format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForAudioEncoding(Format format) throws TransformationException {
|
||||
public Codec createForAudioEncoding(Format format) throws ExportException {
|
||||
Codec audioEncoder = encoderFactory.createForAudioEncoding(format);
|
||||
audioEncoderName = audioEncoder.getName();
|
||||
return audioEncoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForVideoEncoding(Format format) throws TransformationException {
|
||||
public Codec createForVideoEncoding(Format format) throws ExportException {
|
||||
Codec videoEncoder = encoderFactory.createForVideoEncoding(format);
|
||||
videoEncoderName = videoEncoder.getName();
|
||||
return videoEncoder;
|
||||
|
@ -42,9 +42,9 @@ public interface Codec {
|
||||
* @param format The {@link Format} (of the input data) used to determine the underlying decoder
|
||||
* and its configuration values.
|
||||
* @return A {@link Codec} for audio decoding.
|
||||
* @throws TransformationException If no suitable {@link Codec} can be created.
|
||||
* @throws ExportException If no suitable {@link Codec} can be created.
|
||||
*/
|
||||
Codec createForAudioDecoding(Format format) throws TransformationException;
|
||||
Codec createForAudioDecoding(Format format) throws ExportException;
|
||||
|
||||
/**
|
||||
* Returns a {@link Codec} for video decoding.
|
||||
@ -54,11 +54,10 @@ public interface Codec {
|
||||
* @param outputSurface The {@link Surface} to which the decoder output is rendered.
|
||||
* @param requestSdrToneMapping Whether to request tone-mapping to SDR.
|
||||
* @return A {@link Codec} for video decoding.
|
||||
* @throws TransformationException If no suitable {@link Codec} can be created.
|
||||
* @throws ExportException If no suitable {@link Codec} can be created.
|
||||
*/
|
||||
Codec createForVideoDecoding(
|
||||
Format format, Surface outputSurface, boolean requestSdrToneMapping)
|
||||
throws TransformationException;
|
||||
Format format, Surface outputSurface, boolean requestSdrToneMapping) throws ExportException;
|
||||
}
|
||||
|
||||
/** A factory for {@linkplain Codec encoder} instances. */
|
||||
@ -76,9 +75,9 @@ public interface Codec {
|
||||
* those of the desired output video format.
|
||||
* @return A {@link Codec} for encoding audio to the requested {@link Format#sampleMimeType MIME
|
||||
* type}.
|
||||
* @throws TransformationException If no suitable {@link Codec} can be created.
|
||||
* @throws ExportException If no suitable {@link Codec} can be created.
|
||||
*/
|
||||
Codec createForAudioEncoding(Format format) throws TransformationException;
|
||||
Codec createForAudioEncoding(Format format) throws ExportException;
|
||||
|
||||
/**
|
||||
* Returns a {@link Codec} for video encoding.
|
||||
@ -96,9 +95,9 @@ public interface Codec {
|
||||
* Format#height}, therefore the video is always in landscape orientation.
|
||||
* @return A {@link Codec} for encoding video to the requested {@linkplain Format#sampleMimeType
|
||||
* MIME type}.
|
||||
* @throws TransformationException If no suitable {@link Codec} can be created.
|
||||
* @throws ExportException If no suitable {@link Codec} can be created.
|
||||
*/
|
||||
Codec createForVideoEncoding(Format format) throws TransformationException;
|
||||
Codec createForVideoEncoding(Format format) throws ExportException;
|
||||
|
||||
/** Returns whether the audio needs to be encoded because of encoder specific configuration. */
|
||||
default boolean audioNeedsEncoding() {
|
||||
@ -148,9 +147,9 @@ public interface Codec {
|
||||
* @param inputBuffer The buffer where the dequeued buffer data is stored, at {@link
|
||||
* DecoderInputBuffer#data inputBuffer.data}.
|
||||
* @return Whether an input buffer is ready to be used.
|
||||
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
|
||||
* @throws ExportException If the underlying decoder or encoder encounters a problem.
|
||||
*/
|
||||
boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) throws TransformationException;
|
||||
boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException;
|
||||
|
||||
/**
|
||||
* Queues an input buffer to the {@code Codec}. No buffers may be queued after {@linkplain
|
||||
@ -160,9 +159,9 @@ public interface Codec {
|
||||
* to receive input.
|
||||
*
|
||||
* @param inputBuffer The {@linkplain DecoderInputBuffer input buffer}.
|
||||
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
|
||||
* @throws ExportException If the underlying decoder or encoder encounters a problem.
|
||||
*/
|
||||
void queueInputBuffer(DecoderInputBuffer inputBuffer) throws TransformationException;
|
||||
void queueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException;
|
||||
|
||||
/**
|
||||
* Signals end-of-stream on input to a video encoder.
|
||||
@ -172,17 +171,17 @@ public interface Codec {
|
||||
* should be set on the last input buffer {@linkplain #queueInputBuffer(DecoderInputBuffer)
|
||||
* queued}.
|
||||
*
|
||||
* @throws TransformationException If the underlying video encoder encounters a problem.
|
||||
* @throws ExportException If the underlying video encoder encounters a problem.
|
||||
*/
|
||||
void signalEndOfInputStream() throws TransformationException;
|
||||
void signalEndOfInputStream() throws ExportException;
|
||||
|
||||
/**
|
||||
* Returns the current output format, or {@code null} if unavailable.
|
||||
*
|
||||
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
|
||||
* @throws ExportException If the underlying decoder or encoder encounters a problem.
|
||||
*/
|
||||
@Nullable
|
||||
Format getOutputFormat() throws TransformationException;
|
||||
Format getOutputFormat() throws ExportException;
|
||||
|
||||
/**
|
||||
* Returns the current output {@link ByteBuffer}, or {@code null} if unavailable.
|
||||
@ -190,10 +189,10 @@ public interface Codec {
|
||||
* <p>This method must not be called on video decoders because they must output to a {@link
|
||||
* Surface}.
|
||||
*
|
||||
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
|
||||
* @throws ExportException If the underlying decoder or encoder encounters a problem.
|
||||
*/
|
||||
@Nullable
|
||||
ByteBuffer getOutputBuffer() throws TransformationException;
|
||||
ByteBuffer getOutputBuffer() throws ExportException;
|
||||
|
||||
/**
|
||||
* Returns the {@link BufferInfo} associated with the current output buffer, or {@code null} if
|
||||
@ -201,10 +200,10 @@ public interface Codec {
|
||||
*
|
||||
* <p>This method returns {@code null} if and only if {@link #getOutputBuffer()} returns null.
|
||||
*
|
||||
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
|
||||
* @throws ExportException If the underlying decoder or encoder encounters a problem.
|
||||
*/
|
||||
@Nullable
|
||||
BufferInfo getOutputBufferInfo() throws TransformationException;
|
||||
BufferInfo getOutputBufferInfo() throws ExportException;
|
||||
|
||||
/**
|
||||
* Releases the current output buffer.
|
||||
@ -218,9 +217,9 @@ public interface Codec {
|
||||
* be available until the current output buffer has been released.
|
||||
*
|
||||
* @param render Whether the buffer needs to be rendered to the output {@link Surface}.
|
||||
* @throws TransformationException If the underlying decoder or encoder encounters a problem.
|
||||
* @throws ExportException If the underlying decoder or encoder encounters a problem.
|
||||
*/
|
||||
void releaseOutputBuffer(boolean render) throws TransformationException;
|
||||
void releaseOutputBuffer(boolean render) throws ExportException;
|
||||
|
||||
/**
|
||||
* Returns whether the {@code Codec}'s output stream has ended, and no more data can be dequeued.
|
||||
|
@ -173,7 +173,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
@SupportedOutputTypes int supportedOutputTypes,
|
||||
long streamStartPositionUs,
|
||||
long streamOffsetUs)
|
||||
throws TransformationException {
|
||||
throws ExportException {
|
||||
int trackType = MimeTypes.getTrackType(format.sampleMimeType);
|
||||
SampleConsumer sampleConsumer;
|
||||
if (currentMediaItemIndex.get() == 0) {
|
||||
@ -201,8 +201,8 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(TransformationException exception) {
|
||||
compositeAssetLoaderListener.onError(exception);
|
||||
public void onError(ExportException exportException) {
|
||||
compositeAssetLoaderListener.onError(exportException);
|
||||
}
|
||||
|
||||
private void addCurrentProcessedInput() {
|
||||
|
@ -98,7 +98,7 @@ public final class DefaultCodec implements Codec {
|
||||
String mediaCodecName,
|
||||
boolean isDecoder,
|
||||
@Nullable Surface outputSurface)
|
||||
throws TransformationException {
|
||||
throws ExportException {
|
||||
this.configurationFormat = configurationFormat;
|
||||
this.configurationMediaFormat = configurationMediaFormat;
|
||||
this.isDecoder = isDecoder;
|
||||
@ -135,21 +135,21 @@ public final class DefaultCodec implements Codec {
|
||||
mediaCodec.release();
|
||||
}
|
||||
|
||||
@TransformationException.ErrorCode int errorCode;
|
||||
@ExportException.ErrorCode int errorCode;
|
||||
if (e instanceof IOException || e instanceof MediaCodec.CodecException) {
|
||||
errorCode =
|
||||
isDecoder
|
||||
? TransformationException.ERROR_CODE_DECODER_INIT_FAILED
|
||||
: TransformationException.ERROR_CODE_ENCODER_INIT_FAILED;
|
||||
? ExportException.ERROR_CODE_DECODER_INIT_FAILED
|
||||
: ExportException.ERROR_CODE_ENCODER_INIT_FAILED;
|
||||
} else if (e instanceof IllegalArgumentException) {
|
||||
errorCode =
|
||||
isDecoder
|
||||
? TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
|
||||
: TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
|
||||
? ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
|
||||
: ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
|
||||
} else {
|
||||
errorCode = TransformationException.ERROR_CODE_FAILED_RUNTIME_CHECK;
|
||||
errorCode = ExportException.ERROR_CODE_FAILED_RUNTIME_CHECK;
|
||||
}
|
||||
throw createTransformationException(e, errorCode, mediaCodecName);
|
||||
throw createExportException(e, errorCode, mediaCodecName);
|
||||
}
|
||||
this.mediaCodec = mediaCodec;
|
||||
this.inputSurface = inputSurface;
|
||||
@ -175,8 +175,7 @@ public final class DefaultCodec implements Codec {
|
||||
|
||||
@Override
|
||||
@EnsuresNonNullIf(expression = "#1.data", result = true)
|
||||
public boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer)
|
||||
throws TransformationException {
|
||||
public boolean maybeDequeueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException {
|
||||
if (inputStreamEnded) {
|
||||
return false;
|
||||
}
|
||||
@ -184,7 +183,7 @@ public final class DefaultCodec implements Codec {
|
||||
try {
|
||||
inputBufferIndex = mediaCodec.dequeueInputBuffer(/* timeoutUs= */ 0);
|
||||
} catch (RuntimeException e) {
|
||||
throw createTransformationException(e);
|
||||
throw createExportException(e);
|
||||
}
|
||||
if (inputBufferIndex < 0) {
|
||||
return false;
|
||||
@ -192,7 +191,7 @@ public final class DefaultCodec implements Codec {
|
||||
try {
|
||||
inputBuffer.data = mediaCodec.getInputBuffer(inputBufferIndex);
|
||||
} catch (RuntimeException e) {
|
||||
throw createTransformationException(e);
|
||||
throw createExportException(e);
|
||||
}
|
||||
inputBuffer.clear();
|
||||
}
|
||||
@ -201,7 +200,7 @@ public final class DefaultCodec implements Codec {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueInputBuffer(DecoderInputBuffer inputBuffer) throws TransformationException {
|
||||
public void queueInputBuffer(DecoderInputBuffer inputBuffer) throws ExportException {
|
||||
checkState(
|
||||
!inputStreamEnded, "Input buffer can not be queued after the input stream has ended.");
|
||||
|
||||
@ -219,24 +218,24 @@ public final class DefaultCodec implements Codec {
|
||||
try {
|
||||
mediaCodec.queueInputBuffer(inputBufferIndex, offset, size, inputBuffer.timeUs, flags);
|
||||
} catch (RuntimeException e) {
|
||||
throw createTransformationException(e);
|
||||
throw createExportException(e);
|
||||
}
|
||||
inputBufferIndex = C.INDEX_UNSET;
|
||||
inputBuffer.data = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void signalEndOfInputStream() throws TransformationException {
|
||||
public void signalEndOfInputStream() throws ExportException {
|
||||
try {
|
||||
mediaCodec.signalEndOfInputStream();
|
||||
} catch (RuntimeException e) {
|
||||
throw createTransformationException(e);
|
||||
throw createExportException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Format getOutputFormat() throws TransformationException {
|
||||
public Format getOutputFormat() throws ExportException {
|
||||
// The format is updated when dequeueing a 'special' buffer index, so attempt to dequeue now.
|
||||
maybeDequeueOutputBuffer(/* setOutputBuffer= */ false);
|
||||
return outputFormat;
|
||||
@ -244,18 +243,18 @@ public final class DefaultCodec implements Codec {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ByteBuffer getOutputBuffer() throws TransformationException {
|
||||
public ByteBuffer getOutputBuffer() throws ExportException {
|
||||
return maybeDequeueOutputBuffer(/* setOutputBuffer= */ true) ? outputBuffer : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public BufferInfo getOutputBufferInfo() throws TransformationException {
|
||||
public BufferInfo getOutputBufferInfo() throws ExportException {
|
||||
return maybeDequeueOutputBuffer(/* setOutputBuffer= */ false) ? outputBufferInfo : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void releaseOutputBuffer(boolean render) throws TransformationException {
|
||||
public void releaseOutputBuffer(boolean render) throws ExportException {
|
||||
outputBuffer = null;
|
||||
try {
|
||||
if (render) {
|
||||
@ -266,7 +265,7 @@ public final class DefaultCodec implements Codec {
|
||||
mediaCodec.releaseOutputBuffer(outputBufferIndex, /* render= */ false);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
throw createTransformationException(e);
|
||||
throw createExportException(e);
|
||||
}
|
||||
outputBufferIndex = C.INDEX_UNSET;
|
||||
}
|
||||
@ -310,9 +309,9 @@ public final class DefaultCodec implements Codec {
|
||||
* @param setOutputBuffer Whether to read the bytes of the dequeued output buffer and copy them
|
||||
* into {@link #outputBuffer}.
|
||||
* @return Whether there is an output buffer available.
|
||||
* @throws TransformationException If the underlying {@link MediaCodec} encounters a problem.
|
||||
* @throws ExportException If the underlying {@link MediaCodec} encounters a problem.
|
||||
*/
|
||||
private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) throws TransformationException {
|
||||
private boolean maybeDequeueOutputBuffer(boolean setOutputBuffer) throws ExportException {
|
||||
if (outputBufferIndex >= 0) {
|
||||
return true;
|
||||
}
|
||||
@ -323,7 +322,7 @@ public final class DefaultCodec implements Codec {
|
||||
try {
|
||||
outputBufferIndex = mediaCodec.dequeueOutputBuffer(outputBufferInfo, /* timeoutUs= */ 0);
|
||||
} catch (RuntimeException e) {
|
||||
throw createTransformationException(e);
|
||||
throw createExportException(e);
|
||||
}
|
||||
if (outputBufferIndex < 0) {
|
||||
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
|
||||
@ -363,7 +362,7 @@ public final class DefaultCodec implements Codec {
|
||||
try {
|
||||
outputBuffer = checkNotNull(mediaCodec.getOutputBuffer(outputBufferIndex));
|
||||
} catch (RuntimeException e) {
|
||||
throw createTransformationException(e);
|
||||
throw createExportException(e);
|
||||
}
|
||||
outputBuffer.position(outputBufferInfo.offset);
|
||||
outputBuffer.limit(outputBufferInfo.offset + outputBufferInfo.size);
|
||||
@ -371,25 +370,24 @@ public final class DefaultCodec implements Codec {
|
||||
return true;
|
||||
}
|
||||
|
||||
private TransformationException createTransformationException(Exception cause) {
|
||||
return createTransformationException(
|
||||
private ExportException createExportException(Exception cause) {
|
||||
return createExportException(
|
||||
cause,
|
||||
isDecoder
|
||||
? TransformationException.ERROR_CODE_DECODING_FAILED
|
||||
: TransformationException.ERROR_CODE_ENCODING_FAILED,
|
||||
? ExportException.ERROR_CODE_DECODING_FAILED
|
||||
: ExportException.ERROR_CODE_ENCODING_FAILED,
|
||||
getName());
|
||||
}
|
||||
|
||||
/** Creates a {@link TransformationException} with specific {@link MediaCodec} details. */
|
||||
private TransformationException createTransformationException(
|
||||
/** Creates an {@link ExportException} with specific {@link MediaCodec} details. */
|
||||
private ExportException createExportException(
|
||||
@UnknownInitialization DefaultCodec this,
|
||||
Exception cause,
|
||||
@TransformationException.ErrorCode int errorCode,
|
||||
@ExportException.ErrorCode int errorCode,
|
||||
String mediaCodecName) {
|
||||
String codecDetails =
|
||||
"mediaFormat=" + configurationMediaFormat + ", mediaCodecName=" + mediaCodecName;
|
||||
return TransformationException.createForCodec(
|
||||
cause, errorCode, isVideo, isDecoder, codecDetails);
|
||||
return ExportException.createForCodec(cause, errorCode, isVideo, isDecoder, codecDetails);
|
||||
}
|
||||
|
||||
private static boolean areColorTransfersEqual(
|
||||
|
@ -51,14 +51,14 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Codec createForAudioDecoding(Format format) throws TransformationException {
|
||||
public Codec createForAudioDecoding(Format format) throws ExportException {
|
||||
checkNotNull(format.sampleMimeType);
|
||||
MediaFormat mediaFormat = createMediaFormatFromFormat(format);
|
||||
|
||||
@Nullable
|
||||
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
|
||||
if (mediaCodecName == null) {
|
||||
throw createTransformationException(
|
||||
throw createExportException(
|
||||
format, /* reason= */ "The requested decoding format is not supported.");
|
||||
}
|
||||
return new DefaultCodec(
|
||||
@ -73,18 +73,17 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
@SuppressLint("InlinedApi")
|
||||
@Override
|
||||
public Codec createForVideoDecoding(
|
||||
Format format, Surface outputSurface, boolean requestSdrToneMapping)
|
||||
throws TransformationException {
|
||||
Format format, Surface outputSurface, boolean requestSdrToneMapping) throws ExportException {
|
||||
checkNotNull(format.sampleMimeType);
|
||||
|
||||
if (ColorInfo.isTransferHdr(format.colorInfo)) {
|
||||
if (requestSdrToneMapping && (SDK_INT < 31 || deviceNeedsNoToneMappingWorkaround())) {
|
||||
throw createTransformationException(
|
||||
throw createExportException(
|
||||
format, /* reason= */ "Tone-mapping HDR is not supported on this device.");
|
||||
}
|
||||
if (SDK_INT < 29) {
|
||||
// TODO(b/266837571, b/267171669): Remove API version restriction after fixing linked bugs.
|
||||
throw createTransformationException(
|
||||
throw createExportException(
|
||||
format, /* reason= */ "Decoding HDR is not supported on this device.");
|
||||
}
|
||||
}
|
||||
@ -111,7 +110,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
@Nullable
|
||||
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
|
||||
if (mediaCodecName == null) {
|
||||
throw createTransformationException(
|
||||
throw createExportException(
|
||||
format, /* reason= */ "The requested video decoding format is not supported.");
|
||||
}
|
||||
return new DefaultCodec(
|
||||
@ -127,11 +126,10 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
}
|
||||
|
||||
@RequiresNonNull("#1.sampleMimeType")
|
||||
private static TransformationException createTransformationException(
|
||||
Format format, String reason) {
|
||||
return TransformationException.createForCodec(
|
||||
private static ExportException createExportException(Format format, String reason) {
|
||||
return ExportException.createForCodec(
|
||||
new IllegalArgumentException(reason),
|
||||
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
|
||||
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
|
||||
MimeTypes.isVideo(format.sampleMimeType),
|
||||
/* isDecoder= */ true,
|
||||
format);
|
||||
|
@ -173,14 +173,14 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultCodec createForAudioEncoding(Format format) throws TransformationException {
|
||||
public DefaultCodec createForAudioEncoding(Format format) throws ExportException {
|
||||
checkNotNull(format.sampleMimeType);
|
||||
MediaFormat mediaFormat = createMediaFormatFromFormat(format);
|
||||
|
||||
@Nullable
|
||||
String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ false);
|
||||
if (mediaCodecName == null) {
|
||||
throw createTransformationException(
|
||||
throw createExportException(
|
||||
format, /* errorString= */ "The requested audio encoding format is not supported.");
|
||||
}
|
||||
return new DefaultCodec(
|
||||
@ -201,7 +201,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
||||
* VideoEncoderSettings#enableHighQualityTargeting} is set.
|
||||
*/
|
||||
@Override
|
||||
public DefaultCodec createForVideoEncoding(Format format) throws TransformationException {
|
||||
public DefaultCodec createForVideoEncoding(Format format) throws ExportException {
|
||||
if (format.frameRate == Format.NO_VALUE) {
|
||||
format = format.buildUpon().setFrameRate(DEFAULT_FRAME_RATE).build();
|
||||
}
|
||||
@ -220,7 +220,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
||||
format, requestedVideoEncoderSettings, videoEncoderSelector, enableFallback);
|
||||
|
||||
if (encoderAndClosestFormatSupport == null) {
|
||||
throw createTransformationException(
|
||||
throw createExportException(
|
||||
format, /* errorString= */ "The requested video encoding format is not supported.");
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
||||
MediaFormat.KEY_COLOR_FORMAT,
|
||||
MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010);
|
||||
} else {
|
||||
throw createTransformationException(
|
||||
throw createExportException(
|
||||
format, /* errorString= */ "Encoding HDR is not supported on this device.");
|
||||
}
|
||||
} else {
|
||||
@ -664,11 +664,10 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
||||
}
|
||||
|
||||
@RequiresNonNull("#1.sampleMimeType")
|
||||
private static TransformationException createTransformationException(
|
||||
Format format, String errorString) {
|
||||
return TransformationException.createForCodec(
|
||||
private static ExportException createExportException(Format format, String errorString) {
|
||||
return ExportException.createForCodec(
|
||||
new IllegalArgumentException(errorString),
|
||||
TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
|
||||
ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
|
||||
MimeTypes.isVideo(format.sampleMimeType),
|
||||
/* isDecoder= */ false,
|
||||
format);
|
||||
|
@ -45,7 +45,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initDecoder(Format inputFormat) throws TransformationException {
|
||||
protected void initDecoder(Format inputFormat) throws ExportException {
|
||||
decoder = decoderFactory.createForAudioDecoding(inputFormat);
|
||||
}
|
||||
|
||||
@ -53,11 +53,11 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
* Attempts to get decoded audio data and pass it to the sample consumer.
|
||||
*
|
||||
* @return Whether it may be possible to read more data immediately by calling this method again.
|
||||
* @throws TransformationException If an error occurs in the decoder.
|
||||
* @throws ExportException If an error occurs in the decoder.
|
||||
*/
|
||||
@Override
|
||||
@RequiresNonNull("sampleConsumer")
|
||||
protected boolean feedConsumerFromDecoder() throws TransformationException {
|
||||
protected boolean feedConsumerFromDecoder() throws ExportException {
|
||||
@Nullable DecoderInputBuffer sampleConsumerInputBuffer = sampleConsumer.getInputBuffer();
|
||||
if (sampleConsumerInputBuffer == null) {
|
||||
return false;
|
||||
|
@ -101,7 +101,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
} else {
|
||||
while (feedConsumerFromInput()) {}
|
||||
}
|
||||
} catch (TransformationException e) {
|
||||
} catch (ExportException e) {
|
||||
isTransformationRunning = false;
|
||||
assetLoaderListener.onError(e);
|
||||
}
|
||||
@ -140,7 +140,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
/** Initializes {@link #decoder} with an appropriate {@linkplain Codec decoder}. */
|
||||
@RequiresNonNull("sampleConsumer")
|
||||
protected abstract void initDecoder(Format inputFormat) throws TransformationException;
|
||||
protected abstract void initDecoder(Format inputFormat) throws ExportException;
|
||||
|
||||
/**
|
||||
* Preprocesses an encoded {@linkplain DecoderInputBuffer input buffer} and returns whether it
|
||||
@ -159,13 +159,13 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
* Attempts to get decoded data and pass it to the sample consumer.
|
||||
*
|
||||
* @return Whether it may be possible to read more data immediately by calling this method again.
|
||||
* @throws TransformationException If an error occurs in the decoder.
|
||||
* @throws ExportException If an error occurs in the decoder.
|
||||
*/
|
||||
@RequiresNonNull("sampleConsumer")
|
||||
protected abstract boolean feedConsumerFromDecoder() throws TransformationException;
|
||||
protected abstract boolean feedConsumerFromDecoder() throws ExportException;
|
||||
|
||||
@EnsuresNonNullIf(expression = "sampleConsumer", result = true)
|
||||
private boolean ensureConfigured() throws TransformationException {
|
||||
private boolean ensureConfigured() throws ExportException {
|
||||
if (sampleConsumer != null) {
|
||||
return true;
|
||||
}
|
||||
@ -193,9 +193,9 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
* Attempts to read input data and pass it to the decoder.
|
||||
*
|
||||
* @return Whether it may be possible to read more data immediately by calling this method again.
|
||||
* @throws TransformationException If an error occurs in the decoder.
|
||||
* @throws ExportException If an error occurs in the decoder.
|
||||
*/
|
||||
private boolean feedDecoderFromInput() throws TransformationException {
|
||||
private boolean feedDecoderFromInput() throws ExportException {
|
||||
Codec decoder = checkNotNull(this.decoder);
|
||||
if (!decoder.maybeDequeueInputBuffer(decoderInputBuffer)) {
|
||||
return false;
|
||||
|
@ -65,7 +65,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
@Override
|
||||
@RequiresNonNull("sampleConsumer")
|
||||
protected void initDecoder(Format inputFormat) throws TransformationException {
|
||||
protected void initDecoder(Format inputFormat) throws ExportException {
|
||||
boolean isDecoderToneMappingRequired =
|
||||
ColorInfo.isTransferHdr(inputFormat.colorInfo)
|
||||
&& !ColorInfo.isTransferHdr(sampleConsumer.getExpectedInputColorInfo());
|
||||
@ -106,7 +106,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
@Override
|
||||
@RequiresNonNull("sampleConsumer")
|
||||
protected boolean feedConsumerFromDecoder() throws TransformationException {
|
||||
protected boolean feedConsumerFromDecoder() throws ExportException {
|
||||
Codec decoder = checkNotNull(this.decoder);
|
||||
if (decoder.isEnded()) {
|
||||
sampleConsumer.signalEndOfVideoInput();
|
||||
|
@ -21,8 +21,8 @@ import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_BUFFER_FOR_PL
|
||||
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS;
|
||||
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_MAX_BUFFER_MS;
|
||||
import static androidx.media3.exoplayer.DefaultLoadControl.DEFAULT_MIN_BUFFER_MS;
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_FAILED_RUNTIME_CHECK;
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_FAILED_RUNTIME_CHECK;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_UNAVAILABLE;
|
||||
@ -309,7 +309,7 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
|
||||
player.play();
|
||||
} else {
|
||||
assetLoaderListener.onError(
|
||||
TransformationException.createForAssetLoader(
|
||||
ExportException.createForAssetLoader(
|
||||
new IllegalStateException("The asset loader has no track to output."),
|
||||
ERROR_CODE_FAILED_RUNTIME_CHECK));
|
||||
}
|
||||
@ -317,12 +317,12 @@ public final class ExoPlayerAssetLoader implements AssetLoader {
|
||||
|
||||
@Override
|
||||
public void onPlayerError(PlaybackException error) {
|
||||
@TransformationException.ErrorCode
|
||||
@ExportException.ErrorCode
|
||||
int errorCode =
|
||||
checkNotNull(
|
||||
TransformationException.NAME_TO_ERROR_CODE.getOrDefault(
|
||||
ExportException.NAME_TO_ERROR_CODE.getOrDefault(
|
||||
error.getErrorCodeName(), ERROR_CODE_UNSPECIFIED));
|
||||
assetLoaderListener.onError(TransformationException.createForAssetLoader(error, errorCode));
|
||||
assetLoaderListener.onError(ExportException.createForAssetLoader(error, errorCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -47,7 +47,7 @@ public final class ExportResult {
|
||||
private int width;
|
||||
private int videoFrameCount;
|
||||
@Nullable private String videoEncoderName;
|
||||
@Nullable private TransformationException transformationException;
|
||||
@Nullable private ExportException exportException;
|
||||
|
||||
/** Creates a builder. */
|
||||
public Builder() {
|
||||
@ -206,11 +206,10 @@ public final class ExportResult {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the {@link TransformationException} that caused the export to fail. */
|
||||
/** Sets the {@link ExportException} that caused the export to fail. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setTransformationException(
|
||||
@Nullable TransformationException transformationException) {
|
||||
this.transformationException = transformationException;
|
||||
public Builder setExportException(@Nullable ExportException exportException) {
|
||||
this.exportException = exportException;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -231,7 +230,7 @@ public final class ExportResult {
|
||||
width,
|
||||
videoFrameCount,
|
||||
videoEncoderName,
|
||||
transformationException);
|
||||
exportException);
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,10 +295,10 @@ public final class ExportResult {
|
||||
@Nullable public final String videoEncoderName;
|
||||
|
||||
/**
|
||||
* The {@link TransformationException} that caused the export to fail, or {@code null} if the
|
||||
* export was a success.
|
||||
* The {@link ExportException} that caused the export to fail, or {@code null} if the export was a
|
||||
* success.
|
||||
*/
|
||||
@Nullable public final TransformationException transformationException;
|
||||
@Nullable public final ExportException exportException;
|
||||
|
||||
private ExportResult(
|
||||
ImmutableList<ProcessedInput> processedInputs,
|
||||
@ -316,7 +315,7 @@ public final class ExportResult {
|
||||
int width,
|
||||
int videoFrameCount,
|
||||
@Nullable String videoEncoderName,
|
||||
@Nullable TransformationException transformationException) {
|
||||
@Nullable ExportException exportException) {
|
||||
this.processedInputs = processedInputs;
|
||||
this.durationMs = durationMs;
|
||||
this.fileSizeBytes = fileSizeBytes;
|
||||
@ -331,7 +330,7 @@ public final class ExportResult {
|
||||
this.width = width;
|
||||
this.videoFrameCount = videoFrameCount;
|
||||
this.videoEncoderName = videoEncoderName;
|
||||
this.transformationException = transformationException;
|
||||
this.exportException = exportException;
|
||||
}
|
||||
|
||||
public Builder buildUpon() {
|
||||
@ -350,7 +349,7 @@ public final class ExportResult {
|
||||
.setWidth(width)
|
||||
.setVideoFrameCount(videoFrameCount)
|
||||
.setVideoEncoderName(videoEncoderName)
|
||||
.setTransformationException(transformationException);
|
||||
.setExportException(exportException);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -376,7 +375,7 @@ public final class ExportResult {
|
||||
&& width == result.width
|
||||
&& videoFrameCount == result.videoFrameCount
|
||||
&& Objects.equals(videoEncoderName, result.videoEncoderName)
|
||||
&& Objects.equals(transformationException, result.transformationException);
|
||||
&& Objects.equals(exportException, result.exportException);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -395,7 +394,7 @@ public final class ExportResult {
|
||||
result = 31 * result + width;
|
||||
result = 31 * result + videoFrameCount;
|
||||
result = 31 * result + Objects.hashCode(videoEncoderName);
|
||||
result = 31 * result + Objects.hashCode(transformationException);
|
||||
result = 31 * result + Objects.hashCode(exportException);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -18,8 +18,8 @@ package androidx.media3.transformer;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_IO_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_IO_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_UNSPECIFIED;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_AVAILABLE;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
|
||||
|
||||
@ -101,19 +101,17 @@ public final class ImageAssetLoader implements AssetLoader {
|
||||
sampleConsumer.queueInputBitmap(
|
||||
bitmap, editedMediaItem.durationUs, editedMediaItem.frameRate);
|
||||
sampleConsumer.signalEndOfVideoInput();
|
||||
} catch (TransformationException e) {
|
||||
} catch (ExportException e) {
|
||||
listener.onError(e);
|
||||
} catch (RuntimeException e) {
|
||||
listener.onError(
|
||||
TransformationException.createForAssetLoader(e, ERROR_CODE_UNSPECIFIED));
|
||||
listener.onError(ExportException.createForAssetLoader(e, ERROR_CODE_UNSPECIFIED));
|
||||
}
|
||||
progress = 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable t) {
|
||||
listener.onError(
|
||||
TransformationException.createForAssetLoader(t, ERROR_CODE_IO_UNSPECIFIED));
|
||||
listener.onError(ExportException.createForAssetLoader(t, ERROR_CODE_IO_UNSPECIFIED));
|
||||
}
|
||||
},
|
||||
MoreExecutors.directExecutor());
|
||||
|
@ -53,7 +53,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
|
||||
void onEnded(long durationMs, long fileSizeBytes);
|
||||
|
||||
void onError(TransformationException transformationException);
|
||||
void onError(ExportException exportException);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -277,12 +277,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
|
||||
}
|
||||
isAborted = true;
|
||||
listener.onError(
|
||||
TransformationException.createForMuxer(
|
||||
ExportException.createForMuxer(
|
||||
new IllegalStateException(
|
||||
"No output sample written in the last "
|
||||
+ maxDelayBetweenSamplesMs
|
||||
+ " milliseconds. Aborting transformation."),
|
||||
TransformationException.ERROR_CODE_MUXING_FAILED));
|
||||
ExportException.ERROR_CODE_MUXING_FAILED));
|
||||
},
|
||||
maxDelayBetweenSamplesMs,
|
||||
MILLISECONDS);
|
||||
|
@ -64,24 +64,24 @@ import java.util.List;
|
||||
* Processes the input data and returns whether it may be possible to process more data by calling
|
||||
* this method again.
|
||||
*/
|
||||
public final boolean processData() throws TransformationException {
|
||||
public final boolean processData() throws ExportException {
|
||||
return feedMuxer() || processDataUpToMuxer();
|
||||
}
|
||||
|
||||
/** Releases all resources held by the pipeline. */
|
||||
public abstract void release();
|
||||
|
||||
protected boolean processDataUpToMuxer() throws TransformationException {
|
||||
protected boolean processDataUpToMuxer() throws ExportException {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract Format getMuxerInputFormat() throws TransformationException;
|
||||
protected abstract Format getMuxerInputFormat() throws ExportException;
|
||||
|
||||
@Nullable
|
||||
protected abstract DecoderInputBuffer getMuxerInputBuffer() throws TransformationException;
|
||||
protected abstract DecoderInputBuffer getMuxerInputBuffer() throws ExportException;
|
||||
|
||||
protected abstract void releaseMuxerInputBuffer() throws TransformationException;
|
||||
protected abstract void releaseMuxerInputBuffer() throws ExportException;
|
||||
|
||||
protected abstract boolean isMuxerInputEnded();
|
||||
|
||||
@ -89,7 +89,7 @@ import java.util.List;
|
||||
* Attempts to pass encoded data to the muxer, and returns whether it may be possible to pass more
|
||||
* data immediately by calling this method again.
|
||||
*/
|
||||
private boolean feedMuxer() throws TransformationException {
|
||||
private boolean feedMuxer() throws ExportException {
|
||||
if (!muxerWrapperTrackAdded) {
|
||||
@Nullable Format inputFormat = getMuxerInputFormat();
|
||||
if (inputFormat == null) {
|
||||
@ -98,8 +98,7 @@ import java.util.List;
|
||||
try {
|
||||
muxerWrapper.addTrackFormat(inputFormat);
|
||||
} catch (Muxer.MuxerException e) {
|
||||
throw TransformationException.createForMuxer(
|
||||
e, TransformationException.ERROR_CODE_MUXING_FAILED);
|
||||
throw ExportException.createForMuxer(e, ExportException.ERROR_CODE_MUXING_FAILED);
|
||||
}
|
||||
muxerWrapperTrackAdded = true;
|
||||
}
|
||||
@ -126,8 +125,7 @@ import java.util.List;
|
||||
return false;
|
||||
}
|
||||
} catch (Muxer.MuxerException e) {
|
||||
throw TransformationException.createForMuxer(
|
||||
e, TransformationException.ERROR_CODE_MUXING_FAILED);
|
||||
throw ExportException.createForMuxer(e, ExportException.ERROR_CODE_MUXING_FAILED);
|
||||
}
|
||||
|
||||
releaseMuxerInputBuffer();
|
||||
@ -152,10 +150,10 @@ import java.util.List;
|
||||
* @param muxerSupportedMimeTypes The list of sample {@linkplain MimeTypes MIME types} that the
|
||||
* muxer supports.
|
||||
* @return A supported {@linkplain MimeTypes MIME type}.
|
||||
* @throws TransformationException If there are no supported {@linkplain MimeTypes MIME types}.
|
||||
* @throws ExportException If there are no supported {@linkplain MimeTypes MIME types}.
|
||||
*/
|
||||
protected static String findSupportedMimeTypeForEncoderAndMuxer(
|
||||
Format requestedFormat, List<String> muxerSupportedMimeTypes) throws TransformationException {
|
||||
Format requestedFormat, List<String> muxerSupportedMimeTypes) throws ExportException {
|
||||
boolean isVideo = MimeTypes.isVideo(checkNotNull(requestedFormat.sampleMimeType));
|
||||
|
||||
ImmutableSet.Builder<String> mimeTypesToCheckSetBuilder =
|
||||
@ -185,16 +183,16 @@ import java.util.List;
|
||||
throw createNoSupportedMimeTypeException(requestedFormat);
|
||||
}
|
||||
|
||||
private static TransformationException createNoSupportedMimeTypeException(Format format) {
|
||||
private static ExportException createNoSupportedMimeTypeException(Format format) {
|
||||
String errorMessage = "No MIME type is supported by both encoder and muxer.";
|
||||
int errorCode = TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
|
||||
int errorCode = ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
|
||||
boolean isVideo = MimeTypes.isVideo(format.sampleMimeType);
|
||||
|
||||
if (isVideo && isTransferHdr(format.colorInfo)) {
|
||||
errorMessage += " Requested HDR colorInfo: " + format.colorInfo;
|
||||
}
|
||||
|
||||
return TransformationException.createForCodec(
|
||||
return ExportException.createForCodec(
|
||||
new IllegalArgumentException(errorMessage),
|
||||
errorCode,
|
||||
isVideo,
|
||||
|
@ -33,7 +33,10 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** Thrown when a non-locally recoverable transformation failure occurs. */
|
||||
/**
|
||||
* @deprecated Use {@link ExportException} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@UnstableApi
|
||||
public final class TransformationException extends Exception {
|
||||
|
||||
@ -331,6 +334,12 @@ public final class TransformationException extends Exception {
|
||||
this.timestampMs = Clock.DEFAULT.elapsedRealtime();
|
||||
}
|
||||
|
||||
/* package */ TransformationException(ExportException exportException) {
|
||||
super(exportException.getMessage(), exportException.getCause());
|
||||
errorCode = exportException.errorCode;
|
||||
timestampMs = exportException.timestampMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the error data associated to this exception equals the error data associated to
|
||||
* {@code other}.
|
||||
|
@ -70,7 +70,7 @@ public final class TransformationRequest {
|
||||
* <p>Supported on API 31+, by some device and HDR format combinations. Tone-mapping is only
|
||||
* guaranteed to be supported from Android T onwards.
|
||||
*
|
||||
* <p>If not supported, {@link Transformer} throws a {@link TransformationException}.
|
||||
* <p>If not supported, {@link Transformer} throws an {@link ExportException}.
|
||||
*/
|
||||
public static final int HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_MEDIACODEC = 1;
|
||||
/**
|
||||
@ -84,7 +84,7 @@ public final class TransformationRequest {
|
||||
* implementation, but should have much wider support and have more consistent results across
|
||||
* devices.
|
||||
*
|
||||
* <p>If not supported, {@link Transformer} throws a {@link TransformationException}.
|
||||
* <p>If not supported, {@link Transformer} throws an {@link ExportException}.
|
||||
*/
|
||||
public static final int HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL = 2;
|
||||
/**
|
||||
|
@ -94,7 +94,9 @@ public final class TransformationResult {
|
||||
width = exportResult.width;
|
||||
videoFrameCount = exportResult.videoFrameCount;
|
||||
videoEncoderName = exportResult.videoEncoderName;
|
||||
transformationException = exportResult.transformationException;
|
||||
if (exportResult.exportException != null) {
|
||||
transformationException = new TransformationException(exportResult.exportException);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the {@linkplain ProcessedInput processed inputs}. */
|
||||
|
@ -498,13 +498,13 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, ExportException)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(MediaItem inputMediaItem, Exception exception) {}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, ExportException)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(
|
||||
@ -513,7 +513,7 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, ExportException)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(
|
||||
@ -526,16 +526,17 @@ public final class Transformer {
|
||||
*
|
||||
* @param composition The {@link Composition} for which the exception occurs.
|
||||
* @param exportResult The {@link ExportResult} of the export.
|
||||
* @param exception The {@link TransformationException} describing the exception. This is the
|
||||
* same instance as the {@linkplain ExportResult#transformationException exception} in
|
||||
* {@code result}.
|
||||
* @param exportException The {@link ExportException} describing the exception. This is the same
|
||||
* instance as the {@linkplain ExportResult#exportException exception} in {@code result}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
||||
default void onError(
|
||||
Composition composition, ExportResult exportResult, TransformationException exception) {
|
||||
Composition composition, ExportResult exportResult, ExportException exportException) {
|
||||
MediaItem mediaItem = composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
|
||||
onTransformationError(
|
||||
mediaItem, new TransformationResult.Builder(exportResult).build(), exception);
|
||||
mediaItem,
|
||||
new TransformationResult.Builder(exportResult).build(),
|
||||
new TransformationException(exportException));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -751,7 +752,7 @@ public final class Transformer {
|
||||
checkArgument(composition.sequences.size() == 1);
|
||||
checkArgument(composition.effects == Effects.EMPTY);
|
||||
verifyApplicationThread();
|
||||
checkState(transformerInternal == null, "There is already a export in progress.");
|
||||
checkState(transformerInternal == null, "There is already an export in progress.");
|
||||
|
||||
TransformerInternalListener transformerInternalListener =
|
||||
new TransformerInternalListener(composition);
|
||||
@ -928,11 +929,11 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ExportResult exportResult, TransformationException exception) {
|
||||
public void onError(ExportResult exportResult, ExportException exportException) {
|
||||
transformerInternal = null;
|
||||
listeners.queueEvent(
|
||||
/* eventFlag= */ C.INDEX_UNSET,
|
||||
listener -> listener.onError(composition, exportResult, exception));
|
||||
listener -> listener.onError(composition, exportResult, exportException));
|
||||
listeners.flushEvents();
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ package androidx.media3.transformer;
|
||||
import static androidx.media3.common.util.Assertions.checkState;
|
||||
import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_DECODED;
|
||||
import static androidx.media3.transformer.AssetLoader.SUPPORTED_OUTPUT_TYPE_ENCODED;
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_FAILED_RUNTIME_CHECK;
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_MUXING_FAILED;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_FAILED_RUNTIME_CHECK;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_MUXING_FAILED;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NOT_STARTED;
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
|
||||
@ -57,7 +57,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
void onCompleted(ExportResult exportResult);
|
||||
|
||||
void onError(ExportResult exportResult, TransformationException exception);
|
||||
void onError(ExportResult exportResult, ExportException exportException);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,8 +170,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
return;
|
||||
}
|
||||
internalHandler
|
||||
.obtainMessage(
|
||||
MSG_END, END_REASON_CANCELLED, /* unused */ 0, /* transformationException */ null)
|
||||
.obtainMessage(MSG_END, END_REASON_CANCELLED, /* unused */ 0, /* exportException */ null)
|
||||
.sendToTarget();
|
||||
clock.onThreadBlocked();
|
||||
transformerConditionVariable.blockUninterruptible();
|
||||
@ -201,9 +200,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
drainPipelinesInternal();
|
||||
break;
|
||||
case MSG_END:
|
||||
endInternal(
|
||||
/* endReason= */ msg.arg1,
|
||||
/* transformationException= */ (TransformationException) msg.obj);
|
||||
endInternal(/* endReason= */ msg.arg1, /* exportException= */ (ExportException) msg.obj);
|
||||
break;
|
||||
case MSG_UPDATE_PROGRESS:
|
||||
updateProgressInternal(/* progressHolder= */ (ProgressHolder) msg.obj);
|
||||
@ -211,10 +208,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} catch (TransformationException e) {
|
||||
} catch (ExportException e) {
|
||||
endInternal(END_REASON_ERROR, e);
|
||||
} catch (RuntimeException e) {
|
||||
endInternal(END_REASON_ERROR, TransformationException.createForUnexpected(e));
|
||||
endInternal(END_REASON_ERROR, ExportException.createForUnexpected(e));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -231,7 +228,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
}
|
||||
|
||||
private void drainPipelinesInternal() throws TransformationException {
|
||||
private void drainPipelinesInternal() throws ExportException {
|
||||
for (int i = 0; i < samplePipelines.size(); i++) {
|
||||
while (samplePipelines.get(i).processData()) {}
|
||||
}
|
||||
@ -241,8 +238,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
}
|
||||
|
||||
private void endInternal(
|
||||
@EndReason int endReason, @Nullable TransformationException transformationException) {
|
||||
private void endInternal(@EndReason int endReason, @Nullable ExportException exportException) {
|
||||
ImmutableList<ExportResult.ProcessedInput> processedInputs =
|
||||
compositeAssetLoader.getProcessedInputs();
|
||||
exportResultBuilder
|
||||
@ -251,7 +247,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
.setVideoEncoderName(encoderFactory.getVideoEncoderName());
|
||||
|
||||
boolean forCancellation = endReason == END_REASON_CANCELLED;
|
||||
@Nullable TransformationException releaseTransformationException = null;
|
||||
@Nullable ExportException releaseExportException = null;
|
||||
if (!released) {
|
||||
released = true;
|
||||
|
||||
@ -268,10 +264,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
}
|
||||
} catch (Muxer.MuxerException e) {
|
||||
releaseTransformationException =
|
||||
TransformationException.createForMuxer(e, ERROR_CODE_MUXING_FAILED);
|
||||
releaseExportException = ExportException.createForMuxer(e, ERROR_CODE_MUXING_FAILED);
|
||||
} catch (RuntimeException e) {
|
||||
releaseTransformationException = TransformationException.createForUnexpected(e);
|
||||
releaseExportException = ExportException.createForUnexpected(e);
|
||||
// cancelException is not reported through a listener. It is thrown in cancel(), as this
|
||||
// method is blocking.
|
||||
cancelException = e;
|
||||
@ -286,22 +281,21 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
return;
|
||||
}
|
||||
|
||||
TransformationException exception = transformationException;
|
||||
ExportException exception = exportException;
|
||||
if (exception == null) {
|
||||
// We only report the exception caused by releasing the resources if there is no other
|
||||
// exception. It is more intuitive to call the error callback only once and reporting the
|
||||
// exception caused by releasing the resources can be confusing if it is a consequence of the
|
||||
// first exception.
|
||||
exception = releaseTransformationException;
|
||||
exception = releaseExportException;
|
||||
}
|
||||
|
||||
if (exception != null) {
|
||||
TransformationException finalException = exception;
|
||||
ExportException finalException = exception;
|
||||
applicationHandler.post(
|
||||
() ->
|
||||
listener.onError(
|
||||
exportResultBuilder.setTransformationException(finalException).build(),
|
||||
finalException));
|
||||
exportResultBuilder.setExportException(finalException).build(), finalException));
|
||||
} else {
|
||||
applicationHandler.post(() -> listener.onCompleted(exportResultBuilder.build()));
|
||||
}
|
||||
@ -338,9 +332,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
// AssetLoader.Listener and MuxerWrapper.Listener implementation.
|
||||
|
||||
@Override
|
||||
public void onError(TransformationException transformationException) {
|
||||
public void onError(ExportException exportException) {
|
||||
internalHandler
|
||||
.obtainMessage(MSG_END, END_REASON_ERROR, /* unused */ 0, transformationException)
|
||||
.obtainMessage(MSG_END, END_REASON_ERROR, /* unused */ 0, exportException)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@ -355,7 +349,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
public void onTrackCount(int trackCount) {
|
||||
if (trackCount <= 0) {
|
||||
onError(
|
||||
TransformationException.createForAssetLoader(
|
||||
ExportException.createForAssetLoader(
|
||||
new IllegalStateException("AssetLoader instances must provide at least 1 track."),
|
||||
ERROR_CODE_FAILED_RUNTIME_CHECK));
|
||||
return;
|
||||
@ -369,7 +363,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
@AssetLoader.SupportedOutputTypes int supportedOutputTypes,
|
||||
long streamStartPositionUs,
|
||||
long streamOffsetUs)
|
||||
throws TransformationException {
|
||||
throws ExportException {
|
||||
int trackType = MimeTypes.getTrackType(firstInputFormat.sampleMimeType);
|
||||
if (!trackAdded) {
|
||||
if (generateSilentAudio) {
|
||||
@ -449,8 +443,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
exportResultBuilder.setDurationMs(durationMs).setFileSizeBytes(fileSizeBytes);
|
||||
|
||||
internalHandler
|
||||
.obtainMessage(
|
||||
MSG_END, END_REASON_COMPLETED, /* unused */ 0, /* transformationException */ null)
|
||||
.obtainMessage(MSG_END, END_REASON_COMPLETED, /* unused */ 0, /* exportException */ null)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@ -461,7 +454,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
@AssetLoader.SupportedOutputTypes int supportedOutputTypes,
|
||||
long streamStartPositionUs,
|
||||
long streamOffsetUs)
|
||||
throws TransformationException {
|
||||
throws ExportException {
|
||||
checkState(supportedOutputTypes != 0);
|
||||
boolean isAudio = MimeTypes.isAudio(firstInputFormat.sampleMimeType);
|
||||
boolean shouldTranscode;
|
||||
|
@ -81,20 +81,20 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
VideoFrameProcessor.Factory videoFrameProcessorFactory,
|
||||
Codec.EncoderFactory encoderFactory,
|
||||
MuxerWrapper muxerWrapper,
|
||||
Consumer<TransformationException> errorConsumer,
|
||||
Consumer<ExportException> errorConsumer,
|
||||
FallbackListener fallbackListener,
|
||||
DebugViewProvider debugViewProvider)
|
||||
throws TransformationException {
|
||||
throws ExportException {
|
||||
super(firstInputFormat, streamStartPositionUs, muxerWrapper);
|
||||
|
||||
boolean isGlToneMapping = false;
|
||||
if (isTransferHdr(firstInputFormat.colorInfo)) {
|
||||
if (transformationRequest.hdrMode == HDR_MODE_EXPERIMENTAL_FORCE_INTERPRET_HDR_AS_SDR) {
|
||||
if (SDK_INT < 29) {
|
||||
throw TransformationException.createForCodec(
|
||||
throw ExportException.createForCodec(
|
||||
new IllegalArgumentException(
|
||||
"Interpreting HDR video as SDR is not supported on this device."),
|
||||
TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
|
||||
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
|
||||
/* isVideo= */ true,
|
||||
/* isDecoder= */ true,
|
||||
firstInputFormat);
|
||||
@ -154,7 +154,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
try {
|
||||
checkNotNull(videoFrameProcessor)
|
||||
.setOutputSurfaceInfo(encoderWrapper.getSurfaceInfo(width, height));
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
errorConsumer.accept(exception);
|
||||
}
|
||||
}
|
||||
@ -168,9 +168,8 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
@Override
|
||||
public void onError(VideoFrameProcessingException exception) {
|
||||
errorConsumer.accept(
|
||||
TransformationException.createForVideoFrameProcessingException(
|
||||
exception,
|
||||
TransformationException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED));
|
||||
ExportException.createForVideoFrameProcessingException(
|
||||
exception, ExportException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -179,14 +178,14 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
lastProcessedFramePresentationTimeUs;
|
||||
try {
|
||||
encoderWrapper.signalEndOfInputStream();
|
||||
} catch (TransformationException exception) {
|
||||
} catch (ExportException exception) {
|
||||
errorConsumer.accept(exception);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (VideoFrameProcessingException e) {
|
||||
throw TransformationException.createForVideoFrameProcessingException(
|
||||
e, TransformationException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED);
|
||||
throw ExportException.createForVideoFrameProcessingException(
|
||||
e, ExportException.ERROR_CODE_VIDEO_FRAME_PROCESSING_FAILED);
|
||||
}
|
||||
// The decoder rotates encoded frames for display by firstInputFormat.rotationDegrees.
|
||||
int decodedWidth =
|
||||
@ -249,13 +248,13 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected Format getMuxerInputFormat() throws TransformationException {
|
||||
protected Format getMuxerInputFormat() throws ExportException {
|
||||
return encoderWrapper.getOutputFormat();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected DecoderInputBuffer getMuxerInputBuffer() throws TransformationException {
|
||||
protected DecoderInputBuffer getMuxerInputBuffer() throws ExportException {
|
||||
encoderOutputBuffer.data = encoderWrapper.getOutputBuffer();
|
||||
if (encoderOutputBuffer.data == null) {
|
||||
return null;
|
||||
@ -277,7 +276,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void releaseMuxerInputBuffer() throws TransformationException {
|
||||
protected void releaseMuxerInputBuffer() throws ExportException {
|
||||
encoderWrapper.releaseOutputBuffer(/* render= */ false);
|
||||
}
|
||||
|
||||
@ -398,7 +397,7 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
|
||||
@Nullable
|
||||
public SurfaceInfo getSurfaceInfo(int requestedWidth, int requestedHeight)
|
||||
throws TransformationException {
|
||||
throws ExportException {
|
||||
if (releaseEncoder) {
|
||||
return null;
|
||||
}
|
||||
@ -470,14 +469,14 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
return encoderSurfaceInfo;
|
||||
}
|
||||
|
||||
public void signalEndOfInputStream() throws TransformationException {
|
||||
public void signalEndOfInputStream() throws ExportException {
|
||||
if (encoder != null) {
|
||||
encoder.signalEndOfInputStream();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Format getOutputFormat() throws TransformationException {
|
||||
public Format getOutputFormat() throws ExportException {
|
||||
if (encoder == null) {
|
||||
return null;
|
||||
}
|
||||
@ -489,16 +488,16 @@ import org.checkerframework.dataflow.qual.Pure;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ByteBuffer getOutputBuffer() throws TransformationException {
|
||||
public ByteBuffer getOutputBuffer() throws ExportException {
|
||||
return encoder != null ? encoder.getOutputBuffer() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public MediaCodec.BufferInfo getOutputBufferInfo() throws TransformationException {
|
||||
public MediaCodec.BufferInfo getOutputBufferInfo() throws ExportException {
|
||||
return encoder != null ? encoder.getOutputBufferInfo() : null;
|
||||
}
|
||||
|
||||
public void releaseOutputBuffer(boolean render) throws TransformationException {
|
||||
public void releaseOutputBuffer(boolean render) throws ExportException {
|
||||
if (encoder != null) {
|
||||
encoder.releaseOutputBuffer(render);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
package androidx.media3.transformer;
|
||||
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
|
||||
import static androidx.media3.transformer.ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED;
|
||||
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
@ -109,11 +109,11 @@ public class DefaultEncoderFactoryTest {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H265, 1920, 1080, 30);
|
||||
DefaultEncoderFactory encoderFactory = new DefaultEncoderFactory.Builder(context).build();
|
||||
|
||||
TransformationException transformationException =
|
||||
ExportException exportException =
|
||||
assertThrows(
|
||||
TransformationException.class,
|
||||
ExportException.class,
|
||||
() -> encoderFactory.createForVideoEncoding(requestedVideoFormat));
|
||||
assertThat(transformationException.errorCode).isEqualTo(ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
|
||||
assertThat(exportException.errorCode).isEqualTo(ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -239,7 +239,7 @@ public class DefaultEncoderFactoryTest {
|
||||
public void createForVideoEncoding_withNoAvailableEncoderFromEncoderSelector_throws() {
|
||||
Format requestedVideoFormat = createVideoFormat(MimeTypes.VIDEO_H264, 1920, 1080, 30);
|
||||
assertThrows(
|
||||
TransformationException.class,
|
||||
ExportException.class,
|
||||
() ->
|
||||
new DefaultEncoderFactory.Builder(context)
|
||||
.setVideoEncoderSelector((mimeType) -> ImmutableList.of())
|
||||
|
@ -85,7 +85,7 @@ public class ExoPlayerAssetLoaderTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(TransformationException e) {
|
||||
public void onError(ExportException e) {
|
||||
exceptionRef.set(e);
|
||||
}
|
||||
|
||||
|
@ -507,9 +507,8 @@ public final class TransformerEndToEndTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_DECODER);
|
||||
|
||||
transformer.start(mediaItem, outputPath);
|
||||
TransformationException exception =
|
||||
assertThrows(
|
||||
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
ExportException exception =
|
||||
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
|
||||
verify(mockListener1).onError(compositionArgumentCaptor.capture(), any(), eq(exception));
|
||||
Composition composition = compositionArgumentCaptor.getValue();
|
||||
@ -620,7 +619,7 @@ public final class TransformerEndToEndTest {
|
||||
transformer.start(mediaItem, outputPath);
|
||||
try {
|
||||
TransformerTestRunner.runLooper(transformer);
|
||||
} catch (TransformationException transformationException) {
|
||||
} catch (ExportException exportException) {
|
||||
// Ignore exception thrown.
|
||||
}
|
||||
|
||||
@ -715,12 +714,11 @@ public final class TransformerEndToEndTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_MUXER);
|
||||
|
||||
transformer.start(mediaItem, outputPath);
|
||||
TransformationException exception =
|
||||
assertThrows(
|
||||
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
ExportException exception =
|
||||
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -735,12 +733,11 @@ public final class TransformerEndToEndTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_UNSUPPORTED_BY_DECODER);
|
||||
|
||||
transformer.start(mediaItem, outputPath);
|
||||
TransformationException exception =
|
||||
assertThrows(
|
||||
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
ExportException exception =
|
||||
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
assertThat(exception.errorCode)
|
||||
.isEqualTo(TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
.isEqualTo(ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -749,11 +746,10 @@ public final class TransformerEndToEndTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri("asset:///non-existing-path.mp4");
|
||||
|
||||
transformer.start(mediaItem, outputPath);
|
||||
TransformationException exception =
|
||||
assertThrows(
|
||||
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
ExportException exception =
|
||||
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
assertThat(exception).hasCauseThat().hasCauseThat().isInstanceOf(IOException.class);
|
||||
assertThat(exception.errorCode).isEqualTo(TransformationException.ERROR_CODE_IO_FILE_NOT_FOUND);
|
||||
assertThat(exception.errorCode).isEqualTo(ExportException.ERROR_CODE_IO_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -822,11 +818,10 @@ public final class TransformerEndToEndTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);
|
||||
|
||||
transformer.start(mediaItem, outputPath);
|
||||
TransformationException exception =
|
||||
assertThrows(
|
||||
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
ExportException exception =
|
||||
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalStateException.class);
|
||||
assertThat(exception.errorCode).isEqualTo(TransformationException.ERROR_CODE_MUXING_FAILED);
|
||||
assertThat(exception.errorCode).isEqualTo(ExportException.ERROR_CODE_MUXING_FAILED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -857,7 +852,7 @@ public final class TransformerEndToEndTest {
|
||||
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
|
||||
|
||||
// TODO(b/264974805): Make transformation output deterministic and check it against dump file.
|
||||
assertThat(exportResult.transformationException).isNull();
|
||||
assertThat(exportResult.exportException).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -946,11 +941,10 @@ public final class TransformerEndToEndTest {
|
||||
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
|
||||
|
||||
transformer.start(editedMediaItem, outputPath);
|
||||
TransformationException transformationException =
|
||||
assertThrows(
|
||||
TransformationException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
ExportException exportException =
|
||||
assertThrows(ExportException.class, () -> TransformerTestRunner.runLooper(transformer));
|
||||
|
||||
assertThat(transformationException).hasCauseThat().isInstanceOf(IllegalStateException.class);
|
||||
assertThat(exportException).hasCauseThat().isInstanceOf(IllegalStateException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1427,7 +1421,7 @@ public final class TransformerEndToEndTest {
|
||||
if (sampleConsumerRef != null) {
|
||||
sampleConsumerRef.set(sampleConsumer);
|
||||
}
|
||||
} catch (TransformationException e) {
|
||||
} catch (ExportException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
@ -36,13 +36,13 @@ public final class TransformerTestRunner {
|
||||
*
|
||||
* @param transformer The {@link Transformer}.
|
||||
* @return The {@link ExportResult}.
|
||||
* @throws TransformationException If the transformation threw an exception.
|
||||
* @throws ExportException If the transformation threw an exception.
|
||||
* @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
* @throws IllegalStateException If the method is not called from the main thread.
|
||||
*/
|
||||
public static ExportResult runLooper(Transformer transformer)
|
||||
throws TransformationException, TimeoutException {
|
||||
throws ExportException, TimeoutException {
|
||||
AtomicReference<@NullableType ExportResult> exportResultRef = new AtomicReference<>();
|
||||
|
||||
transformer.addListener(
|
||||
@ -54,11 +54,9 @@ public final class TransformerTestRunner {
|
||||
|
||||
@Override
|
||||
public void onError(
|
||||
Composition composition,
|
||||
ExportResult exportResult,
|
||||
TransformationException exception) {
|
||||
if (!Objects.equals(exportResult.transformationException, exception)) {
|
||||
exportResult = exportResult.buildUpon().setTransformationException(exception).build();
|
||||
Composition composition, ExportResult exportResult, ExportException exportException) {
|
||||
if (!Objects.equals(exportResult.exportException, exportException)) {
|
||||
exportResult = exportResult.buildUpon().setExportException(exportException).build();
|
||||
}
|
||||
exportResultRef.set(exportResult);
|
||||
}
|
||||
@ -66,8 +64,8 @@ public final class TransformerTestRunner {
|
||||
runLooperUntil(transformer.getApplicationLooper(), () -> exportResultRef.get() != null);
|
||||
|
||||
ExportResult exportResult = checkNotNull(exportResultRef.get());
|
||||
if (exportResult.transformationException != null) {
|
||||
throw exportResult.transformationException;
|
||||
if (exportResult.exportException != null) {
|
||||
throw exportResult.exportException;
|
||||
}
|
||||
|
||||
return exportResult;
|
||||
|
@ -118,8 +118,7 @@ public final class VideoEncoderWrapperTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSurfaceInfo_withEncoderFallback_usesFallbackResolution()
|
||||
throws TransformationException {
|
||||
public void getSurfaceInfo_withEncoderFallback_usesFallbackResolution() throws Exception {
|
||||
int inputWidth = 200;
|
||||
int inputHeight = 150;
|
||||
int fallbackWidth = 100;
|
||||
|
Loading…
x
Reference in New Issue
Block a user