Add CodecDetails to ExportException

This will replace the existing free-form string in the error message

PiperOrigin-RevId: 640954158
This commit is contained in:
sheenachhabra 2024-06-06 10:58:33 -07:00 committed by Copybara-Service
parent 977fe6aef3
commit ec0af5a7e0
6 changed files with 88 additions and 54 deletions

View File

@ -997,7 +997,7 @@ public class TransformerEndToEndTest {
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
assertThat(exception.errorCode).isEqualTo(ExportException.ERROR_CODE_ENCODER_INIT_FAILED);
assertThat(exception).hasMessageThat().contains("video");
assertThat(exception.codecInfo.isVideo).isTrue();
}
@Test
@ -1813,9 +1813,8 @@ public class TransformerEndToEndTest {
throw ExportException.createForCodec(
new IllegalArgumentException(),
ExportException.ERROR_CODE_ENCODER_INIT_FAILED,
/* isVideo= */ true,
/* isDecoder= */ false,
format);
new ExportException.CodecInfo(
format.toString(), /* isVideo= */ true, /* isDecoder= */ false, /* name= */ null));
}
@Override

View File

@ -460,9 +460,10 @@ public final class DefaultCodec implements Codec {
Exception cause,
@ExportException.ErrorCode int errorCode,
String mediaCodecName) {
String codecDetails =
"mediaFormat=" + configurationMediaFormat + ", mediaCodecName=" + mediaCodecName;
return ExportException.createForCodec(cause, errorCode, isVideo, isDecoder, codecDetails);
ExportException.CodecInfo codecInfo =
new ExportException.CodecInfo(
configurationMediaFormat.toString(), isVideo, isDecoder, mediaCodecName);
return ExportException.createForCodec(cause, errorCode, codecInfo);
}
private static Format convertToFormat(

View File

@ -389,8 +389,10 @@ public final class DefaultDecoderFactory implements Codec.DecoderFactory {
return ExportException.createForCodec(
new IllegalArgumentException(reason),
ExportException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
MimeTypes.isVideo(checkNotNull(format.sampleMimeType)),
/* isDecoder= */ true,
format);
new ExportException.CodecInfo(
format.toString(),
MimeTypes.isVideo(checkNotNull(format.sampleMimeType)),
/* isDecoder= */ true,
/* name= */ null));
}
}

View File

@ -711,9 +711,11 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
return ExportException.createForCodec(
new IllegalArgumentException(errorString),
ExportException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED,
MimeTypes.isVideo(format.sampleMimeType),
/* isDecoder= */ false,
format);
new ExportException.CodecInfo(
format.toString(),
MimeTypes.isVideo(format.sampleMimeType),
/* isDecoder= */ false,
/* name= */ null));
}
private static boolean deviceNeedsDefaultFrameRateWorkaround() {

View File

@ -17,6 +17,7 @@ package androidx.media3.transformer;
import static java.lang.annotation.ElementType.TYPE_USE;
import android.media.MediaFormat;
import android.os.SystemClock;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
@ -37,6 +38,46 @@ import java.lang.annotation.Target;
@UnstableApi
public final class ExportException extends Exception {
/** The {@link Codec} details. */
public static final class CodecInfo {
/**
* A string describing the format used to configure the underlying codec, for example, the value
* returned by {@link Format#toString()} or {@link MediaFormat#toString()}.
*/
public final String configurationFormat;
/** Whether the {@link Codec} is configured for video. */
public final boolean isVideo;
/** Whether the {@link Codec} is used as a decoder. */
public final boolean isDecoder;
/** The {@link Codec} name, or {@code null} if the {@link Codec} is not yet initialized. */
@Nullable public final String name;
/** Creates an instance. */
public CodecInfo(
String configurationFormat, boolean isVideo, boolean isDecoder, @Nullable String name) {
this.configurationFormat = configurationFormat;
this.isVideo = isVideo;
this.isDecoder = isDecoder;
this.name = name;
}
@Override
public String toString() {
String type = (isVideo ? "Video" : "Audio") + (isDecoder ? "Decoder" : "Encoder");
return "CodecInfo{"
+ "type="
+ type
+ ", configurationFormat="
+ configurationFormat
+ ", name="
+ name
+ '}';
}
}
/**
* Error codes that identify causes of {@link Transformer} errors.
*
@ -244,48 +285,14 @@ public final class ExportException extends Exception {
/**
* 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}.
* @param codecInfo The {@link CodecInfo}.
* @return The created instance.
*/
public static ExportException createForCodec(
Throwable cause,
@ErrorCode int errorCode,
boolean isVideo,
boolean isDecoder,
Format format) {
String details = "format=" + format;
if (isVideo) {
details += ", colorInfo=" + format.colorInfo;
}
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);
Throwable cause, @ErrorCode int errorCode, CodecInfo codecInfo) {
return new ExportException("Codec exception: " + codecInfo, cause, errorCode, codecInfo);
}
/**
@ -352,7 +359,13 @@ public final class ExportException extends Exception {
public final long timestampMs;
/**
* Creates an instance.
* The {@linkplain CodecInfo} for codec related exceptions, or {@code null} if the exception is
* not codec related.
*/
@Nullable public final CodecInfo codecInfo;
/**
* Creates an instance with {@code codecInfo} set to {@code null}.
*
* @param message See {@link #getMessage()}.
* @param cause See {@link #getCause()}.
@ -361,9 +374,27 @@ public final class ExportException extends Exception {
*/
private ExportException(
@Nullable String message, @Nullable Throwable cause, @ErrorCode int errorCode) {
this(message, cause, errorCode, /* codecInfo= */ null);
}
/**
* 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}.
* @param codecInfo The {@link CodecInfo}, or {@code null} if the exception is not codec related.
*/
private ExportException(
@Nullable String message,
@Nullable Throwable cause,
@ErrorCode int errorCode,
@Nullable CodecInfo codecInfo) {
super(message, cause);
this.errorCode = errorCode;
this.timestampMs = Clock.DEFAULT.elapsedRealtime();
this.codecInfo = codecInfo;
}
/**

View File

@ -208,8 +208,7 @@ import java.util.List;
return ExportException.createForCodec(
new IllegalArgumentException(errorMessage),
errorCode,
isVideo,
/* isDecoder= */ false,
format);
new ExportException.CodecInfo(
format.toString(), isVideo, /* isDecoder= */ false, /* name= */ null));
}
}