Increase the maxImage on ImageReader, hoping less flaky tests

PiperOrigin-RevId: 679528425
This commit is contained in:
claincly 2024-09-27 04:00:21 -07:00 committed by Copybara-Service
parent b9aed0a937
commit e0e9f5b057

View File

@ -17,6 +17,7 @@
package androidx.media3.transformer.mh.performance;
import static androidx.media3.common.Player.STATE_ENDED;
import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import static androidx.media3.test.utils.BitmapPixelTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE;
import static androidx.media3.test.utils.BitmapPixelTestUtil.createArgb8888BitmapFromRgba8888Image;
@ -58,6 +59,7 @@ import androidx.media3.test.utils.BitmapPixelTestUtil;
import androidx.media3.transformer.SurfaceTestActivity;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@ -69,38 +71,44 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
/** Pixel tests for {@link ExoPlayer#setVideoEffects}. */
// These tests are in the performance package even though they are not performance tests so that
// they are not run on all devices. This is because they use ImageReader, which has a tendency to
// drop frames.
@RunWith(Enclosed.class)
@RunWith(AndroidJUnit4.class)
public class EffectPlaybackPixelTest {
private static final String TEST_DIRECTORY = "test-generated-goldens/ExoPlayerPlaybackTest";
private static final long TEST_TIMEOUT_MS = 10_000;
/**
* The test asserts the first frame is rendered for {@link Player#setPlayWhenReady playWhenReady}
* is set to either {@code true} or {@code false}.
*/
@RunWith(Parameterized.class)
public static class RenderedFirstFrameTest {
/** Playback test for {@link Effect}-enabled playback. */
@Rule public final TestName testName = new TestName();
// Force the test to run in foreground to make it faster and avoid ImageReader frame drops.
@Rule
public ActivityScenarioRule<SurfaceTestActivity> rule =
new ActivityScenarioRule<>(SurfaceTestActivity.class);
private final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
private @MonotonicNonNull ExoPlayer player;
private @MonotonicNonNull ImageReader outputImageReader;
private String testId;
@Parameter public boolean playWhenReady;
@Parameters(name = "playWhenReady={0}")
public static ImmutableList<Boolean> parameters() {
return ImmutableList.of(true, false);
@Before
public void setUp() {
testId = testName.getMethodName();
// Setting maxImages=10 ensures image reader gets all rendered frames from
// VideoFrameProcessor. Using maxImages=10 runs successfully on a Pixel3.
outputImageReader =
ImageReader.newInstance(
MP4_ASSET.videoFormat.width,
MP4_ASSET.videoFormat.height,
PixelFormat.RGBA_8888,
// Use a larger count to avoid ImageReader dropping frames
/* maxImages= */ 10);
}
@After
@ -109,24 +117,14 @@ public class EffectPlaybackPixelTest {
}
@Test
public void exoplayerEffectsPreviewTest_ensuresFirstFrameRendered() throws Exception {
String testId =
Util.formatInvariant(
"exoplayerEffectsPreviewTest_withPlayWhenReady[%b]_ensuresFirstFrameRendered",
playWhenReady);
public void exoplayerEffectsPreviewTest_playWhenReadySetToFalse_ensuresFirstFrameRendered()
throws Exception {
AtomicReference<Bitmap> renderedFirstFrameBitmap = new AtomicReference<>();
ConditionVariable hasRenderedFirstFrameCondition = new ConditionVariable();
outputImageReader =
ImageReader.newInstance(
MP4_ASSET.videoFormat.width,
MP4_ASSET.videoFormat.height,
PixelFormat.RGBA_8888,
/* maxImages= */ 1);
instrumentation.runOnMainSync(
() -> {
player = new ExoPlayer.Builder(ApplicationProvider.getApplicationContext()).build();
checkStateNotNull(outputImageReader);
outputImageReader.setOnImageAvailableListener(
imageReader -> {
@ -139,11 +137,11 @@ public class EffectPlaybackPixelTest {
setOutputSurfaceAndSizeOnPlayer(
player,
findVideoRenderer(player),
checkNotNull(findVideoRenderer(player)),
outputImageReader.getSurface(),
new Size(MP4_ASSET.videoFormat.width, MP4_ASSET.videoFormat.height));
player.setPlayWhenReady(playWhenReady);
player.setPlayWhenReady(false);
player.setVideoEffects(ImmutableList.of(createTimestampOverlay()));
// Adding an EventLogger to use its log output in case the test fails.
@ -163,35 +161,9 @@ public class EffectPlaybackPixelTest {
/* expected= */ readBitmap(TEST_DIRECTORY + "/first_frame.png"),
/* actual= */ renderedFirstFrameBitmap.get(),
testId);
assertThat(averagePixelAbsoluteDifference)
.isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
assertThat(averagePixelAbsoluteDifference).isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
// TODO: b/315800590 - Verify onFirstFrameRendered is invoked only once.
}
}
/** Playback test for {@link Effect}-enabled playback. */
public static class PlaybackTest {
@Rule public final TestName testName = new TestName();
// Force the test to run in foreground to make it faster and avoid ImageReader frame drops.
@Rule
public ActivityScenarioRule<SurfaceTestActivity> rule =
new ActivityScenarioRule<>(SurfaceTestActivity.class);
private final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
private @MonotonicNonNull ExoPlayer player;
private @MonotonicNonNull ImageReader outputImageReader;
private String testId;
@Before
public void setUpTestId() {
testId = testName.getMethodName();
}
@After
public void tearDown() {
instrumentation.runOnMainSync(() -> release(player, outputImageReader));
}
@Test
public void exoplayerEffectsPreviewTest_ensuresAllFramesRendered() throws Exception {
@ -205,14 +177,6 @@ public class EffectPlaybackPixelTest {
AtomicInteger renderedFramesCount = new AtomicInteger();
ConditionVariable playerEnded = new ConditionVariable();
ConditionVariable readAllOutputFrames = new ConditionVariable();
// Setting maxImages=10 ensures image reader gets all rendered frames from
// VideoFrameProcessor. Using maxImages=10 runs successfully on a Pixel3.
outputImageReader =
ImageReader.newInstance(
MP4_ASSET.videoFormat.width,
MP4_ASSET.videoFormat.height,
PixelFormat.RGBA_8888,
/* maxImages= */ 10);
instrumentation.runOnMainSync(
() -> {
@ -242,8 +206,7 @@ public class EffectPlaybackPixelTest {
outputImageReader.setOnImageAvailableListener(
imageReader -> {
try (Image image = imageReader.acquireNextImage()) {
readImageBuffers.add(
BitmapPixelTestUtil.copyByteBufferFromRbga8888Image(image));
readImageBuffers.add(BitmapPixelTestUtil.copyByteBufferFromRbga8888Image(image));
}
if (renderedFramesCount.incrementAndGet() == MP4_ASSET.videoFrameCount) {
readAllOutputFrames.open();
@ -358,8 +321,7 @@ public class EffectPlaybackPixelTest {
outputImageReader.setOnImageAvailableListener(
imageReader -> {
try (Image image = imageReader.acquireNextImage()) {
readImageBuffers.add(
BitmapPixelTestUtil.copyByteBufferFromRbga8888Image(image));
readImageBuffers.add(BitmapPixelTestUtil.copyByteBufferFromRbga8888Image(image));
}
if (renderedFramesCount.incrementAndGet() == MP4_ASSET.videoFrameCount) {
readAllOutputFrames.open();
@ -426,7 +388,6 @@ public class EffectPlaybackPixelTest {
.isAtMost(MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE);
}
}
}
@Nullable
private static MediaCodecVideoRenderer findVideoRenderer(ExoPlayer player) {