From 85512f66e6823b36f9b2bb6875a1339a8163ac49 Mon Sep 17 00:00:00 2001 From: claincly Date: Mon, 28 Feb 2022 19:08:46 +0000 Subject: [PATCH] Add SSIM support to AndroidTestUtil. PiperOrigin-RevId: 431479473 --- .../transformer/AndroidTestUtil.java | 34 ++++++++++++++++--- .../exoplayer2/transformer/SsimHelper.java | 9 +++-- .../transformer/TestTransformationResult.java | 11 ++++++ .../transformer/TransformerEndToEndTest.java | 6 ++-- .../mh/RemoveAudioTransformationTest.java | 3 +- .../mh/RemoveVideoTransformationTest.java | 3 +- .../RepeatedTranscodeTransformationTest.java | 9 +++-- .../transformer/mh/SefTransformationTest.java | 3 +- ...ransformationMatrixTransformationTest.java | 3 +- .../transformer/mh/TranscodeQualityTest.java | 12 ++----- .../transformer/mh/TransformationTest.java | 3 +- 11 files changed, 68 insertions(+), 28 deletions(-) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java index 02814c2d59..abcd9b5371 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/AndroidTestUtil.java @@ -58,19 +58,32 @@ public final class AndroidTestUtil { * @param transformer The {@link Transformer} that performs the transformation. * @param uriString The uri (as a {@link String}) that will be transformed. * @param timeoutSeconds The transformer timeout. An exception is thrown if this is exceeded. + * @param calculateSsim Whether to include SSIM in the {@link TestTransformationResult}. The + * calculation involves decoding and comparing both the input and the output video. + * Consequently this calculation is not cost-free. Requires the input and output video to be + * the same size. * @return The {@link TestTransformationResult}. * @throws Exception The cause of the transformation not completing. */ public static TestTransformationResult runTransformer( - Context context, String testId, Transformer transformer, String uriString, int timeoutSeconds) + Context context, + String testId, + Transformer transformer, + String uriString, + int timeoutSeconds, + boolean calculateSsim) throws Exception { JSONObject resultJson = new JSONObject(); try { TestTransformationResult testTransformationResult = - runTransformerInternal(context, testId, transformer, uriString, timeoutSeconds); + runTransformerInternal( + context, testId, transformer, uriString, timeoutSeconds, calculateSsim); resultJson.put( "transformationResult", getTransformationResultJson(testTransformationResult.transformationResult)); + if (testTransformationResult.ssim != TestTransformationResult.SSIM_UNSET) { + resultJson.put("ssim", testTransformationResult.ssim); + } return testTransformationResult; } catch (Exception e) { resultJson.put("exception", getExceptionJson(e)); @@ -81,7 +94,12 @@ public final class AndroidTestUtil { } private static TestTransformationResult runTransformerInternal( - Context context, String testId, Transformer transformer, String uriString, int timeoutSeconds) + Context context, + String testId, + Transformer transformer, + String uriString, + int timeoutSeconds, + boolean calculateSsim) throws Exception { AtomicReference<@NullableType TransformationException> transformationExceptionReference = new AtomicReference<>(); @@ -150,7 +168,15 @@ public final class AndroidTestUtil { .setFileSizeBytes(outputVideoFile.length()) .build(); - return new TestTransformationResult(transformationResult, outputVideoFile.getPath()); + if (calculateSsim) { + return new TestTransformationResult( + transformationResult, + outputVideoFile.getPath(), + SsimHelper.calculate( + context, /* expectedVideoPath= */ uriString, outputVideoFile.getPath())); + } else { + return new TestTransformationResult(transformationResult, outputVideoFile.getPath()); + } } private static void writeTestSummaryToFile(Context context, String testId, JSONObject resultJson) diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/SsimHelper.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/SsimHelper.java index b943ce9356..70af8e747a 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/SsimHelper.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/SsimHelper.java @@ -82,18 +82,17 @@ public final class SsimHelper { /** * Returns the mean SSIM score between the expected and the actual video. * + *

The method compares every {@link #DEFAULT_COMPARISON_INTERVAL n-th} frame from both videos. + * * @param context The {@link Context}. * @param expectedVideoPath The path to the expected video file, must be in {@link * Context#getAssets() Assets}. * @param actualVideoPath The path to the actual video file. - * @param comparisonInterval The number of frames between the frames selected for comparison by - * SSIM. * @throws IOException When unable to open the provided video paths. */ - public static double calculate( - Context context, String expectedVideoPath, String actualVideoPath, int comparisonInterval) + public static double calculate(Context context, String expectedVideoPath, String actualVideoPath) throws IOException, InterruptedException { - return new SsimHelper(context, expectedVideoPath, actualVideoPath, comparisonInterval) + return new SsimHelper(context, expectedVideoPath, actualVideoPath, DEFAULT_COMPARISON_INTERVAL) .startCalculation(); } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TestTransformationResult.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TestTransformationResult.java index edc6c1a045..ec847bfab7 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TestTransformationResult.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TestTransformationResult.java @@ -17,11 +17,22 @@ package com.google.android.exoplayer2.transformer; /** A test only class for holding additional details alongside a {@link TransformationResult}. */ public class TestTransformationResult { + /** Represents an unset or unknown SSIM score. */ + public static final double SSIM_UNSET = -1.0d; + public final TransformationResult transformationResult; public final String filePath; + /** The SSIM score of the transformation, {@link #SSIM_UNSET} if unavailable. */ + public final double ssim; public TestTransformationResult(TransformationResult transformationResult, String filePath) { + this(transformationResult, filePath, /* ssim= */ SSIM_UNSET); + } + + public TestTransformationResult( + TransformationResult transformationResult, String filePath, double ssim) { this.transformationResult = transformationResult; this.filePath = filePath; + this.ssim = ssim; } } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java index 87e2c81a3d..152684be7c 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/TransformerEndToEndTest.java @@ -59,7 +59,8 @@ public class TransformerEndToEndTest { /* testId= */ "videoTranscoding_completesWithConsistentFrameCount", transformer, VP9_VIDEO_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); FrameCountingMuxer frameCountingMuxer = checkNotNull(muxerFactory.getLastFrameCountingMuxerCreated()); @@ -92,7 +93,8 @@ public class TransformerEndToEndTest { /* testId= */ "videoEditing_completesWithConsistentFrameCount", transformer, AVC_VIDEO_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); FrameCountingMuxer frameCountingMuxer = checkNotNull(muxerFactory.getLastFrameCountingMuxerCreated()); diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveAudioTransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveAudioTransformationTest.java index 5f53a5527a..696b80b180 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveAudioTransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveAudioTransformationTest.java @@ -40,6 +40,7 @@ public class RemoveAudioTransformationTest { /* testId= */ "removeAudioTransform", transformer, MP4_ASSET_WITH_INCREASING_TIMESTAMPS_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); } } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveVideoTransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveVideoTransformationTest.java index 3ca45e2314..1ee67917cb 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveVideoTransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RemoveVideoTransformationTest.java @@ -37,6 +37,7 @@ public class RemoveVideoTransformationTest { /* testId= */ "removeVideoTransform", transformer, MP4_ASSET_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); } } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java index 9860ead318..26c8817bbf 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/RepeatedTranscodeTransformationTest.java @@ -62,7 +62,8 @@ public final class RepeatedTranscodeTransformationTest { /* testId= */ "repeatedTranscode_givesConsistentLengthOutput_" + i, transformer, AndroidTestUtil.REMOTE_MP4_10_SECONDS_H264_MP3_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); differentOutputSizesBytes.add(checkNotNull(testResult.transformationResult.fileSizeBytes)); } @@ -96,7 +97,8 @@ public final class RepeatedTranscodeTransformationTest { /* testId= */ "repeatedTranscodeNoAudio_givesConsistentLengthOutput_" + i, transformer, AndroidTestUtil.REMOTE_MP4_10_SECONDS_H264_MP3_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); differentOutputSizesBytes.add(checkNotNull(testResult.transformationResult.fileSizeBytes)); } @@ -125,7 +127,8 @@ public final class RepeatedTranscodeTransformationTest { /* testId= */ "repeatedTranscodeNoVideo_givesConsistentLengthOutput_" + i, transformer, AndroidTestUtil.REMOTE_MP4_10_SECONDS_H264_MP3_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); differentOutputSizesBytes.add(checkNotNull(testResult.transformationResult.fileSizeBytes)); } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SefTransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SefTransformationTest.java index b700f94028..7330afb7ff 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SefTransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SefTransformationTest.java @@ -53,6 +53,7 @@ public class SefTransformationTest { /* testId = */ "sefTransform", transformer, SEF_ASSET_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); } } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SetTransformationMatrixTransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SetTransformationMatrixTransformationTest.java index 6c7751e495..96eca86ab1 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SetTransformationMatrixTransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/SetTransformationMatrixTransformationTest.java @@ -48,6 +48,7 @@ public class SetTransformationMatrixTransformationTest { /* testId= */ "setTransformationMatrixTransform", transformer, REMOTE_MP4_10_SECONDS_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); } } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java index 8d5e421aa6..b853e55d7b 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TranscodeQualityTest.java @@ -23,7 +23,6 @@ import android.content.Context; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.android.exoplayer2.transformer.AndroidTestUtil; -import com.google.android.exoplayer2.transformer.SsimHelper; import com.google.android.exoplayer2.transformer.TestTransformationResult; import com.google.android.exoplayer2.transformer.TransformationRequest; import com.google.android.exoplayer2.transformer.Transformer; @@ -52,14 +51,9 @@ public final class TranscodeQualityTest { /* testId= */ "singleTranscode_ssim", transformer, AndroidTestUtil.MP4_ASSET_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ true); - assertThat( - SsimHelper.calculate( - context, - AndroidTestUtil.MP4_ASSET_URI_STRING, - result.filePath, - SsimHelper.DEFAULT_COMPARISON_INTERVAL)) - .isGreaterThan(0.95); + assertThat(result.ssim).isGreaterThan(0.95); } } diff --git a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java index 06fb4e0fc8..67ed39a21b 100644 --- a/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java +++ b/library/transformer/src/androidTest/java/com/google/android/exoplayer2/transformer/mh/TransformationTest.java @@ -40,6 +40,7 @@ public class TransformationTest { /* testId= */ "transform", transformer, MP4_ASSET_WITH_INCREASING_TIMESTAMPS_URI_STRING, - /* timeoutSeconds= */ 120); + /* timeoutSeconds= */ 120, + /* calculateSsim= */ false); } }