Prevent ExoPlayer dropping frames in EffectPlaybackPixelTest
Some tests check all the output frames and fail if there are frames missing. PiperOrigin-RevId: 677676143
This commit is contained in:
parent
5e3dcea1bf
commit
be4d31ba87
@ -17,7 +17,6 @@
|
|||||||
package androidx.media3.transformer.mh.performance;
|
package androidx.media3.transformer.mh.performance;
|
||||||
|
|
||||||
import static androidx.media3.common.Player.STATE_ENDED;
|
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.common.util.Assertions.checkStateNotNull;
|
||||||
import static androidx.media3.test.utils.BitmapPixelTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE;
|
import static androidx.media3.test.utils.BitmapPixelTestUtil.MAXIMUM_AVERAGE_PIXEL_ABSOLUTE_DIFFERENCE;
|
||||||
import static androidx.media3.test.utils.BitmapPixelTestUtil.createArgb8888BitmapFromRgba8888Image;
|
import static androidx.media3.test.utils.BitmapPixelTestUtil.createArgb8888BitmapFromRgba8888Image;
|
||||||
@ -31,10 +30,12 @@ import static com.google.common.truth.Truth.assertWithMessage;
|
|||||||
import static org.junit.Assume.assumeTrue;
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
import android.app.Instrumentation;
|
import android.app.Instrumentation;
|
||||||
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.media.Image;
|
import android.media.Image;
|
||||||
import android.media.ImageReader;
|
import android.media.ImageReader;
|
||||||
|
import android.os.Handler;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
@ -46,10 +47,13 @@ import androidx.media3.common.util.Size;
|
|||||||
import androidx.media3.common.util.Util;
|
import androidx.media3.common.util.Util;
|
||||||
import androidx.media3.effect.Brightness;
|
import androidx.media3.effect.Brightness;
|
||||||
import androidx.media3.effect.TimestampWrapper;
|
import androidx.media3.effect.TimestampWrapper;
|
||||||
|
import androidx.media3.exoplayer.DefaultRenderersFactory;
|
||||||
import androidx.media3.exoplayer.ExoPlayer;
|
import androidx.media3.exoplayer.ExoPlayer;
|
||||||
import androidx.media3.exoplayer.Renderer;
|
import androidx.media3.exoplayer.Renderer;
|
||||||
|
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector;
|
||||||
import androidx.media3.exoplayer.util.EventLogger;
|
import androidx.media3.exoplayer.util.EventLogger;
|
||||||
import androidx.media3.exoplayer.video.MediaCodecVideoRenderer;
|
import androidx.media3.exoplayer.video.MediaCodecVideoRenderer;
|
||||||
|
import androidx.media3.exoplayer.video.VideoRendererEventListener;
|
||||||
import androidx.media3.test.utils.BitmapPixelTestUtil;
|
import androidx.media3.test.utils.BitmapPixelTestUtil;
|
||||||
import androidx.media3.transformer.SurfaceTestActivity;
|
import androidx.media3.transformer.SurfaceTestActivity;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
@ -135,6 +139,7 @@ public class EffectPlaybackPixelTest {
|
|||||||
|
|
||||||
setOutputSurfaceAndSizeOnPlayer(
|
setOutputSurfaceAndSizeOnPlayer(
|
||||||
player,
|
player,
|
||||||
|
findVideoRenderer(player),
|
||||||
outputImageReader.getSurface(),
|
outputImageReader.getSurface(),
|
||||||
new Size(MP4_ASSET.videoFormat.width, MP4_ASSET.videoFormat.height));
|
new Size(MP4_ASSET.videoFormat.width, MP4_ASSET.videoFormat.height));
|
||||||
|
|
||||||
@ -192,8 +197,8 @@ public class EffectPlaybackPixelTest {
|
|||||||
public void exoplayerEffectsPreviewTest_ensuresAllFramesRendered() throws Exception {
|
public void exoplayerEffectsPreviewTest_ensuresAllFramesRendered() throws Exception {
|
||||||
// Internal reference: b/264252759.
|
// Internal reference: b/264252759.
|
||||||
assumeTrue(
|
assumeTrue(
|
||||||
"This test should run on real devices because OpenGL to ImageReader rendering is not"
|
"This test should run on real devices because OpenGL to ImageReader rendering is"
|
||||||
+ " always reliable on emulators.",
|
+ "not always reliable on emulators.",
|
||||||
!Util.isRunningOnEmulator());
|
!Util.isRunningOnEmulator());
|
||||||
|
|
||||||
ArrayList<BitmapPixelTestUtil.ImageBuffer> readImageBuffers = new ArrayList<>();
|
ArrayList<BitmapPixelTestUtil.ImageBuffer> readImageBuffers = new ArrayList<>();
|
||||||
@ -211,7 +216,27 @@ public class EffectPlaybackPixelTest {
|
|||||||
|
|
||||||
instrumentation.runOnMainSync(
|
instrumentation.runOnMainSync(
|
||||||
() -> {
|
() -> {
|
||||||
player = new ExoPlayer.Builder(ApplicationProvider.getApplicationContext()).build();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
Renderer videoRenderer =
|
||||||
|
new NoFrameDroppedVideoRenderer(context, MediaCodecSelector.DEFAULT);
|
||||||
|
player =
|
||||||
|
new ExoPlayer.Builder(context)
|
||||||
|
.setRenderersFactory(
|
||||||
|
new DefaultRenderersFactory(context) {
|
||||||
|
@Override
|
||||||
|
protected void buildVideoRenderers(
|
||||||
|
Context context,
|
||||||
|
@ExtensionRendererMode int extensionRendererMode,
|
||||||
|
MediaCodecSelector mediaCodecSelector,
|
||||||
|
boolean enableDecoderFallback,
|
||||||
|
Handler eventHandler,
|
||||||
|
VideoRendererEventListener eventListener,
|
||||||
|
long allowedVideoJoiningTimeMs,
|
||||||
|
ArrayList<Renderer> out) {
|
||||||
|
out.add(videoRenderer);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
checkStateNotNull(outputImageReader);
|
checkStateNotNull(outputImageReader);
|
||||||
outputImageReader.setOnImageAvailableListener(
|
outputImageReader.setOnImageAvailableListener(
|
||||||
@ -228,6 +253,7 @@ public class EffectPlaybackPixelTest {
|
|||||||
|
|
||||||
setOutputSurfaceAndSizeOnPlayer(
|
setOutputSurfaceAndSizeOnPlayer(
|
||||||
player,
|
player,
|
||||||
|
videoRenderer,
|
||||||
outputImageReader.getSurface(),
|
outputImageReader.getSurface(),
|
||||||
new Size(MP4_ASSET.videoFormat.width, MP4_ASSET.videoFormat.height));
|
new Size(MP4_ASSET.videoFormat.width, MP4_ASSET.videoFormat.height));
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
@ -287,8 +313,8 @@ public class EffectPlaybackPixelTest {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
// Internal reference: b/264252759.
|
// Internal reference: b/264252759.
|
||||||
assumeTrue(
|
assumeTrue(
|
||||||
"This test should run on real devices because OpenGL to ImageReader rendering is not"
|
"This test should run on real devices because OpenGL to ImageReader rendering is"
|
||||||
+ " always reliable on emulators.",
|
+ "not always reliable on emulators.",
|
||||||
!Util.isRunningOnEmulator());
|
!Util.isRunningOnEmulator());
|
||||||
|
|
||||||
ArrayList<BitmapPixelTestUtil.ImageBuffer> readImageBuffers = new ArrayList<>();
|
ArrayList<BitmapPixelTestUtil.ImageBuffer> readImageBuffers = new ArrayList<>();
|
||||||
@ -306,7 +332,27 @@ public class EffectPlaybackPixelTest {
|
|||||||
|
|
||||||
instrumentation.runOnMainSync(
|
instrumentation.runOnMainSync(
|
||||||
() -> {
|
() -> {
|
||||||
player = new ExoPlayer.Builder(ApplicationProvider.getApplicationContext()).build();
|
Context context = ApplicationProvider.getApplicationContext();
|
||||||
|
Renderer videoRenderer =
|
||||||
|
new NoFrameDroppedVideoRenderer(context, MediaCodecSelector.DEFAULT);
|
||||||
|
player =
|
||||||
|
new ExoPlayer.Builder(context)
|
||||||
|
.setRenderersFactory(
|
||||||
|
new DefaultRenderersFactory(context) {
|
||||||
|
@Override
|
||||||
|
protected void buildVideoRenderers(
|
||||||
|
Context context,
|
||||||
|
@ExtensionRendererMode int extensionRendererMode,
|
||||||
|
MediaCodecSelector mediaCodecSelector,
|
||||||
|
boolean enableDecoderFallback,
|
||||||
|
Handler eventHandler,
|
||||||
|
VideoRendererEventListener eventListener,
|
||||||
|
long allowedVideoJoiningTimeMs,
|
||||||
|
ArrayList<Renderer> out) {
|
||||||
|
out.add(videoRenderer);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
checkStateNotNull(outputImageReader);
|
checkStateNotNull(outputImageReader);
|
||||||
outputImageReader.setOnImageAvailableListener(
|
outputImageReader.setOnImageAvailableListener(
|
||||||
@ -323,6 +369,7 @@ public class EffectPlaybackPixelTest {
|
|||||||
|
|
||||||
setOutputSurfaceAndSizeOnPlayer(
|
setOutputSurfaceAndSizeOnPlayer(
|
||||||
player,
|
player,
|
||||||
|
videoRenderer,
|
||||||
outputImageReader.getSurface(),
|
outputImageReader.getSurface(),
|
||||||
new Size(MP4_ASSET.videoFormat.width, MP4_ASSET.videoFormat.height));
|
new Size(MP4_ASSET.videoFormat.width, MP4_ASSET.videoFormat.height));
|
||||||
player.setPlayWhenReady(true);
|
player.setPlayWhenReady(true);
|
||||||
@ -395,11 +442,10 @@ public class EffectPlaybackPixelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void setOutputSurfaceAndSizeOnPlayer(
|
private static void setOutputSurfaceAndSizeOnPlayer(
|
||||||
ExoPlayer player, Surface outputSurface, Size outputSize) {
|
ExoPlayer player, Renderer videoRenderer, Surface outputSurface, Size outputSize) {
|
||||||
// We need to access renderer directly because ExoPlayer.setVideoEffects() doesn't support
|
// We need to access renderer directly because ExoPlayer.setVideoEffects() doesn't support
|
||||||
// output to a Surface. When using ImageReader, we need to manually set output resolution on
|
// output to a Surface. When using ImageReader, we need to manually set output resolution on
|
||||||
// the renderer directly.
|
// the renderer directly.
|
||||||
MediaCodecVideoRenderer videoRenderer = checkNotNull(findVideoRenderer(player));
|
|
||||||
player
|
player
|
||||||
.createMessage(videoRenderer)
|
.createMessage(videoRenderer)
|
||||||
.setType(Renderer.MSG_SET_VIDEO_OUTPUT)
|
.setType(Renderer.MSG_SET_VIDEO_OUTPUT)
|
||||||
@ -420,4 +466,23 @@ public class EffectPlaybackPixelTest {
|
|||||||
imageReader.close();
|
imageReader.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class NoFrameDroppedVideoRenderer extends MediaCodecVideoRenderer {
|
||||||
|
|
||||||
|
public NoFrameDroppedVideoRenderer(Context context, MediaCodecSelector mediaCodecSelector) {
|
||||||
|
super(context, mediaCodecSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldDropOutputBuffer(
|
||||||
|
long earlyUs, long elapsedRealtimeUs, boolean isLastBuffer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean shouldDropBuffersToKeyframe(
|
||||||
|
long earlyUs, long elapsedRealtimeUs, boolean isLastBuffer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user