Rename TransformationResult to ExportResult
Also replace some usages of deprecated Transformer listeners with the new ones. PiperOrigin-RevId: 507743860
This commit is contained in:
parent
01d7bc7279
commit
c434cc0c9f
@ -74,14 +74,15 @@ import androidx.media3.effect.TextureOverlay;
|
||||
import androidx.media3.exoplayer.ExoPlayer;
|
||||
import androidx.media3.exoplayer.audio.SilenceSkippingAudioProcessor;
|
||||
import androidx.media3.exoplayer.util.DebugTextViewHelper;
|
||||
import androidx.media3.transformer.Composition;
|
||||
import androidx.media3.transformer.DefaultEncoderFactory;
|
||||
import androidx.media3.transformer.DefaultMuxer;
|
||||
import androidx.media3.transformer.EditedMediaItem;
|
||||
import androidx.media3.transformer.Effects;
|
||||
import androidx.media3.transformer.ExportResult;
|
||||
import androidx.media3.transformer.ProgressHolder;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.TransformationResult;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.ui.AspectRatioFrameLayout;
|
||||
import androidx.media3.ui.PlayerView;
|
||||
@ -307,15 +308,16 @@ public final class TransformerActivity extends AppCompatActivity {
|
||||
.addListener(
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(
|
||||
MediaItem mediaItem, TransformationResult result) {
|
||||
public void onCompleted(Composition composition, ExportResult exportResult) {
|
||||
MediaItem mediaItem =
|
||||
composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
|
||||
TransformerActivity.this.onTransformationCompleted(filePath, mediaItem);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransformationError(
|
||||
MediaItem mediaItem,
|
||||
TransformationResult result,
|
||||
public void onError(
|
||||
Composition composition,
|
||||
ExportResult exportResult,
|
||||
TransformationException exception) {
|
||||
TransformerActivity.this.onTransformationError(exception);
|
||||
}
|
||||
|
@ -504,17 +504,17 @@ public final class AndroidTestUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link JSONArray} from {@link TransformationResult.ProcessedInput processed inputs}.
|
||||
* Creates a {@link JSONArray} from {@link ExportResult.ProcessedInput processed inputs}.
|
||||
*
|
||||
* @param processedInputs The list of {@link TransformationResult.ProcessedInput} instances.
|
||||
* @param processedInputs The list of {@link ExportResult.ProcessedInput} instances.
|
||||
* @return A {@link JSONArray} containing {@link JSONObject} instances representing the {@link
|
||||
* TransformationResult.ProcessedInput} instances.
|
||||
* ExportResult.ProcessedInput} instances.
|
||||
*/
|
||||
public static JSONArray processedInputsAsJsonArray(
|
||||
ImmutableList<TransformationResult.ProcessedInput> processedInputs) throws JSONException {
|
||||
ImmutableList<ExportResult.ProcessedInput> processedInputs) throws JSONException {
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (int i = 0; i < processedInputs.size(); i++) {
|
||||
TransformationResult.ProcessedInput processedInput = processedInputs.get(i);
|
||||
ExportResult.ProcessedInput processedInput = processedInputs.get(i);
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
@Nullable
|
||||
MediaItem.LocalConfiguration localConfiguration = processedInput.mediaItem.localConfiguration;
|
||||
|
@ -25,14 +25,14 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/** A test only class for holding the details of a test transformation. */
|
||||
public class TransformationTestResult {
|
||||
/** A test only class for holding the details of a test export. */
|
||||
public class ExportTestResult {
|
||||
/** Represents an unset or unknown SSIM score. */
|
||||
public static final double SSIM_UNSET = -1.0d;
|
||||
|
||||
/** A builder for {@link TransformationTestResult}. */
|
||||
/** A builder for {@link ExportTestResult}. */
|
||||
public static class Builder {
|
||||
private final TransformationResult transformationResult;
|
||||
private final ExportResult exportResult;
|
||||
|
||||
@Nullable private String filePath;
|
||||
private long elapsedTimeMs;
|
||||
@ -41,8 +41,8 @@ public class TransformationTestResult {
|
||||
@Nullable private Exception analysisException;
|
||||
|
||||
/** Creates a new {@link Builder}. */
|
||||
public Builder(TransformationResult transformationResult) {
|
||||
this.transformationResult = transformationResult;
|
||||
public Builder(ExportResult exportResult) {
|
||||
this.exportResult = exportResult;
|
||||
this.elapsedTimeMs = C.TIME_UNSET;
|
||||
this.ssim = SSIM_UNSET;
|
||||
}
|
||||
@ -62,8 +62,8 @@ public class TransformationTestResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amount of time taken to perform the transformation in milliseconds. {@link
|
||||
* C#TIME_UNSET} if unset.
|
||||
* Sets the amount of time taken to perform the export in milliseconds. {@link C#TIME_UNSET} if
|
||||
* unset.
|
||||
*
|
||||
* <p>{@link C#TIME_UNSET} represents an unset or unknown value.
|
||||
*
|
||||
@ -92,7 +92,7 @@ public class TransformationTestResult {
|
||||
|
||||
/**
|
||||
* Sets an {@link FallbackDetails} object that describes the fallbacks that occurred during
|
||||
* post-transformation analysis.
|
||||
* post-export analysis.
|
||||
*
|
||||
* <p>{@code null} represents no fallback was applied.
|
||||
*
|
||||
@ -106,7 +106,7 @@ public class TransformationTestResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an {@link Exception} that occurred during post-transformation analysis.
|
||||
* Sets an {@link Exception} that occurred during post-export analysis.
|
||||
*
|
||||
* <p>{@code null} represents an unset or unknown value.
|
||||
*
|
||||
@ -119,20 +119,20 @@ public class TransformationTestResult {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds the {@link TransformationTestResult} instance. */
|
||||
public TransformationTestResult build() {
|
||||
return new TransformationTestResult(
|
||||
transformationResult, filePath, elapsedTimeMs, ssim, fallbackDetails, analysisException);
|
||||
/** Builds the {@link ExportTestResult} instance. */
|
||||
public ExportTestResult build() {
|
||||
return new ExportTestResult(
|
||||
exportResult, filePath, elapsedTimeMs, ssim, fallbackDetails, analysisException);
|
||||
}
|
||||
}
|
||||
|
||||
/** The {@link TransformationResult} of the transformation. */
|
||||
public final TransformationResult transformationResult;
|
||||
/** The path to the file created in the transformation, or {@code null} if unset. */
|
||||
/** The {@link ExportResult} of the export. */
|
||||
public final ExportResult exportResult;
|
||||
/** The path to the file created in the export, or {@code null} if unset. */
|
||||
@Nullable public final String filePath;
|
||||
/**
|
||||
* The amount of time taken to perform the transformation in milliseconds, or {@link C#TIME_UNSET}
|
||||
* if unset.
|
||||
* The amount of time taken to perform the export in milliseconds, or {@link C#TIME_UNSET} if
|
||||
* unset.
|
||||
*/
|
||||
public final long elapsedTimeMs;
|
||||
/**
|
||||
@ -140,16 +140,16 @@ public class TransformationTestResult {
|
||||
* C#RATE_UNSET} if unset.
|
||||
*/
|
||||
public final float throughputFps;
|
||||
/** The SSIM score of the transformation, or {@link #SSIM_UNSET} if unset. */
|
||||
/** The SSIM score of the export, or {@link #SSIM_UNSET} if unset. */
|
||||
public final double ssim;
|
||||
/**
|
||||
* The {@link FallbackDetails} describing the fallbacks that occurred doing transformation, or
|
||||
* {@code null} if no fallback occurred.
|
||||
* The {@link FallbackDetails} describing the fallbacks that occurred doing export, or {@code
|
||||
* null} if no fallback occurred.
|
||||
*/
|
||||
@Nullable public final FallbackDetails fallbackDetails;
|
||||
/**
|
||||
* The {@link Exception} thrown during post-transformation analysis, or {@code null} if nothing
|
||||
* was thrown.
|
||||
* The {@link Exception} thrown during post-export analysis, or {@code null} if nothing was
|
||||
* thrown.
|
||||
*/
|
||||
@Nullable public final Exception analysisException;
|
||||
|
||||
@ -157,80 +157,77 @@ public class TransformationTestResult {
|
||||
public JSONObject asJsonObject() throws JSONException {
|
||||
JSONObject jsonObject =
|
||||
new JSONObject()
|
||||
.putOpt("audioEncoderName", transformationResult.audioEncoderName)
|
||||
.putOpt("audioEncoderName", exportResult.audioEncoderName)
|
||||
.putOpt(
|
||||
"fallbackDetails", fallbackDetails != null ? fallbackDetails.asJsonObject() : null)
|
||||
.putOpt("filePath", filePath)
|
||||
.putOpt("colorInfo", transformationResult.colorInfo)
|
||||
.putOpt("videoEncoderName", transformationResult.videoEncoderName)
|
||||
.putOpt(
|
||||
"testException",
|
||||
exceptionAsJsonObject(transformationResult.transformationException))
|
||||
.putOpt("colorInfo", exportResult.colorInfo)
|
||||
.putOpt("videoEncoderName", exportResult.videoEncoderName)
|
||||
.putOpt("testException", exceptionAsJsonObject(exportResult.transformationException))
|
||||
.putOpt("analysisException", exceptionAsJsonObject(analysisException));
|
||||
|
||||
if (!transformationResult.processedInputs.isEmpty()) {
|
||||
jsonObject.put(
|
||||
"processedInputs", processedInputsAsJsonArray(transformationResult.processedInputs));
|
||||
if (!exportResult.processedInputs.isEmpty()) {
|
||||
jsonObject.put("processedInputs", processedInputsAsJsonArray(exportResult.processedInputs));
|
||||
}
|
||||
|
||||
if (transformationResult.averageAudioBitrate != C.RATE_UNSET_INT) {
|
||||
jsonObject.put("averageAudioBitrate", transformationResult.averageAudioBitrate);
|
||||
if (exportResult.averageAudioBitrate != C.RATE_UNSET_INT) {
|
||||
jsonObject.put("averageAudioBitrate", exportResult.averageAudioBitrate);
|
||||
}
|
||||
if (transformationResult.averageVideoBitrate != C.RATE_UNSET_INT) {
|
||||
jsonObject.put("averageVideoBitrate", transformationResult.averageVideoBitrate);
|
||||
if (exportResult.averageVideoBitrate != C.RATE_UNSET_INT) {
|
||||
jsonObject.put("averageVideoBitrate", exportResult.averageVideoBitrate);
|
||||
}
|
||||
if (transformationResult.channelCount != C.LENGTH_UNSET) {
|
||||
jsonObject.put("channelCount", transformationResult.channelCount);
|
||||
if (exportResult.channelCount != C.LENGTH_UNSET) {
|
||||
jsonObject.put("channelCount", exportResult.channelCount);
|
||||
}
|
||||
if (transformationResult.durationMs != C.TIME_UNSET) {
|
||||
jsonObject.put("durationMs", transformationResult.durationMs);
|
||||
if (exportResult.durationMs != C.TIME_UNSET) {
|
||||
jsonObject.put("durationMs", exportResult.durationMs);
|
||||
}
|
||||
if (elapsedTimeMs != C.TIME_UNSET) {
|
||||
jsonObject.put("elapsedTimeMs", elapsedTimeMs);
|
||||
}
|
||||
if (transformationResult.fileSizeBytes != C.LENGTH_UNSET) {
|
||||
jsonObject.put("fileSizeBytes", transformationResult.fileSizeBytes);
|
||||
if (exportResult.fileSizeBytes != C.LENGTH_UNSET) {
|
||||
jsonObject.put("fileSizeBytes", exportResult.fileSizeBytes);
|
||||
}
|
||||
if (transformationResult.height != C.LENGTH_UNSET) {
|
||||
jsonObject.put("height", transformationResult.height);
|
||||
if (exportResult.height != C.LENGTH_UNSET) {
|
||||
jsonObject.put("height", exportResult.height);
|
||||
}
|
||||
if (transformationResult.pcmEncoding != Format.NO_VALUE) {
|
||||
jsonObject.put("pcmEncoding", transformationResult.pcmEncoding);
|
||||
if (exportResult.pcmEncoding != Format.NO_VALUE) {
|
||||
jsonObject.put("pcmEncoding", exportResult.pcmEncoding);
|
||||
}
|
||||
if (transformationResult.sampleRate != C.RATE_UNSET_INT) {
|
||||
jsonObject.put("sampleRate", transformationResult.sampleRate);
|
||||
if (exportResult.sampleRate != C.RATE_UNSET_INT) {
|
||||
jsonObject.put("sampleRate", exportResult.sampleRate);
|
||||
}
|
||||
if (ssim != TransformationTestResult.SSIM_UNSET) {
|
||||
if (ssim != ExportTestResult.SSIM_UNSET) {
|
||||
jsonObject.put("ssim", ssim);
|
||||
}
|
||||
if (throughputFps != C.RATE_UNSET) {
|
||||
jsonObject.put("throughputFps", throughputFps);
|
||||
}
|
||||
if (transformationResult.videoFrameCount > 0) {
|
||||
jsonObject.put("videoFrameCount", transformationResult.videoFrameCount);
|
||||
if (exportResult.videoFrameCount > 0) {
|
||||
jsonObject.put("videoFrameCount", exportResult.videoFrameCount);
|
||||
}
|
||||
if (transformationResult.width != C.LENGTH_UNSET) {
|
||||
jsonObject.put("width", transformationResult.width);
|
||||
if (exportResult.width != C.LENGTH_UNSET) {
|
||||
jsonObject.put("width", exportResult.width);
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
private TransformationTestResult(
|
||||
TransformationResult transformationResult,
|
||||
private ExportTestResult(
|
||||
ExportResult exportResult,
|
||||
@Nullable String filePath,
|
||||
long elapsedTimeMs,
|
||||
double ssim,
|
||||
@Nullable FallbackDetails fallbackDetails,
|
||||
@Nullable Exception analysisException) {
|
||||
this.transformationResult = transformationResult;
|
||||
this.exportResult = exportResult;
|
||||
this.filePath = filePath;
|
||||
this.elapsedTimeMs = elapsedTimeMs;
|
||||
this.ssim = ssim;
|
||||
this.fallbackDetails = fallbackDetails;
|
||||
this.analysisException = analysisException;
|
||||
this.throughputFps =
|
||||
elapsedTimeMs != C.TIME_UNSET && transformationResult.videoFrameCount > 0
|
||||
? 1000f * transformationResult.videoFrameCount / elapsedTimeMs
|
||||
elapsedTimeMs != C.TIME_UNSET && exportResult.videoFrameCount > 0
|
||||
? 1000f * exportResult.videoFrameCount / elapsedTimeMs
|
||||
: C.RATE_UNSET;
|
||||
}
|
||||
}
|
@ -174,36 +174,34 @@ public class TransformerAndroidTestRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the {@link EditedMediaItem}, saving a summary of the transformation to the
|
||||
* application cache.
|
||||
* Exports the {@link EditedMediaItem}, saving a summary of the export to the application cache.
|
||||
*
|
||||
* @param testId A unique identifier for the transformer test run.
|
||||
* @param editedMediaItem The {@link EditedMediaItem} to transform.
|
||||
* @return The {@link TransformationTestResult}.
|
||||
* @throws Exception The cause of the transformation not completing.
|
||||
* @param editedMediaItem The {@link EditedMediaItem} to export.
|
||||
* @return The {@link ExportTestResult}.
|
||||
* @throws Exception The cause of the export not completing.
|
||||
*/
|
||||
public TransformationTestResult run(String testId, EditedMediaItem editedMediaItem)
|
||||
throws Exception {
|
||||
public ExportTestResult run(String testId, EditedMediaItem editedMediaItem) throws Exception {
|
||||
JSONObject resultJson = new JSONObject();
|
||||
if (inputValues != null) {
|
||||
resultJson.put("inputValues", JSONObject.wrap(inputValues));
|
||||
}
|
||||
try {
|
||||
TransformationTestResult transformationTestResult = runInternal(testId, editedMediaItem);
|
||||
resultJson.put("transformationResult", transformationTestResult.asJsonObject());
|
||||
if (transformationTestResult.transformationResult.transformationException != null) {
|
||||
throw transformationTestResult.transformationResult.transformationException;
|
||||
ExportTestResult exportTestResult = runInternal(testId, editedMediaItem);
|
||||
resultJson.put("exportResult", exportTestResult.asJsonObject());
|
||||
if (exportTestResult.exportResult.transformationException != null) {
|
||||
throw exportTestResult.exportResult.transformationException;
|
||||
}
|
||||
if (!suppressAnalysisExceptions && transformationTestResult.analysisException != null) {
|
||||
throw transformationTestResult.analysisException;
|
||||
if (!suppressAnalysisExceptions && exportTestResult.analysisException != null) {
|
||||
throw exportTestResult.analysisException;
|
||||
}
|
||||
return transformationTestResult;
|
||||
return exportTestResult;
|
||||
} catch (InterruptedException
|
||||
| IOException
|
||||
| TimeoutException
|
||||
| UnsupportedOperationException e) {
|
||||
resultJson.put(
|
||||
"transformationResult",
|
||||
"exportResult",
|
||||
new JSONObject().put("testException", AndroidTestUtil.exceptionAsJsonObject(e)));
|
||||
throw e;
|
||||
} finally {
|
||||
@ -212,33 +210,32 @@ public class TransformerAndroidTestRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the {@link MediaItem}, saving a summary of the transformation to the application
|
||||
* cache.
|
||||
* Exports the {@link MediaItem}, saving a summary of the export to the application cache.
|
||||
*
|
||||
* @param testId A unique identifier for the transformer test run.
|
||||
* @param mediaItem The {@link MediaItem} to transform.
|
||||
* @return The {@link TransformationTestResult}.
|
||||
* @throws Exception The cause of the transformation not completing.
|
||||
* @param mediaItem The {@link MediaItem} to export.
|
||||
* @return The {@link ExportTestResult}.
|
||||
* @throws Exception The cause of the export not completing.
|
||||
*/
|
||||
public TransformationTestResult run(String testId, MediaItem mediaItem) throws Exception {
|
||||
public ExportTestResult run(String testId, MediaItem mediaItem) throws Exception {
|
||||
EditedMediaItem editedMediaItem = new EditedMediaItem.Builder(mediaItem).build();
|
||||
return run(testId, editedMediaItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the {@link EditedMediaItem}.
|
||||
* Exports the {@link EditedMediaItem}.
|
||||
*
|
||||
* @param testId An identifier for the test.
|
||||
* @param editedMediaItem The {@link EditedMediaItem} to transform.
|
||||
* @return The {@link TransformationTestResult}.
|
||||
* @param editedMediaItem The {@link EditedMediaItem} to export.
|
||||
* @return The {@link ExportTestResult}.
|
||||
* @throws IllegalStateException See {@link Transformer#start(EditedMediaItem, String)}.
|
||||
* @throws InterruptedException If the thread is interrupted whilst waiting for transformer to
|
||||
* complete.
|
||||
* @throws IOException If an error occurs opening the output file for writing.
|
||||
* @throws TimeoutException If the transformation has not completed after {@linkplain
|
||||
* @throws TimeoutException If the export has not completed after {@linkplain
|
||||
* Builder#setTimeoutSeconds(int) the given timeout}.
|
||||
*/
|
||||
private TransformationTestResult runInternal(String testId, EditedMediaItem editedMediaItem)
|
||||
private ExportTestResult runInternal(String testId, EditedMediaItem editedMediaItem)
|
||||
throws InterruptedException, IOException, TimeoutException {
|
||||
MediaItem mediaItem = editedMediaItem.mediaItem;
|
||||
if (!mediaItem.clippingConfiguration.equals(MediaItem.ClippingConfiguration.UNSET)
|
||||
@ -258,8 +255,7 @@ public class TransformerAndroidTestRunner {
|
||||
AtomicReference<@NullableType FallbackDetails> fallbackDetailsReference =
|
||||
new AtomicReference<>();
|
||||
AtomicReference<@NullableType Exception> unexpectedExceptionReference = new AtomicReference<>();
|
||||
AtomicReference<@NullableType TransformationResult> transformationResultReference =
|
||||
new AtomicReference<>();
|
||||
AtomicReference<@NullableType ExportResult> exportResultReference = new AtomicReference<>();
|
||||
CountDownLatch countDownLatch = new CountDownLatch(1);
|
||||
long startTimeMs = SystemClock.DEFAULT.elapsedRealtime();
|
||||
|
||||
@ -269,18 +265,17 @@ public class TransformerAndroidTestRunner {
|
||||
.addListener(
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(
|
||||
MediaItem inputMediaItem, TransformationResult result) {
|
||||
transformationResultReference.set(result);
|
||||
public void onCompleted(Composition composition, ExportResult exportResult) {
|
||||
exportResultReference.set(exportResult);
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransformationError(
|
||||
MediaItem inputMediaItem,
|
||||
TransformationResult result,
|
||||
public void onError(
|
||||
Composition composition,
|
||||
ExportResult exportResult,
|
||||
TransformationException exception) {
|
||||
transformationResultReference.set(result);
|
||||
exportResultReference.set(exportResult);
|
||||
countDownLatch.countDown();
|
||||
}
|
||||
|
||||
@ -333,19 +328,19 @@ public class TransformerAndroidTestRunner {
|
||||
|
||||
long elapsedTimeMs = SystemClock.DEFAULT.elapsedRealtime() - startTimeMs;
|
||||
@Nullable FallbackDetails fallbackDetails = fallbackDetailsReference.get();
|
||||
TransformationResult transformationResult = checkNotNull(transformationResultReference.get());
|
||||
ExportResult exportResult = checkNotNull(exportResultReference.get());
|
||||
|
||||
if (transformationResult.transformationException != null) {
|
||||
return new TransformationTestResult.Builder(transformationResult)
|
||||
if (exportResult.transformationException != null) {
|
||||
return new ExportTestResult.Builder(exportResult)
|
||||
.setElapsedTimeMs(elapsedTimeMs)
|
||||
.setFallbackDetails(fallbackDetails)
|
||||
.build();
|
||||
}
|
||||
|
||||
// No exceptions raised, transformation has succeeded.
|
||||
TransformationTestResult.Builder testResultBuilder =
|
||||
new TransformationTestResult.Builder(
|
||||
checkNotNull(transformationResultReference.get())
|
||||
ExportTestResult.Builder testResultBuilder =
|
||||
new ExportTestResult.Builder(
|
||||
checkNotNull(exportResultReference.get())
|
||||
.buildUpon()
|
||||
.setFileSizeBytes(outputVideoFile.length())
|
||||
.build())
|
||||
@ -373,7 +368,7 @@ public class TransformerAndroidTestRunner {
|
||||
} 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
|
||||
// TransformationTestResult.
|
||||
// ExportTestResult.
|
||||
throw interruptedException;
|
||||
} catch (Throwable analysisFailure) {
|
||||
if (Util.SDK_INT == 21 && Ascii.toLowerCase(Util.MODEL).contains("nexus")) {
|
||||
@ -381,7 +376,7 @@ public class TransformerAndroidTestRunner {
|
||||
Log.i(TAG, testId + ": Skipping SSIM calculation due to known device-specific issue");
|
||||
} else {
|
||||
// Catch all (checked and unchecked) failures thrown by the SsimHelper and process them as
|
||||
// part of the TransformationTestResult.
|
||||
// part of the ExportTestResult.
|
||||
Exception analysisException =
|
||||
analysisFailure instanceof Exception
|
||||
? (Exception) analysisFailure
|
||||
|
@ -53,12 +53,12 @@ public class TransformerAudioEndToEndTest {
|
||||
.setEffects(effects)
|
||||
.build();
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build())
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
assertThat(result.transformationResult.channelCount).isEqualTo(2);
|
||||
assertThat(result.exportResult.channelCount).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -76,12 +76,12 @@ public class TransformerAudioEndToEndTest {
|
||||
.setEffects(effects)
|
||||
.build();
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build())
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
assertThat(result.transformationResult.pcmEncoding).isEqualTo(C.ENCODING_PCM_FLOAT);
|
||||
assertThat(result.exportResult.pcmEncoding).isEqualTo(C.ENCODING_PCM_FLOAT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -100,12 +100,12 @@ public class TransformerAudioEndToEndTest {
|
||||
.setEffects(effects)
|
||||
.build();
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build())
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
assertThat(result.transformationResult.pcmEncoding).isEqualTo(C.ENCODING_PCM_16BIT);
|
||||
assertThat(result.exportResult.pcmEncoding).isEqualTo(C.ENCODING_PCM_16BIT);
|
||||
}
|
||||
|
||||
private static Effects createForAudioProcessors(AudioProcessor... audioProcessors) {
|
||||
|
@ -57,12 +57,12 @@ public class TransformerEndToEndTest {
|
||||
// ffprobe -count_frames -select_streams v:0 -show_entries stream=nb_read_frames sample.mp4
|
||||
int expectedFrameCount = 30;
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(/* testId= */ "videoEditing_completesWithConsistentFrameCount", editedMediaItem);
|
||||
|
||||
assertThat(result.transformationResult.videoFrameCount).isEqualTo(expectedFrameCount);
|
||||
assertThat(result.exportResult.videoFrameCount).isEqualTo(expectedFrameCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -79,12 +79,12 @@ public class TransformerEndToEndTest {
|
||||
new EditedMediaItem.Builder(mediaItem).setRemoveAudio(true).setEffects(effects).build();
|
||||
long expectedDurationMs = 967;
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(/* testId= */ "videoOnly_completesWithConsistentDuration", editedMediaItem);
|
||||
|
||||
assertThat(result.transformationResult.durationMs).isEqualTo(expectedDurationMs);
|
||||
assertThat(result.exportResult.durationMs).isEqualTo(expectedDurationMs);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -102,12 +102,12 @@ public class TransformerEndToEndTest {
|
||||
.build())
|
||||
.build();
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(/* testId= */ "clippedMedia_completesWithClippedDuration", mediaItem);
|
||||
|
||||
assertThat(result.transformationResult.durationMs).isAtMost(clippingEndMs - clippingStartMs);
|
||||
assertThat(result.exportResult.durationMs).isAtMost(clippingEndMs - clippingStartMs);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -27,9 +27,9 @@ 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.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.TransformationTestResult;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@ -69,11 +69,11 @@ public class ForceInterpretHdrVideoAsSdrTest {
|
||||
.build();
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_4_SECOND_HDR10));
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
Log.i(TAG, "Transformed.");
|
||||
} catch (TransformationException exception) {
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
|
||||
@ -106,11 +106,11 @@ public class ForceInterpretHdrVideoAsSdrTest {
|
||||
.build();
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_5_SECOND_HLG10));
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
Log.i(TAG, "Transformed.");
|
||||
} catch (TransformationException exception) {
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED
|
||||
|
@ -36,9 +36,9 @@ import androidx.media3.effect.ScaleToFitTransformation;
|
||||
import androidx.media3.transformer.EditedMediaItem;
|
||||
import androidx.media3.transformer.Effects;
|
||||
import androidx.media3.transformer.EncoderUtil;
|
||||
import androidx.media3.transformer.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.TransformationTestResult;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@ -77,12 +77,12 @@ public class HdrEditingTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_4_SECOND_HDR10));
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Transformed.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_ST2084);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_ST2084);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
@ -102,12 +102,12 @@ public class HdrEditingTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_5_SECOND_HLG10));
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Transformed.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_HLG);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_HLG);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
@ -136,11 +136,11 @@ public class HdrEditingTest {
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
|
||||
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_ST2084);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_ST2084);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -161,11 +161,11 @@ public class HdrEditingTest {
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
|
||||
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_HLG);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_HLG);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -206,13 +206,13 @@ public class HdrEditingTest {
|
||||
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
@ -260,13 +260,13 @@ public class HdrEditingTest {
|
||||
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertThat(isToneMappingFallbackApplied.get()).isTrue();
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
|
@ -26,8 +26,8 @@ import androidx.media3.effect.ScaleToFitTransformation;
|
||||
import androidx.media3.transformer.AndroidTestUtil;
|
||||
import androidx.media3.transformer.EditedMediaItem;
|
||||
import androidx.media3.transformer.Effects;
|
||||
import androidx.media3.transformer.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.TransformationTestResult;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@ -65,10 +65,10 @@ public final class RepeatedTranscodeTest {
|
||||
Set<Long> differentOutputSizesBytes = new HashSet<>();
|
||||
for (int i = 0; i < TRANSCODE_COUNT; i++) {
|
||||
// Use a long video in case an error occurs a while after the start of the video.
|
||||
TransformationTestResult testResult =
|
||||
ExportTestResult testResult =
|
||||
transformerRunner.run(
|
||||
/* testId= */ "repeatedTranscode_givesConsistentLengthOutput_" + i, editedMediaItem);
|
||||
differentOutputSizesBytes.add(checkNotNull(testResult.transformationResult.fileSizeBytes));
|
||||
differentOutputSizesBytes.add(checkNotNull(testResult.exportResult.fileSizeBytes));
|
||||
}
|
||||
|
||||
assertWithMessage(
|
||||
@ -98,11 +98,11 @@ public final class RepeatedTranscodeTest {
|
||||
Set<Long> differentOutputSizesBytes = new HashSet<>();
|
||||
for (int i = 0; i < TRANSCODE_COUNT; i++) {
|
||||
// Use a long video in case an error occurs a while after the start of the video.
|
||||
TransformationTestResult testResult =
|
||||
ExportTestResult testResult =
|
||||
transformerRunner.run(
|
||||
/* testId= */ "repeatedTranscodeNoAudio_givesConsistentLengthOutput_" + i,
|
||||
editedMediaItem);
|
||||
differentOutputSizesBytes.add(checkNotNull(testResult.transformationResult.fileSizeBytes));
|
||||
differentOutputSizesBytes.add(checkNotNull(testResult.exportResult.fileSizeBytes));
|
||||
}
|
||||
|
||||
assertWithMessage(
|
||||
@ -130,11 +130,11 @@ public final class RepeatedTranscodeTest {
|
||||
Set<Long> differentOutputSizesBytes = new HashSet<>();
|
||||
for (int i = 0; i < TRANSCODE_COUNT; i++) {
|
||||
// Use a long video in case an error occurs a while after the start of the video.
|
||||
TransformationTestResult testResult =
|
||||
ExportTestResult testResult =
|
||||
transformerRunner.run(
|
||||
/* testId= */ "repeatedTranscodeNoVideo_givesConsistentLengthOutput_" + i,
|
||||
editedMediaItem);
|
||||
differentOutputSizesBytes.add(checkNotNull(testResult.transformationResult.fileSizeBytes));
|
||||
differentOutputSizesBytes.add(checkNotNull(testResult.exportResult.fileSizeBytes));
|
||||
}
|
||||
|
||||
assertWithMessage(
|
||||
|
@ -30,9 +30,9 @@ 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.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.TransformationTestResult;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@ -78,12 +78,12 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_4_SECOND_HDR10));
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
@ -120,12 +120,12 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_5_SECOND_HLG10));
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
@ -167,12 +167,12 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
@ -214,12 +214,12 @@ public class ToneMapHdrToSdrUsingMediaCodecTest {
|
||||
new EditedMediaItem.Builder(mediaItem).setEffects(effects).build();
|
||||
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
assertThat(exception).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
|
||||
|
@ -32,9 +32,9 @@ 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.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationException;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.TransformationTestResult;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
@ -87,12 +87,12 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
|
||||
.build();
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_5_SECOND_HLG10));
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
@ -138,12 +138,12 @@ public class ToneMapHdrToSdrUsingOpenGlTest {
|
||||
.build();
|
||||
MediaItem mediaItem = MediaItem.fromUri(Uri.parse(MP4_ASSET_1080P_4_SECOND_HDR10));
|
||||
try {
|
||||
TransformationTestResult transformationTestResult =
|
||||
ExportTestResult exportTestResult =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.build()
|
||||
.run(testId, mediaItem);
|
||||
Log.i(TAG, "Tone mapped.");
|
||||
assertFileHasColorTransfer(transformationTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
assertFileHasColorTransfer(exportTestResult.filePath, C.COLOR_TRANSFER_SDR);
|
||||
} catch (TransformationException exception) {
|
||||
Log.i(TAG, checkNotNull(exception.getCause()).toString());
|
||||
if (exception.errorCode != TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED) {
|
||||
|
@ -25,8 +25,8 @@ import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.transformer.AndroidTestUtil;
|
||||
import androidx.media3.transformer.DefaultEncoderFactory;
|
||||
import androidx.media3.transformer.EditedMediaItem;
|
||||
import androidx.media3.transformer.ExportTestResult;
|
||||
import androidx.media3.transformer.TransformationRequest;
|
||||
import androidx.media3.transformer.TransformationTestResult;
|
||||
import androidx.media3.transformer.Transformer;
|
||||
import androidx.media3.transformer.TransformerAndroidTestRunner;
|
||||
import androidx.media3.transformer.VideoEncoderSettings;
|
||||
@ -70,13 +70,13 @@ public final class TranscodeQualityTest {
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(mediaItem).setRemoveAudio(true).build();
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.setRequestCalculateSsim(true)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
if (result.ssim != TransformationTestResult.SSIM_UNSET) {
|
||||
if (result.ssim != ExportTestResult.SSIM_UNSET) {
|
||||
assertThat(result.ssim).isGreaterThan(0.90);
|
||||
}
|
||||
}
|
||||
@ -108,13 +108,13 @@ public final class TranscodeQualityTest {
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(mediaItem).setRemoveAudio(true).build();
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.setRequestCalculateSsim(true)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
if (result.ssim != TransformationTestResult.SSIM_UNSET) {
|
||||
if (result.ssim != ExportTestResult.SSIM_UNSET) {
|
||||
assertThat(result.ssim).isGreaterThan(0.90);
|
||||
}
|
||||
}
|
||||
@ -140,13 +140,13 @@ public final class TranscodeQualityTest {
|
||||
EditedMediaItem editedMediaItem =
|
||||
new EditedMediaItem.Builder(mediaItem).setRemoveAudio(true).build();
|
||||
|
||||
TransformationTestResult result =
|
||||
ExportTestResult result =
|
||||
new TransformerAndroidTestRunner.Builder(context, transformer)
|
||||
.setRequestCalculateSsim(true)
|
||||
.build()
|
||||
.run(testId, editedMediaItem);
|
||||
|
||||
if (result.ssim != TransformationTestResult.SSIM_UNSET) {
|
||||
if (result.ssim != ExportTestResult.SSIM_UNSET) {
|
||||
assertThat(result.ssim).isGreaterThan(0.90);
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ import static androidx.media3.transformer.AndroidTestUtil.MP4_REMOTE_854W_480H_3
|
||||
import static androidx.media3.transformer.AndroidTestUtil.MP4_REMOTE_854W_480H_30_SECOND_ROOF_REDMINOTE9_DOWNSAMPLED;
|
||||
import static androidx.media3.transformer.AndroidTestUtil.getFormatForTestFile;
|
||||
import static androidx.media3.transformer.AndroidTestUtil.skipAndLogIfInsufficientCodecSupport;
|
||||
import static androidx.media3.transformer.TransformationTestResult.SSIM_UNSET;
|
||||
import static androidx.media3.transformer.ExportTestResult.SSIM_UNSET;
|
||||
import static com.google.common.collect.Iterables.getLast;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -54,7 +54,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
private final Listener compositeAssetLoaderListener;
|
||||
private final Map<Integer, SampleConsumer> sampleConsumersByTrackType;
|
||||
private final Map<Integer, OnMediaItemChangedListener> mediaItemChangedListenersByTrackType;
|
||||
private final ImmutableList.Builder<TransformationResult.ProcessedInput> processedInputsBuilder;
|
||||
private final ImmutableList.Builder<ExportResult.ProcessedInput> processedInputsBuilder;
|
||||
private final AtomicLong totalDurationUs;
|
||||
private final AtomicInteger nonEndedTracks;
|
||||
|
||||
@ -114,10 +114,9 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the partially or entirely {@linkplain TransformationResult.ProcessedInput processed
|
||||
* inputs}.
|
||||
* Returns the partially or entirely {@linkplain ExportResult.ProcessedInput processed inputs}.
|
||||
*/
|
||||
public ImmutableList<TransformationResult.ProcessedInput> getProcessedInputs() {
|
||||
public ImmutableList<ExportResult.ProcessedInput> getProcessedInputs() {
|
||||
addCurrentProcessedInput();
|
||||
return processedInputsBuilder.build();
|
||||
}
|
||||
@ -212,7 +211,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
MediaItem mediaItem = editedMediaItems.get(currentMediaItemIndex).mediaItem;
|
||||
ImmutableMap<Integer, String> decoders = currentAssetLoader.getDecoderNames();
|
||||
processedInputsBuilder.add(
|
||||
new TransformationResult.ProcessedInput(
|
||||
new ExportResult.ProcessedInput(
|
||||
mediaItem, decoders.get(C.TRACK_TYPE_AUDIO), decoders.get(C.TRACK_TYPE_VIDEO)));
|
||||
processedInputsSize++;
|
||||
}
|
||||
|
@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright 2022 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 androidx.media3.common.util.Assertions.checkArgument;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.ColorInfo;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import java.util.Objects;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/** Information about the result of an export. */
|
||||
@UnstableApi
|
||||
public final class ExportResult {
|
||||
/** A builder for {@link ExportResult} instances. */
|
||||
public static final class Builder {
|
||||
private ImmutableList<ProcessedInput> processedInputs;
|
||||
private long durationMs;
|
||||
private long fileSizeBytes;
|
||||
private int averageAudioBitrate;
|
||||
private int channelCount;
|
||||
private @C.PcmEncoding int pcmEncoding;
|
||||
private int sampleRate;
|
||||
@Nullable private String audioEncoderName;
|
||||
private int averageVideoBitrate;
|
||||
@Nullable ColorInfo colorInfo;
|
||||
private int height;
|
||||
private int width;
|
||||
private int videoFrameCount;
|
||||
@Nullable private String videoEncoderName;
|
||||
@Nullable private TransformationException transformationException;
|
||||
|
||||
/** Creates a builder. */
|
||||
public Builder() {
|
||||
processedInputs = ImmutableList.of();
|
||||
durationMs = C.TIME_UNSET;
|
||||
fileSizeBytes = C.LENGTH_UNSET;
|
||||
averageAudioBitrate = C.RATE_UNSET_INT;
|
||||
channelCount = C.LENGTH_UNSET;
|
||||
pcmEncoding = Format.NO_VALUE;
|
||||
sampleRate = C.RATE_UNSET_INT;
|
||||
averageVideoBitrate = C.RATE_UNSET_INT;
|
||||
height = C.LENGTH_UNSET;
|
||||
width = C.LENGTH_UNSET;
|
||||
}
|
||||
|
||||
/** Sets the {@linkplain ProcessedInput processed inputs}. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setProcessedInputs(ImmutableList<ProcessedInput> processedInputs) {
|
||||
this.processedInputs = processedInputs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the duration of the output in milliseconds.
|
||||
*
|
||||
* <p>Must be positive or {@link C#TIME_UNSET}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setDurationMs(long durationMs) {
|
||||
checkArgument(durationMs >= 0 || durationMs == C.TIME_UNSET);
|
||||
this.durationMs = durationMs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file size in bytes.
|
||||
*
|
||||
* <p>Must be positive or {@link C#LENGTH_UNSET}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setFileSizeBytes(long fileSizeBytes) {
|
||||
checkArgument(fileSizeBytes > 0 || fileSizeBytes == C.LENGTH_UNSET);
|
||||
this.fileSizeBytes = fileSizeBytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the average audio bitrate.
|
||||
*
|
||||
* <p>Must be positive or {@link C#RATE_UNSET_INT}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setAverageAudioBitrate(int averageAudioBitrate) {
|
||||
checkArgument(averageAudioBitrate > 0 || averageAudioBitrate == C.RATE_UNSET_INT);
|
||||
this.averageAudioBitrate = averageAudioBitrate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the channel count.
|
||||
*
|
||||
* <p>Must be positive or {@link C#LENGTH_UNSET}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setChannelCount(int channelCount) {
|
||||
checkArgument(channelCount > 0 || channelCount == C.LENGTH_UNSET);
|
||||
this.channelCount = channelCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the {@link C.PcmEncoding}. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setPcmEncoding(@C.PcmEncoding int pcmEncoding) {
|
||||
this.pcmEncoding = pcmEncoding;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample rate.
|
||||
*
|
||||
* <p>Must be positive or {@link C#RATE_UNSET_INT}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setSampleRate(int sampleRate) {
|
||||
checkArgument(sampleRate > 0 || sampleRate == C.RATE_UNSET_INT);
|
||||
this.sampleRate = sampleRate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the name of the audio encoder used. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setAudioEncoderName(@Nullable String audioEncoderName) {
|
||||
this.audioEncoderName = audioEncoderName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the average video bitrate.
|
||||
*
|
||||
* <p>Must be positive or {@link C#RATE_UNSET_INT}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setAverageVideoBitrate(int averageVideoBitrate) {
|
||||
checkArgument(averageVideoBitrate > 0 || averageVideoBitrate == C.RATE_UNSET_INT);
|
||||
this.averageVideoBitrate = averageVideoBitrate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the {@link ColorInfo}. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setColorInfo(@Nullable ColorInfo colorInfo) {
|
||||
this.colorInfo = colorInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the height.
|
||||
*
|
||||
* <p>Must be positive or {@link C#LENGTH_UNSET}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setHeight(int height) {
|
||||
checkArgument(height > 0 || height == C.LENGTH_UNSET);
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width.
|
||||
*
|
||||
* <p>Must be positive or {@link C#LENGTH_UNSET}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setWidth(int width) {
|
||||
checkArgument(width > 0 || width == C.LENGTH_UNSET);
|
||||
this.width = width;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of video frames.
|
||||
*
|
||||
* <p>Must be positive or {@code 0}.
|
||||
*/
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setVideoFrameCount(int videoFrameCount) {
|
||||
checkArgument(videoFrameCount >= 0);
|
||||
this.videoFrameCount = videoFrameCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the name of the video encoder used. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setVideoEncoderName(@Nullable String videoEncoderName) {
|
||||
this.videoEncoderName = videoEncoderName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets the {@link TransformationException} that caused the export to fail. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setTransformationException(
|
||||
@Nullable TransformationException transformationException) {
|
||||
this.transformationException = transformationException;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds an {@link ExportResult} instance. */
|
||||
public ExportResult build() {
|
||||
return new ExportResult(
|
||||
processedInputs,
|
||||
durationMs,
|
||||
fileSizeBytes,
|
||||
averageAudioBitrate,
|
||||
channelCount,
|
||||
pcmEncoding,
|
||||
sampleRate,
|
||||
audioEncoderName,
|
||||
averageVideoBitrate,
|
||||
colorInfo,
|
||||
height,
|
||||
width,
|
||||
videoFrameCount,
|
||||
videoEncoderName,
|
||||
transformationException);
|
||||
}
|
||||
}
|
||||
|
||||
/** An input entirely or partially processed. */
|
||||
public static final class ProcessedInput {
|
||||
/** The processed {@link MediaItem}. */
|
||||
public final MediaItem mediaItem;
|
||||
/**
|
||||
* The name of the audio decoder used to process {@code mediaItem}. This field is {@code null}
|
||||
* if no audio decoder was used.
|
||||
*/
|
||||
public final @MonotonicNonNull String audioDecoderName;
|
||||
/**
|
||||
* The name of the video decoder used to process {@code mediaItem}. This field is {@code null}
|
||||
* if no video decoder was used.
|
||||
*/
|
||||
public final @MonotonicNonNull String videoDecoderName;
|
||||
|
||||
/** Creates an instance. */
|
||||
public ProcessedInput(
|
||||
MediaItem mediaItem, @Nullable String audioDecoderName, @Nullable String videoDecoderName) {
|
||||
this.mediaItem = mediaItem;
|
||||
this.audioDecoderName = audioDecoderName;
|
||||
this.videoDecoderName = videoDecoderName;
|
||||
}
|
||||
}
|
||||
|
||||
/** The list of {@linkplain ProcessedInput processed inputs}. */
|
||||
public final ImmutableList<ProcessedInput> processedInputs;
|
||||
|
||||
/** The duration of the file in milliseconds, or {@link C#TIME_UNSET} if unset or unknown. */
|
||||
public final long durationMs;
|
||||
/** The size of the file in bytes, or {@link C#LENGTH_UNSET} if unset or unknown. */
|
||||
public final long fileSizeBytes;
|
||||
|
||||
/**
|
||||
* The average bitrate of the audio track data, or {@link C#RATE_UNSET_INT} if unset or unknown.
|
||||
*/
|
||||
public final int averageAudioBitrate;
|
||||
/** The channel count of the audio, or {@link C#LENGTH_UNSET} if unset or unknown. */
|
||||
public final int channelCount;
|
||||
/** The {@link C.PcmEncoding} of the audio, or {@link Format#NO_VALUE} if unset or unknown. */
|
||||
public final @C.PcmEncoding int pcmEncoding;
|
||||
/** The sample rate of the audio, or {@link C#RATE_UNSET_INT} if unset or unknown. */
|
||||
public final int sampleRate;
|
||||
/** The name of the audio encoder used, or {@code null} if none were used. */
|
||||
@Nullable public final String audioEncoderName;
|
||||
|
||||
/**
|
||||
* The average bitrate of the video track data, or {@link C#RATE_UNSET_INT} if unset or unknown.
|
||||
*/
|
||||
public final int averageVideoBitrate;
|
||||
/** The {@link ColorInfo} of the video, or {@code null} if unset or unknown. */
|
||||
@Nullable public final ColorInfo colorInfo;
|
||||
/** The height of the video, or {@link C#LENGTH_UNSET} if unset or unknown. */
|
||||
public final int height;
|
||||
/** The width of the video, or {@link C#LENGTH_UNSET} if unset or unknown. */
|
||||
public final int width;
|
||||
/** The number of video frames. */
|
||||
public final int videoFrameCount;
|
||||
/** 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 export to fail, or {@code null} if the
|
||||
* export was a success.
|
||||
*/
|
||||
@Nullable public final TransformationException transformationException;
|
||||
|
||||
private ExportResult(
|
||||
ImmutableList<ProcessedInput> processedInputs,
|
||||
long durationMs,
|
||||
long fileSizeBytes,
|
||||
int averageAudioBitrate,
|
||||
int channelCount,
|
||||
@C.PcmEncoding int pcmEncoding,
|
||||
int sampleRate,
|
||||
@Nullable String audioEncoderName,
|
||||
int averageVideoBitrate,
|
||||
@Nullable ColorInfo colorInfo,
|
||||
int height,
|
||||
int width,
|
||||
int videoFrameCount,
|
||||
@Nullable String videoEncoderName,
|
||||
@Nullable TransformationException transformationException) {
|
||||
this.processedInputs = processedInputs;
|
||||
this.durationMs = durationMs;
|
||||
this.fileSizeBytes = fileSizeBytes;
|
||||
this.averageAudioBitrate = averageAudioBitrate;
|
||||
this.channelCount = channelCount;
|
||||
this.pcmEncoding = pcmEncoding;
|
||||
this.sampleRate = sampleRate;
|
||||
this.audioEncoderName = audioEncoderName;
|
||||
this.averageVideoBitrate = averageVideoBitrate;
|
||||
this.colorInfo = colorInfo;
|
||||
this.height = height;
|
||||
this.width = width;
|
||||
this.videoFrameCount = videoFrameCount;
|
||||
this.videoEncoderName = videoEncoderName;
|
||||
this.transformationException = transformationException;
|
||||
}
|
||||
|
||||
public Builder buildUpon() {
|
||||
return new Builder()
|
||||
.setProcessedInputs(processedInputs)
|
||||
.setDurationMs(durationMs)
|
||||
.setFileSizeBytes(fileSizeBytes)
|
||||
.setAverageAudioBitrate(averageAudioBitrate)
|
||||
.setChannelCount(channelCount)
|
||||
.setPcmEncoding(pcmEncoding)
|
||||
.setSampleRate(sampleRate)
|
||||
.setAudioEncoderName(audioEncoderName)
|
||||
.setAverageVideoBitrate(averageVideoBitrate)
|
||||
.setColorInfo(colorInfo)
|
||||
.setHeight(height)
|
||||
.setWidth(width)
|
||||
.setVideoFrameCount(videoFrameCount)
|
||||
.setVideoEncoderName(videoEncoderName)
|
||||
.setTransformationException(transformationException);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof ExportResult)) {
|
||||
return false;
|
||||
}
|
||||
ExportResult result = (ExportResult) o;
|
||||
return Objects.equals(processedInputs, result.processedInputs)
|
||||
&& durationMs == result.durationMs
|
||||
&& fileSizeBytes == result.fileSizeBytes
|
||||
&& averageAudioBitrate == result.averageAudioBitrate
|
||||
&& channelCount == result.channelCount
|
||||
&& pcmEncoding == result.pcmEncoding
|
||||
&& sampleRate == result.sampleRate
|
||||
&& Objects.equals(audioEncoderName, result.audioEncoderName)
|
||||
&& averageVideoBitrate == result.averageVideoBitrate
|
||||
&& Objects.equals(colorInfo, result.colorInfo)
|
||||
&& height == result.height
|
||||
&& width == result.width
|
||||
&& videoFrameCount == result.videoFrameCount
|
||||
&& Objects.equals(videoEncoderName, result.videoEncoderName)
|
||||
&& Objects.equals(transformationException, result.transformationException);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Objects.hashCode(processedInputs);
|
||||
result = 31 * result + (int) durationMs;
|
||||
result = 31 * result + (int) fileSizeBytes;
|
||||
result = 31 * result + averageAudioBitrate;
|
||||
result = 31 * result + channelCount;
|
||||
result = 31 * result + pcmEncoding;
|
||||
result = 31 * result + sampleRate;
|
||||
result = 31 * result + Objects.hashCode(audioEncoderName);
|
||||
result = 31 * result + averageVideoBitrate;
|
||||
result = 31 * result + Objects.hashCode(colorInfo);
|
||||
result = 31 * result + height;
|
||||
result = 31 * result + width;
|
||||
result = 31 * result + videoFrameCount;
|
||||
result = 31 * result + Objects.hashCode(videoEncoderName);
|
||||
result = 31 * result + Objects.hashCode(transformationException);
|
||||
return result;
|
||||
}
|
||||
}
|
@ -28,10 +28,16 @@ import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||
import java.util.Objects;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/** Information about the result of a transformation. */
|
||||
/**
|
||||
* @deprecated Use {@link ExportResult} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@UnstableApi
|
||||
public final class TransformationResult {
|
||||
/** A builder for {@link TransformationResult} instances. */
|
||||
/**
|
||||
* @deprecated Use {@link ExportResult.Builder} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final class Builder {
|
||||
private ImmutableList<ProcessedInput> processedInputs;
|
||||
private long durationMs;
|
||||
@ -63,6 +69,34 @@ public final class TransformationResult {
|
||||
width = C.LENGTH_UNSET;
|
||||
}
|
||||
|
||||
/** Creates a builder from an {@link ExportResult}. */
|
||||
/* package */ Builder(ExportResult exportResult) {
|
||||
ImmutableList.Builder<ProcessedInput> processedInputsBuilder = new ImmutableList.Builder<>();
|
||||
for (int i = 0; i < exportResult.processedInputs.size(); i++) {
|
||||
ExportResult.ProcessedInput processedInput = exportResult.processedInputs.get(i);
|
||||
processedInputsBuilder.add(
|
||||
new ProcessedInput(
|
||||
processedInput.mediaItem,
|
||||
processedInput.audioDecoderName,
|
||||
processedInput.videoDecoderName));
|
||||
}
|
||||
processedInputs = processedInputsBuilder.build();
|
||||
durationMs = exportResult.durationMs;
|
||||
fileSizeBytes = exportResult.fileSizeBytes;
|
||||
averageAudioBitrate = exportResult.averageAudioBitrate;
|
||||
channelCount = exportResult.channelCount;
|
||||
pcmEncoding = exportResult.pcmEncoding;
|
||||
sampleRate = exportResult.sampleRate;
|
||||
audioEncoderName = exportResult.audioEncoderName;
|
||||
averageVideoBitrate = exportResult.averageVideoBitrate;
|
||||
colorInfo = exportResult.colorInfo;
|
||||
height = exportResult.height;
|
||||
width = exportResult.width;
|
||||
videoFrameCount = exportResult.videoFrameCount;
|
||||
videoEncoderName = exportResult.videoEncoderName;
|
||||
transformationException = exportResult.transformationException;
|
||||
}
|
||||
|
||||
/** Sets the {@linkplain ProcessedInput processed inputs}. */
|
||||
@CanIgnoreReturnValue
|
||||
public Builder setProcessedInputs(ImmutableList<ProcessedInput> processedInputs) {
|
||||
@ -235,7 +269,10 @@ public final class TransformationResult {
|
||||
}
|
||||
}
|
||||
|
||||
/** An input entirely or partially processed. */
|
||||
/**
|
||||
* @deprecated Use {@link ExportResult.ProcessedInput} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final class ProcessedInput {
|
||||
/** The processed {@link MediaItem}. */
|
||||
public final MediaItem mediaItem;
|
||||
|
@ -446,13 +446,13 @@ public final class Transformer {
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onCompleted(Composition, TransformationResult)} instead.
|
||||
* @deprecated Use {@link #onCompleted(Composition, ExportResult)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationCompleted(MediaItem inputMediaItem) {}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onCompleted(Composition, TransformationResult)} instead.
|
||||
* @deprecated Use {@link #onCompleted(Composition, ExportResult)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationCompleted(MediaItem inputMediaItem, TransformationResult result) {
|
||||
@ -463,23 +463,22 @@ public final class Transformer {
|
||||
* Called when the export is completed successfully.
|
||||
*
|
||||
* @param composition The {@link Composition} for which the export is completed.
|
||||
* @param result The {@link TransformationResult} of the export.
|
||||
* @param exportResult The {@link ExportResult} of the export.
|
||||
*/
|
||||
default void onCompleted(Composition composition, TransformationResult result) {
|
||||
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
||||
default void onCompleted(Composition composition, ExportResult exportResult) {
|
||||
MediaItem mediaItem = composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
|
||||
onTransformationCompleted(mediaItem, result);
|
||||
onTransformationCompleted(mediaItem, new TransformationResult.Builder(exportResult).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onError(Composition, TransformationResult, TransformationException)}
|
||||
* instead.
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(MediaItem inputMediaItem, Exception exception) {}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onError(Composition, TransformationResult, TransformationException)}
|
||||
* instead.
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(
|
||||
@ -488,8 +487,7 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #onError(Composition, TransformationResult, TransformationException)}
|
||||
* instead.
|
||||
* @deprecated Use {@link #onError(Composition, ExportResult, TransformationException)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
default void onTransformationError(
|
||||
@ -501,15 +499,17 @@ public final class Transformer {
|
||||
* Called if an exception occurs during the export.
|
||||
*
|
||||
* @param composition The {@link Composition} for which the exception occurs.
|
||||
* @param result The {@link TransformationResult} of the export.
|
||||
* @param exportResult The {@link ExportResult} of the export.
|
||||
* @param exception The {@link TransformationException} describing the exception. This is the
|
||||
* same instance as the {@linkplain TransformationResult#transformationException exception}
|
||||
* in {@code result}.
|
||||
* same instance as the {@linkplain ExportResult#transformationException exception} in
|
||||
* {@code result}.
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
||||
default void onError(
|
||||
Composition composition, TransformationResult result, TransformationException exception) {
|
||||
Composition composition, ExportResult exportResult, TransformationException exception) {
|
||||
MediaItem mediaItem = composition.sequences.get(0).editedMediaItems.get(0).mediaItem;
|
||||
onTransformationError(mediaItem, result, exception);
|
||||
onTransformationError(
|
||||
mediaItem, new TransformationResult.Builder(exportResult).build(), exception);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -534,6 +534,7 @@ public final class Transformer {
|
||||
* TransformationRequest#videoMimeType}, {@link TransformationRequest#outputHeight}, and
|
||||
* {@link TransformationRequest#hdrMode} values set.
|
||||
*/
|
||||
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
||||
default void onFallbackApplied(
|
||||
Composition composition,
|
||||
TransformationRequest originalTransformationRequest,
|
||||
@ -792,8 +793,8 @@ public final class Transformer {
|
||||
* Returns the current {@link ProgressState} and updates {@code progressHolder} with the current
|
||||
* progress if it is {@link #PROGRESS_STATE_AVAILABLE available}.
|
||||
*
|
||||
* <p>After an export {@linkplain Listener#onCompleted(Composition,TransformationResult)
|
||||
* completes}, this method returns {@link #PROGRESS_STATE_NOT_STARTED}.
|
||||
* <p>After an export {@linkplain Listener#onCompleted(Composition, ExportResult) completes}, this
|
||||
* method returns {@link #PROGRESS_STATE_NOT_STARTED}.
|
||||
*
|
||||
* @param progressHolder A {@link ProgressHolder}, updated to hold the percentage progress if
|
||||
* {@link #PROGRESS_STATE_AVAILABLE available}.
|
||||
@ -839,21 +840,21 @@ public final class Transformer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCompleted(TransformationResult transformationResult) {
|
||||
public void onCompleted(ExportResult exportResult) {
|
||||
// TODO(b/213341814): Add event flags for Transformer events.
|
||||
transformerInternal = null;
|
||||
listeners.queueEvent(
|
||||
/* eventFlag= */ C.INDEX_UNSET,
|
||||
listener -> listener.onCompleted(composition, transformationResult));
|
||||
listener -> listener.onCompleted(composition, exportResult));
|
||||
listeners.flushEvents();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(TransformationResult result, TransformationException exception) {
|
||||
public void onError(ExportResult exportResult, TransformationException exception) {
|
||||
transformerInternal = null;
|
||||
listeners.queueEvent(
|
||||
/* eventFlag= */ C.INDEX_UNSET,
|
||||
listener -> listener.onError(composition, result, exception));
|
||||
listener -> listener.onError(composition, exportResult, exception));
|
||||
listeners.flushEvents();
|
||||
}
|
||||
}
|
||||
|
@ -57,9 +57,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
public interface Listener {
|
||||
|
||||
void onCompleted(TransformationResult result);
|
||||
void onCompleted(ExportResult exportResult);
|
||||
|
||||
void onError(TransformationResult result, TransformationException exception);
|
||||
void onError(ExportResult exportResult, TransformationException exception);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,7 +100,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
private final List<SamplePipeline> samplePipelines;
|
||||
private final MuxerWrapper muxerWrapper;
|
||||
private final ConditionVariable transformerConditionVariable;
|
||||
private final TransformationResult.Builder transformationResultBuilder;
|
||||
private final ExportResult.Builder exportResultBuilder;
|
||||
|
||||
private boolean generateSilentAudio;
|
||||
private boolean isDrainingPipelines;
|
||||
@ -142,7 +142,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
samplePipelines = new ArrayList<>();
|
||||
muxerWrapper = new MuxerWrapper(outputPath, muxerFactory, componentListener);
|
||||
transformerConditionVariable = new ConditionVariable();
|
||||
transformationResultBuilder = new TransformationResult.Builder();
|
||||
exportResultBuilder = new ExportResult.Builder();
|
||||
// It's safe to use "this" because we don't send a message before exiting the constructor.
|
||||
@SuppressWarnings("nullness:methodref.receiver.bound")
|
||||
HandlerWrapper internalHandler =
|
||||
@ -243,9 +243,9 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
private void endInternal(
|
||||
@EndReason int endReason, @Nullable TransformationException transformationException) {
|
||||
ImmutableList<TransformationResult.ProcessedInput> processedInputs =
|
||||
ImmutableList<ExportResult.ProcessedInput> processedInputs =
|
||||
compositeAssetLoader.getProcessedInputs();
|
||||
transformationResultBuilder
|
||||
exportResultBuilder
|
||||
.setProcessedInputs(processedInputs)
|
||||
.setAudioEncoderName(encoderFactory.getAudioEncoderName())
|
||||
.setVideoEncoderName(encoderFactory.getVideoEncoderName());
|
||||
@ -300,10 +300,10 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
applicationHandler.post(
|
||||
() ->
|
||||
listener.onError(
|
||||
transformationResultBuilder.setTransformationException(finalException).build(),
|
||||
exportResultBuilder.setTransformationException(finalException).build(),
|
||||
finalException));
|
||||
} else {
|
||||
applicationHandler.post(() -> listener.onCompleted(transformationResultBuilder.build()));
|
||||
applicationHandler.post(() -> listener.onCompleted(exportResultBuilder.build()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,32 +416,32 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
public void onTrackEnded(
|
||||
@C.TrackType int trackType, Format format, int averageBitrate, int sampleCount) {
|
||||
if (trackType == C.TRACK_TYPE_AUDIO) {
|
||||
transformationResultBuilder
|
||||
exportResultBuilder
|
||||
.setAverageAudioBitrate(averageBitrate)
|
||||
.setPcmEncoding(format.pcmEncoding);
|
||||
if (format.channelCount != Format.NO_VALUE) {
|
||||
transformationResultBuilder.setChannelCount(format.channelCount);
|
||||
exportResultBuilder.setChannelCount(format.channelCount);
|
||||
}
|
||||
if (format.sampleRate != Format.NO_VALUE) {
|
||||
transformationResultBuilder.setSampleRate(format.sampleRate);
|
||||
exportResultBuilder.setSampleRate(format.sampleRate);
|
||||
}
|
||||
} else if (trackType == C.TRACK_TYPE_VIDEO) {
|
||||
transformationResultBuilder
|
||||
exportResultBuilder
|
||||
.setAverageVideoBitrate(averageBitrate)
|
||||
.setColorInfo(format.colorInfo)
|
||||
.setVideoFrameCount(sampleCount);
|
||||
if (format.height != Format.NO_VALUE) {
|
||||
transformationResultBuilder.setHeight(format.height);
|
||||
exportResultBuilder.setHeight(format.height);
|
||||
}
|
||||
if (format.width != Format.NO_VALUE) {
|
||||
transformationResultBuilder.setWidth(format.width);
|
||||
exportResultBuilder.setWidth(format.width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnded(long durationMs, long fileSizeBytes) {
|
||||
transformationResultBuilder.setDurationMs(durationMs).setFileSizeBytes(fileSizeBytes);
|
||||
exportResultBuilder.setDurationMs(durationMs).setFileSizeBytes(fileSizeBytes);
|
||||
|
||||
internalHandler
|
||||
.obtainMessage(
|
||||
|
@ -602,10 +602,10 @@ public final class TransformerEndToEndTest {
|
||||
MediaItem mediaItem = MediaItem.fromUri(ASSET_URI_PREFIX + FILE_AUDIO_VIDEO);
|
||||
|
||||
transformer.start(mediaItem, outputPath);
|
||||
TransformationResult result = TransformerTestRunner.runLooper(transformer);
|
||||
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
|
||||
|
||||
assertThat(result.averageAudioBitrate).isGreaterThan(0);
|
||||
assertThat(result.averageVideoBitrate).isGreaterThan(0);
|
||||
assertThat(exportResult.averageAudioBitrate).isGreaterThan(0);
|
||||
assertThat(exportResult.averageVideoBitrate).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -760,10 +760,10 @@ public final class TransformerEndToEndTest {
|
||||
|
||||
// This would throw if the previous transformation had not been cancelled.
|
||||
transformer.start(mediaItem, outputPath);
|
||||
TransformationResult transformationResult = TransformerTestRunner.runLooper(transformer);
|
||||
ExportResult exportResult = TransformerTestRunner.runLooper(transformer);
|
||||
|
||||
// TODO(b/264974805): Make transformation output deterministic and check it against dump file.
|
||||
assertThat(transformationResult.transformationException).isNull();
|
||||
assertThat(exportResult.transformationException).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -19,7 +19,6 @@ package androidx.media3.transformer;
|
||||
import static androidx.media3.common.util.Assertions.checkNotNull;
|
||||
import static androidx.media3.test.utils.robolectric.RobolectricUtil.runLooperUntil;
|
||||
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.test.utils.robolectric.RobolectricUtil;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@ -33,46 +32,44 @@ public final class TransformerTestRunner {
|
||||
|
||||
/**
|
||||
* Runs tasks of the {@linkplain Transformer#getApplicationLooper() transformer Looper} until the
|
||||
* {@linkplain Transformer transformation} ends.
|
||||
* {@linkplain Transformer export} ends.
|
||||
*
|
||||
* @param transformer The {@link Transformer}.
|
||||
* @return The {@link TransformationResult}.
|
||||
* @return The {@link ExportResult}.
|
||||
* @throws TransformationException 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 TransformationResult runLooper(Transformer transformer)
|
||||
public static ExportResult runLooper(Transformer transformer)
|
||||
throws TransformationException, TimeoutException {
|
||||
AtomicReference<@NullableType TransformationResult> transformationResultRef =
|
||||
new AtomicReference<>();
|
||||
AtomicReference<@NullableType ExportResult> exportResultRef = new AtomicReference<>();
|
||||
|
||||
transformer.addListener(
|
||||
new Transformer.Listener() {
|
||||
@Override
|
||||
public void onTransformationCompleted(
|
||||
MediaItem inputMediaItem, TransformationResult result) {
|
||||
transformationResultRef.set(result);
|
||||
public void onCompleted(Composition composition, ExportResult exportResult) {
|
||||
exportResultRef.set(exportResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransformationError(
|
||||
MediaItem inputMediaItem,
|
||||
TransformationResult result,
|
||||
public void onError(
|
||||
Composition composition,
|
||||
ExportResult exportResult,
|
||||
TransformationException exception) {
|
||||
if (!Objects.equals(result.transformationException, exception)) {
|
||||
result = result.buildUpon().setTransformationException(exception).build();
|
||||
if (!Objects.equals(exportResult.transformationException, exception)) {
|
||||
exportResult = exportResult.buildUpon().setTransformationException(exception).build();
|
||||
}
|
||||
transformationResultRef.set(result);
|
||||
exportResultRef.set(exportResult);
|
||||
}
|
||||
});
|
||||
runLooperUntil(transformer.getApplicationLooper(), () -> transformationResultRef.get() != null);
|
||||
runLooperUntil(transformer.getApplicationLooper(), () -> exportResultRef.get() != null);
|
||||
|
||||
TransformationResult result = checkNotNull(transformationResultRef.get());
|
||||
if (result.transformationException != null) {
|
||||
throw result.transformationException;
|
||||
ExportResult exportResult = checkNotNull(exportResultRef.get());
|
||||
if (exportResult.transformationException != null) {
|
||||
throw exportResult.transformationException;
|
||||
}
|
||||
|
||||
return result;
|
||||
return exportResult;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user