Create and return a TransformationResult regardless of success.
The TransformationResult has some useful values that are set in error cases, such as the codecs used. PiperOrigin-RevId: 495568259
This commit is contained in:
parent
a09bdfe995
commit
63cc0338e1
@ -311,13 +311,15 @@ public final class TransformerActivity extends AppCompatActivity {
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(
|
||||
MediaItem mediaItem, TransformationResult transformationResult) {
|
||||
MediaItem mediaItem, TransformationResult result) {
|
||||
TransformerActivity.this.onTransformationCompleted(filePath, mediaItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransformationError(
|
||||
MediaItem mediaItem, TransformationException exception) {
|
||||
MediaItem mediaItem,
|
||||
TransformationResult result,
|
||||
TransformationException exception) {
|
||||
TransformerActivity.this.onTransformationError(exception);
|
||||
}
|
||||
})
|
||||
|
@ -17,6 +17,7 @@ package androidx.media3.transformer;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.util.Assertions;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -28,20 +29,33 @@ public class TransformationTestResult {
|
||||
|
||||
/** A builder for {@link TransformationTestResult}. */
|
||||
public static class Builder {
|
||||
private final TransformationResult transformationResult;
|
||||
|
||||
@Nullable private TransformationResult transformationResult;
|
||||
@Nullable private String filePath;
|
||||
@Nullable private Exception analysisException;
|
||||
private long elapsedTimeMs;
|
||||
private double ssim;
|
||||
@Nullable private Exception testException;
|
||||
@Nullable private Exception analysisException;
|
||||
|
||||
/** Creates a new {@link Builder}. */
|
||||
public Builder(TransformationResult transformationResult) {
|
||||
this.transformationResult = transformationResult;
|
||||
public Builder() {
|
||||
this.elapsedTimeMs = C.TIME_UNSET;
|
||||
this.ssim = SSIM_UNSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link TransformationResult} of the transformation.
|
||||
*
|
||||
* <p>This field must be set.
|
||||
*
|
||||
* @param transformationResult The {@link TransformationResult}.
|
||||
* @return This {@link Builder}
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setTransformationResult(TransformationResult transformationResult) {
|
||||
this.transformationResult = transformationResult;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file path of the output file.
|
||||
*
|
||||
@ -85,6 +99,20 @@ public class TransformationTestResult {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an {@link Exception} that occurred during the test.
|
||||
*
|
||||
* <p>{@code null} represents an unset or unknown value.
|
||||
*
|
||||
* @param testException The {@link Exception} thrown during the test.
|
||||
* @return This {@link Builder}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setTestException(@Nullable Exception testException) {
|
||||
this.testException = testException;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an {@link Exception} that occurred during post-transformation analysis.
|
||||
*
|
||||
@ -102,7 +130,12 @@ public class TransformationTestResult {
|
||||
/** Builds the {@link TransformationTestResult} instance. */
|
||||
public TransformationTestResult build() {
|
||||
return new TransformationTestResult(
|
||||
transformationResult, filePath, elapsedTimeMs, ssim, analysisException);
|
||||
Assertions.checkNotNull(transformationResult),
|
||||
filePath,
|
||||
elapsedTimeMs,
|
||||
ssim,
|
||||
testException,
|
||||
analysisException);
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,6 +153,12 @@ public class TransformationTestResult {
|
||||
public final long elapsedTimeMs;
|
||||
/** The SSIM score of the transformation, {@link #SSIM_UNSET} if unavailable. */
|
||||
public final double ssim;
|
||||
|
||||
/**
|
||||
* The {@link Exception} that was thrown during the test, or {@code null} if nothing was thrown.
|
||||
*/
|
||||
@Nullable public final Exception testException;
|
||||
|
||||
/**
|
||||
* The {@link Exception} that was thrown during post-transformation analysis, or {@code null} if
|
||||
* nothing was thrown.
|
||||
@ -165,6 +204,9 @@ public class TransformationTestResult {
|
||||
if (ssim != TransformationTestResult.SSIM_UNSET) {
|
||||
jsonObject.put("ssim", ssim);
|
||||
}
|
||||
if (testException != null) {
|
||||
jsonObject.put("testException", AndroidTestUtil.exceptionAsJsonObject(testException));
|
||||
}
|
||||
if (analysisException != null) {
|
||||
jsonObject.put("analysisException", AndroidTestUtil.exceptionAsJsonObject(analysisException));
|
||||
}
|
||||
@ -176,11 +218,13 @@ public class TransformationTestResult {
|
||||
@Nullable String filePath,
|
||||
long elapsedTimeMs,
|
||||
double ssim,
|
||||
@Nullable Exception testException,
|
||||
@Nullable Exception analysisException) {
|
||||
this.transformationResult = transformationResult;
|
||||
this.filePath = filePath;
|
||||
this.elapsedTimeMs = elapsedTimeMs;
|
||||
this.ssim = ssim;
|
||||
this.testException = testException;
|
||||
this.analysisException = analysisException;
|
||||
this.throughputFps =
|
||||
elapsedTimeMs != C.TIME_UNSET && transformationResult.videoFrameCount > 0
|
||||
|
@ -39,7 +39,6 @@ import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/** An android instrumentation test runner for {@link Transformer}. */
|
||||
@ -153,8 +152,6 @@ public class TransformerAndroidTestRunner {
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
private final CapturingDecoderFactory decoderFactory;
|
||||
private final CapturingEncoderFactory encoderFactory;
|
||||
private final Transformer transformer;
|
||||
private final int timeoutSeconds;
|
||||
private final boolean requestCalculateSsim;
|
||||
@ -169,14 +166,7 @@ public class TransformerAndroidTestRunner {
|
||||
boolean suppressAnalysisExceptions,
|
||||
@Nullable Map<String, Object> inputValues) {
|
||||
this.context = context;
|
||||
this.decoderFactory = new CapturingDecoderFactory(transformer.decoderFactory);
|
||||
this.encoderFactory = new CapturingEncoderFactory(transformer.encoderFactory);
|
||||
this.transformer =
|
||||
transformer
|
||||
.buildUpon()
|
||||
.setDecoderFactory(decoderFactory)
|
||||
.setEncoderFactory(encoderFactory)
|
||||
.build();
|
||||
this.transformer = transformer;
|
||||
this.timeoutSeconds = timeoutSeconds;
|
||||
this.requestCalculateSsim = requestCalculateSsim;
|
||||
this.suppressAnalysisExceptions = suppressAnalysisExceptions;
|
||||
@ -184,7 +174,7 @@ public class TransformerAndroidTestRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the {@code uriString}, saving a summary of the transformation to the application
|
||||
* Transforms the {@link MediaItem}, saving a summary of the transformation to the application
|
||||
* cache.
|
||||
*
|
||||
* @param testId A unique identifier for the transformer test run.
|
||||
@ -200,35 +190,35 @@ public class TransformerAndroidTestRunner {
|
||||
try {
|
||||
TransformationTestResult transformationTestResult = runInternal(testId, mediaItem);
|
||||
resultJson.put("transformationResult", transformationTestResult.asJsonObject());
|
||||
if (transformationTestResult.testException != null) {
|
||||
throw transformationTestResult.testException;
|
||||
}
|
||||
if (!suppressAnalysisExceptions && transformationTestResult.analysisException != null) {
|
||||
throw transformationTestResult.analysisException;
|
||||
}
|
||||
return transformationTestResult;
|
||||
} catch (Exception e) {
|
||||
resultJson.put("exception", AndroidTestUtil.exceptionAsJsonObject(e));
|
||||
} catch (UnsupportedOperationException | InterruptedException | IOException e) {
|
||||
resultJson.put(
|
||||
"transformationResult",
|
||||
new JSONObject().put("testException", AndroidTestUtil.exceptionAsJsonObject(e)));
|
||||
throw e;
|
||||
} finally {
|
||||
resultJson.put("codecDetails", getCodecNamesAsJsonObject());
|
||||
AndroidTestUtil.writeTestSummaryToFile(context, testId, resultJson);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the {@code uriString}.
|
||||
* Transforms the {@link MediaItem}.
|
||||
*
|
||||
* @param testId An identifier for the test.
|
||||
* @param mediaItem The {@link MediaItem} to transform.
|
||||
* @return The {@link TransformationTestResult}.
|
||||
* @throws IOException If an error occurs opening the output file for writing
|
||||
* @throws TimeoutException If the transformation takes longer than the {@link #timeoutSeconds}.
|
||||
* @throws InterruptedException If the thread is interrupted whilst waiting for transformer to
|
||||
* complete.
|
||||
* @throws TransformationException If an exception occurs as a result of the transformation.
|
||||
* @throws IllegalArgumentException If the path is invalid.
|
||||
* @throws IllegalStateException If an unexpected exception occurs when starting a transformation.
|
||||
* @throws IOException If an error occurs opening the output file for writing.
|
||||
*/
|
||||
private TransformationTestResult runInternal(String testId, MediaItem mediaItem)
|
||||
throws InterruptedException, IOException, TimeoutException, TransformationException {
|
||||
throws InterruptedException, IOException {
|
||||
if (!mediaItem.clippingConfiguration.equals(MediaItem.ClippingConfiguration.UNSET)
|
||||
&& requestCalculateSsim) {
|
||||
throw new UnsupportedOperationException(
|
||||
@ -266,8 +256,11 @@ public class TransformerAndroidTestRunner {
|
||||
|
||||
@Override
|
||||
public void onTransformationError(
|
||||
MediaItem inputMediaItem, TransformationException exception) {
|
||||
MediaItem inputMediaItem,
|
||||
TransformationResult result,
|
||||
TransformationException exception) {
|
||||
transformationExceptionReference.set(exception);
|
||||
transformationResultReference.set(result);
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
|
||||
@ -302,45 +295,54 @@ public class TransformerAndroidTestRunner {
|
||||
}
|
||||
});
|
||||
|
||||
if (!countDownLatch.await(timeoutSeconds, SECONDS)) {
|
||||
throw new TimeoutException("Transformer timed out after " + timeoutSeconds + " seconds.");
|
||||
}
|
||||
long elapsedTimeMs = SystemClock.DEFAULT.elapsedRealtime() - startTimeMs;
|
||||
// Block here until timeout reached or latch is counted down.
|
||||
boolean timeoutReached = !countDownLatch.await(timeoutSeconds, SECONDS);
|
||||
|
||||
TransformationTestResult.Builder testResultBuilder =
|
||||
new TransformationTestResult.Builder()
|
||||
.setElapsedTimeMs(SystemClock.DEFAULT.elapsedRealtime() - startTimeMs);
|
||||
|
||||
@Nullable Exception unexpectedException = unexpectedExceptionReference.get();
|
||||
if (unexpectedException != null) {
|
||||
throw new IllegalStateException(
|
||||
"Unexpected exception starting the transformer.", unexpectedException);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
TransformationException transformationException = transformationExceptionReference.get();
|
||||
if (transformationException != null) {
|
||||
throw transformationException;
|
||||
|
||||
@Nullable Exception testException = null;
|
||||
if (timeoutReached) {
|
||||
testException =
|
||||
new TimeoutException("Transformer timed out after " + timeoutSeconds + " seconds.");
|
||||
} else if (unexpectedException != null) {
|
||||
testException =
|
||||
new IllegalStateException(
|
||||
"Unexpected exception starting the transformer.", unexpectedException);
|
||||
} else if (transformationException != null) {
|
||||
testException = transformationException;
|
||||
}
|
||||
|
||||
// If both exceptions are null, the Transformation must have succeeded, and a
|
||||
// transformationResult will be available.
|
||||
TransformationResult transformationResult =
|
||||
checkNotNull(transformationResultReference.get())
|
||||
.buildUpon()
|
||||
.setFileSizeBytes(outputVideoFile.length())
|
||||
.build();
|
||||
if (testException != null) {
|
||||
return testResultBuilder
|
||||
.setTransformationResult(checkNotNull(transformationResultReference.get()))
|
||||
.setTestException(testException)
|
||||
.build();
|
||||
}
|
||||
|
||||
TransformationTestResult.Builder resultBuilder =
|
||||
new TransformationTestResult.Builder(transformationResult)
|
||||
.setFilePath(outputVideoFile.getPath())
|
||||
.setElapsedTimeMs(elapsedTimeMs);
|
||||
// No exceptions raised, transformation has succeeded.
|
||||
testResultBuilder
|
||||
.setTransformationResult(
|
||||
checkNotNull(transformationResultReference.get())
|
||||
.buildUpon()
|
||||
.setFileSizeBytes(outputVideoFile.length())
|
||||
.build())
|
||||
.setFilePath(outputVideoFile.getPath());
|
||||
|
||||
if (!requestCalculateSsim) {
|
||||
return resultBuilder.build();
|
||||
return testResultBuilder.build();
|
||||
}
|
||||
if (fallbackResolutionApplied.get()) {
|
||||
Log.i(
|
||||
TAG,
|
||||
testId
|
||||
+ ": Skipping SSIM calculation because an encoder resolution fallback was applied.");
|
||||
return resultBuilder.build();
|
||||
return testResultBuilder.build();
|
||||
}
|
||||
try {
|
||||
double ssim =
|
||||
@ -348,7 +350,7 @@ public class TransformerAndroidTestRunner {
|
||||
context,
|
||||
/* referenceVideoPath= */ checkNotNull(mediaItem.localConfiguration).uri.toString(),
|
||||
/* distortedVideoPath= */ outputVideoFile.getPath());
|
||||
resultBuilder.setSsim(ssim);
|
||||
testResultBuilder.setSsim(ssim);
|
||||
} catch (InterruptedException interruptedException) {
|
||||
// InterruptedException is a special unexpected case because it is not related to Ssim
|
||||
// calculation, so it should be thrown, rather than processed as part of the
|
||||
@ -366,11 +368,11 @@ public class TransformerAndroidTestRunner {
|
||||
? (Exception) analysisFailure
|
||||
: new IllegalStateException(analysisFailure);
|
||||
|
||||
resultBuilder.setAnalysisException(analysisException);
|
||||
testResultBuilder.setAnalysisException(analysisException);
|
||||
Log.e(TAG, testId + ": SSIM calculation failed.", analysisException);
|
||||
}
|
||||
}
|
||||
return resultBuilder.build();
|
||||
return testResultBuilder.build();
|
||||
}
|
||||
|
||||
/** Returns whether the context is connected to the network. */
|
||||
@ -400,21 +402,4 @@ public class TransformerAndroidTestRunner {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private JSONObject getCodecNamesAsJsonObject() throws JSONException {
|
||||
JSONObject detailsJson = new JSONObject();
|
||||
if (decoderFactory.getAudioDecoderName() != null) {
|
||||
detailsJson.put("audioDecoderName", decoderFactory.getAudioDecoderName());
|
||||
}
|
||||
if (decoderFactory.getVideoDecoderName() != null) {
|
||||
detailsJson.put("videoDecoderName", decoderFactory.getVideoDecoderName());
|
||||
}
|
||||
if (encoderFactory.getAudioEncoderName() != null) {
|
||||
detailsJson.put("audioEncoderName", encoderFactory.getAudioEncoderName());
|
||||
}
|
||||
if (encoderFactory.getVideoEncoderName() != null) {
|
||||
detailsJson.put("videoEncoderName", encoderFactory.getVideoEncoderName());
|
||||
}
|
||||
return detailsJson;
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public final class TransformationResult {
|
||||
@Nullable private String audioEncoderName;
|
||||
@Nullable private String videoDecoderName;
|
||||
@Nullable private String videoEncoderName;
|
||||
@Nullable private TransformationException transformationException;
|
||||
|
||||
public Builder() {
|
||||
durationMs = C.TIME_UNSET;
|
||||
@ -53,7 +54,7 @@ public final class TransformationResult {
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setDurationMs(long durationMs) {
|
||||
checkArgument(durationMs > 0 || durationMs == C.TIME_UNSET);
|
||||
checkArgument(durationMs >= 0 || durationMs == C.TIME_UNSET);
|
||||
this.durationMs = durationMs;
|
||||
return this;
|
||||
}
|
||||
@ -134,6 +135,14 @@ public final class TransformationResult {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the {@link TransformationException} that caused the transformation to fail. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setTransformationException(
|
||||
@Nullable TransformationException transformationException) {
|
||||
this.transformationException = transformationException;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransformationResult build() {
|
||||
return new TransformationResult(
|
||||
durationMs,
|
||||
@ -144,7 +153,8 @@ public final class TransformationResult {
|
||||
audioDecoderName,
|
||||
audioEncoderName,
|
||||
videoDecoderName,
|
||||
videoEncoderName);
|
||||
videoEncoderName,
|
||||
transformationException);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +172,6 @@ public final class TransformationResult {
|
||||
public final int averageVideoBitrate;
|
||||
/** The number of video frames. */
|
||||
public final int videoFrameCount;
|
||||
|
||||
/** The name of the audio decoder used, or {@code null} if none were used. */
|
||||
@Nullable public final String audioDecoderName;
|
||||
/** The name of the audio encoder used, or {@code null} if none were used. */
|
||||
@ -171,6 +180,11 @@ public final class TransformationResult {
|
||||
@Nullable public final String videoDecoderName;
|
||||
/** The name of the video encoder used, or {@code null} if none were used. */
|
||||
@Nullable public final String videoEncoderName;
|
||||
/**
|
||||
* The {@link TransformationException} that caused the transformation to fail, or {@code null} if
|
||||
* the transformation was a success.
|
||||
*/
|
||||
@Nullable public final TransformationException transformationException;
|
||||
|
||||
private TransformationResult(
|
||||
long durationMs,
|
||||
@ -181,7 +195,8 @@ public final class TransformationResult {
|
||||
@Nullable String audioDecoderName,
|
||||
@Nullable String audioEncoderName,
|
||||
@Nullable String videoDecoderName,
|
||||
@Nullable String videoEncoderName) {
|
||||
@Nullable String videoEncoderName,
|
||||
@Nullable TransformationException transformationException) {
|
||||
this.durationMs = durationMs;
|
||||
this.fileSizeBytes = fileSizeBytes;
|
||||
this.averageAudioBitrate = averageAudioBitrate;
|
||||
@ -191,6 +206,7 @@ public final class TransformationResult {
|
||||
this.audioEncoderName = audioEncoderName;
|
||||
this.videoDecoderName = videoDecoderName;
|
||||
this.videoEncoderName = videoEncoderName;
|
||||
this.transformationException = transformationException;
|
||||
}
|
||||
|
||||
public Builder buildUpon() {
|
||||
@ -203,7 +219,8 @@ public final class TransformationResult {
|
||||
.setAudioDecoderName(audioDecoderName)
|
||||
.setAudioEncoderName(audioEncoderName)
|
||||
.setVideoDecoderName(videoDecoderName)
|
||||
.setVideoEncoderName(videoEncoderName);
|
||||
.setVideoEncoderName(videoEncoderName)
|
||||
.setTransformationException(transformationException);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -223,7 +240,8 @@ public final class TransformationResult {
|
||||
&& Objects.equals(audioDecoderName, result.audioDecoderName)
|
||||
&& Objects.equals(audioEncoderName, result.audioEncoderName)
|
||||
&& Objects.equals(videoDecoderName, result.videoDecoderName)
|
||||
&& Objects.equals(videoEncoderName, result.videoEncoderName);
|
||||
&& Objects.equals(videoEncoderName, result.videoEncoderName)
|
||||
&& Objects.equals(transformationException, result.transformationException);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -237,6 +255,7 @@ public final class TransformationResult {
|
||||
result = 31 * result + Objects.hashCode(audioEncoderName);
|
||||
result = 31 * result + Objects.hashCode(videoDecoderName);
|
||||
result = 31 * result + Objects.hashCode(videoEncoderName);
|
||||
result = 31 * result + Objects.hashCode(transformationException);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -535,21 +535,33 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onTransformationError(MediaItem, TransformationException)}.
|
||||
* @deprecated Use {@link #onTransformationError(MediaItem, TransformationResult,
|
||||
* TransformationException)}.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(MediaItem inputMediaItem, Exception exception) {
|
||||
onTransformationError(inputMediaItem, (TransformationException) exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onTransformationError(MediaItem, TransformationResult,
|
||||
* TransformationException)}.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(
|
||||
MediaItem inputMediaItem, TransformationException exception) {
|
||||
onTransformationError(inputMediaItem, new TransformationResult.Builder().build(), exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called if an exception occurs during the transformation.
|
||||
*
|
||||
* @param inputMediaItem The {@link MediaItem} for which the exception occurs.
|
||||
* @param result The {@link TransformationResult} of the transformation.
|
||||
* @param exception The {@link TransformationException} describing the exception.
|
||||
*/
|
||||
default void onTransformationError(
|
||||
MediaItem inputMediaItem, TransformationException exception) {}
|
||||
MediaItem inputMediaItem, TransformationResult result, TransformationException exception) {}
|
||||
|
||||
/**
|
||||
* Called when fallback to an alternative {@link TransformationRequest} is necessary to comply
|
||||
@ -880,13 +892,14 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransformationError(TransformationException exception) {
|
||||
public void onTransformationError(
|
||||
TransformationResult result, TransformationException exception) {
|
||||
handler.post(
|
||||
() -> {
|
||||
transformerInternal = null;
|
||||
listeners.queueEvent(
|
||||
/* eventFlag= */ C.INDEX_UNSET,
|
||||
listener -> listener.onTransformationError(mediaItem, exception));
|
||||
listener -> listener.onTransformationError(mediaItem, result, exception));
|
||||
listeners.flushEvents();
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package androidx.media3.transformer;
|
||||
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.transformer.TransformationException.ERROR_CODE_MUXING_FAILED;
|
||||
import static androidx.media3.transformer.Transformer.PROGRESS_STATE_NO_TRANSFORMATION;
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
@ -57,9 +56,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
public interface Listener {
|
||||
|
||||
void onTransformationCompleted(TransformationResult transformationResult);
|
||||
void onTransformationCompleted(TransformationResult result);
|
||||
|
||||
void onTransformationError(TransformationException exception);
|
||||
void onTransformationError(TransformationResult result, TransformationException exception);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -300,7 +299,13 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
private void endInternal(
|
||||
@EndReason int endReason, @Nullable TransformationException transformationException) {
|
||||
@Nullable TransformationResult transformationResult = null;
|
||||
TransformationResult.Builder transformationResultBuilder =
|
||||
new TransformationResult.Builder()
|
||||
.setAudioDecoderName(decoderFactory.getAudioDecoderName())
|
||||
.setVideoDecoderName(decoderFactory.getVideoDecoderName())
|
||||
.setAudioEncoderName(encoderFactory.getAudioEncoderName())
|
||||
.setVideoEncoderName(encoderFactory.getVideoEncoderName());
|
||||
|
||||
boolean forCancellation = endReason == END_REASON_CANCELLED;
|
||||
@Nullable TransformationException releaseTransformationException = null;
|
||||
if (!released) {
|
||||
@ -315,26 +320,17 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
assetLoader.release();
|
||||
} finally {
|
||||
try {
|
||||
for (int i = 0; i < samplePipelines.size(); i++) {
|
||||
samplePipelines.get(i).release();
|
||||
if (endReason == END_REASON_COMPLETED) {
|
||||
transformationResultBuilder
|
||||
.setDurationMs(muxerWrapper.getDurationMs())
|
||||
.setFileSizeBytes(muxerWrapper.getCurrentOutputSizeBytes())
|
||||
.setAverageAudioBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_AUDIO))
|
||||
.setAverageVideoBitrate(muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_VIDEO))
|
||||
.setVideoFrameCount(muxerWrapper.getTrackSampleCount(C.TRACK_TYPE_VIDEO));
|
||||
}
|
||||
|
||||
// TODO(b/250564186): Create TransformationResult on END_REASON_ERROR as well.
|
||||
if (endReason == END_REASON_COMPLETED) {
|
||||
transformationResult =
|
||||
new TransformationResult.Builder()
|
||||
.setDurationMs(checkNotNull(muxerWrapper).getDurationMs())
|
||||
.setAverageAudioBitrate(
|
||||
muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_AUDIO))
|
||||
.setAverageVideoBitrate(
|
||||
muxerWrapper.getTrackAverageBitrate(C.TRACK_TYPE_VIDEO))
|
||||
.setVideoFrameCount(muxerWrapper.getTrackSampleCount(C.TRACK_TYPE_VIDEO))
|
||||
.setFileSizeBytes(muxerWrapper.getCurrentOutputSizeBytes())
|
||||
.setAudioDecoderName(decoderFactory.getAudioDecoderName())
|
||||
.setAudioEncoderName(encoderFactory.getAudioEncoderName())
|
||||
.setVideoDecoderName(decoderFactory.getVideoDecoderName())
|
||||
.setVideoEncoderName(encoderFactory.getVideoEncoderName())
|
||||
.build();
|
||||
for (int i = 0; i < samplePipelines.size(); i++) {
|
||||
samplePipelines.get(i).release();
|
||||
}
|
||||
} finally {
|
||||
muxerWrapper.release(forCancellation);
|
||||
@ -369,9 +365,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
}
|
||||
|
||||
if (exception != null) {
|
||||
listener.onTransformationError(exception);
|
||||
listener.onTransformationError(
|
||||
transformationResultBuilder.setTransformationException(exception).build(), exception);
|
||||
} else {
|
||||
listener.onTransformationCompleted(checkNotNull(transformationResult));
|
||||
listener.onTransformationCompleted(transformationResultBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,9 +337,9 @@ public final class TransformerEndToEndTest {
|
||||
transformer.startTransformation(mediaItem, outputPath);
|
||||
TransformationException exception = TransformerTestRunner.runUntilError(transformer);
|
||||
|
||||
verify(mockListener1).onTransformationError(mediaItem, exception);
|
||||
verify(mockListener2).onTransformationError(mediaItem, exception);
|
||||
verify(mockListener3).onTransformationError(mediaItem, exception);
|
||||
verify(mockListener1).onTransformationError(eq(mediaItem), any(), eq(exception));
|
||||
verify(mockListener2).onTransformationError(eq(mediaItem), any(), eq(exception));
|
||||
verify(mockListener3).onTransformationError(eq(mediaItem), any(), eq(exception));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -85,7 +85,9 @@ public final class TransformerTestRunner {
|
||||
|
||||
@Override
|
||||
public void onTransformationError(
|
||||
MediaItem inputMediaItem, TransformationException exception) {
|
||||
MediaItem inputMediaItem,
|
||||
TransformationResult result,
|
||||
TransformationException exception) {
|
||||
transformationException.set(exception);
|
||||
}
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user