diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/image/ImageRenderer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/image/ImageRenderer.java index b05da06548..344eb6d2da 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/image/ImageRenderer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/image/ImageRenderer.java @@ -571,7 +571,7 @@ public class ImageRenderer extends BaseRenderer { checkStateNotNull(outputBitmap); int tileWidth = outputBitmap.getWidth() / checkStateNotNull(inputFormat).tileCountHorizontal; int tileHeight = outputBitmap.getHeight() / checkStateNotNull(inputFormat).tileCountVertical; - int tileStartXCoordinate = tileWidth * (tileIndex % inputFormat.tileCountVertical); + int tileStartXCoordinate = tileWidth * (tileIndex % inputFormat.tileCountHorizontal); int tileStartYCoordinate = tileHeight * (tileIndex / inputFormat.tileCountHorizontal); return Bitmap.createBitmap( outputBitmap, tileStartXCoordinate, tileStartYCoordinate, tileWidth, tileHeight); diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/image/ImageRendererTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/image/ImageRendererTest.java index 242f9b4d45..beee713a0a 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/image/ImageRendererTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/image/ImageRendererTest.java @@ -66,16 +66,16 @@ public class ImageRendererTest { .setTileCountVertical(1) .setTileCountHorizontal(1) .build(); - private static final Format JPEG_FORMAT_WITH_FOUR_TILES = + private static final Format JPEG_FORMAT_WITH_SIX_TILES = new Format.Builder() .setSampleMimeType(MimeTypes.IMAGE_JPEG) - .setTileCountVertical(2) + .setTileCountVertical(3) .setTileCountHorizontal(2) .build(); private final List> renderedBitmaps = new ArrayList<>(); private final Bitmap fakeDecodedBitmap1 = - Bitmap.createBitmap(/* width= */ 2, /* height= */ 2, Bitmap.Config.ARGB_8888); + Bitmap.createBitmap(/* width= */ 2, /* height= */ 3, Bitmap.Config.ARGB_8888); private final Bitmap fakeDecodedBitmap2 = Bitmap.createBitmap(/* width= */ 4, /* height= */ 4, Bitmap.Config.ARGB_8888); @@ -223,16 +223,18 @@ public class ImageRendererTest { throws Exception { FakeSampleStream fakeSampleStream1 = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), - emptySample(/* timeUs= */ 300_000L, /* flags= */ 0))); + emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0))); fakeSampleStream1.writeData(/* startPositionUs= */ 0); FakeSampleStream fakeSampleStream2 = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 10L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM)); @@ -254,25 +256,27 @@ public class ImageRendererTest { renderer.start(); renderer.render(/* positionUs= */ 200_000L, /* elapsedRealtimeUs= */ 0); renderer.render(/* positionUs= */ 300_000L, /* elapsedRealtimeUs= */ 0); + renderer.render(/* positionUs= */ 400_000L, /* elapsedRealtimeUs= */ 0); + renderer.render(/* positionUs= */ 500_000L, /* elapsedRealtimeUs= */ 0); renderer.replaceStream( new Format[] {PNG_FORMAT}, fakeSampleStream2, /* startPositionUs= */ 10, - /* offsetUs= */ 450_000L, + /* offsetUs= */ 650_000L, new MediaSource.MediaPeriodId(new Object())); renderer.setCurrentStreamFinal(); // Render last sample of first stream - renderer.render(/* positionUs= */ 400_000L, /* elapsedRealtimeUs= */ 0); + renderer.render(/* positionUs= */ 600_000L, /* elapsedRealtimeUs= */ 0); StopWatch hasReadStreamToEndStopWatch = new StopWatch(HAS_READ_STREAM_TO_END_TIMEOUT_MESSAGE); while (!renderer.hasReadStreamToEnd() && hasReadStreamToEndStopWatch.ensureNotExpired()) { - renderer.render(/* positionUs= */ 450_010L, /* elapsedRealtimeUs= */ 0L); + renderer.render(/* positionUs= */ 650_010L, /* elapsedRealtimeUs= */ 0L); } renderer.stop(); - assertThat(renderedBitmaps).hasSize(5); + assertThat(renderedBitmaps).hasSize(7); assertThat(renderedBitmaps.get(0).first).isEqualTo(0); - assertThat(renderedBitmaps.get(4).first).isEqualTo(10L); + assertThat(renderedBitmaps.get(6).first).isEqualTo(10L); } @Test @@ -280,7 +284,7 @@ public class ImageRendererTest { throws Exception { FakeSampleStream fakeSampleStream1 = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), @@ -289,7 +293,7 @@ public class ImageRendererTest { fakeSampleStream1.writeData(/* startPositionUs= */ 0); FakeSampleStream fakeSampleStream2 = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 10L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM)); @@ -397,17 +401,19 @@ public class ImageRendererTest { public void render_tiledImage_cropsAndRendersToImageOutput() throws Exception { FakeSampleStream fakeSampleStream = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); renderer.enable( RendererConfiguration.DEFAULT, - new Format[] {JPEG_FORMAT_WITH_FOUR_TILES}, + new Format[] {JPEG_FORMAT_WITH_SIX_TILES}, fakeSampleStream, /* positionUs= */ 0, /* joining= */ false, @@ -431,7 +437,7 @@ public class ImageRendererTest { positionUs += 100_000; } - assertThat(renderedBitmaps).hasSize(4); + assertThat(renderedBitmaps).hasSize(6); assertThat(renderedBitmaps.get(0).first).isEqualTo(0L); assertThat(renderedBitmaps.get(0).second.getHeight()).isEqualTo(1); assertThat(renderedBitmaps.get(0).second.getWidth()).isEqualTo(1); @@ -444,23 +450,31 @@ public class ImageRendererTest { assertThat(renderedBitmaps.get(3).first).isEqualTo(300_000L); assertThat(renderedBitmaps.get(3).second.getHeight()).isEqualTo(1); assertThat(renderedBitmaps.get(3).second.getWidth()).isEqualTo(1); + assertThat(renderedBitmaps.get(4).first).isEqualTo(400_000L); + assertThat(renderedBitmaps.get(4).second.getHeight()).isEqualTo(1); + assertThat(renderedBitmaps.get(4).second.getWidth()).isEqualTo(1); + assertThat(renderedBitmaps.get(5).first).isEqualTo(500_000L); + assertThat(renderedBitmaps.get(5).second.getHeight()).isEqualTo(1); + assertThat(renderedBitmaps.get(5).second.getWidth()).isEqualTo(1); } @Test public void render_tiledImageWithNonZeroStartPosition_rendersToImageOutput() throws Exception { FakeSampleStream fakeSampleStream = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); renderer.enable( RendererConfiguration.DEFAULT, - new Format[] {JPEG_FORMAT_WITH_FOUR_TILES}, + new Format[] {JPEG_FORMAT_WITH_SIX_TILES}, fakeSampleStream, /* positionUs= */ 200_000, /* joining= */ false, @@ -484,9 +498,11 @@ public class ImageRendererTest { positionUs += 100_000; } - assertThat(renderedBitmaps).hasSize(2); + assertThat(renderedBitmaps).hasSize(4); assertThat(renderedBitmaps.get(0).first).isEqualTo(200_000L); assertThat(renderedBitmaps.get(1).first).isEqualTo(300_000L); + assertThat(renderedBitmaps.get(2).first).isEqualTo(400_000L); + assertThat(renderedBitmaps.get(3).first).isEqualTo(500_000L); } @Test @@ -494,17 +510,19 @@ public class ImageRendererTest { throws Exception { FakeSampleStream fakeSampleStream = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); renderer.enable( RendererConfiguration.DEFAULT, - new Format[] {JPEG_FORMAT_WITH_FOUR_TILES}, + new Format[] {JPEG_FORMAT_WITH_SIX_TILES}, fakeSampleStream, /* positionUs= */ 0, /* joining= */ false, @@ -517,11 +535,11 @@ public class ImageRendererTest { StopWatch isReadyStopWatch = new StopWatch(IS_READY_TIMEOUT_MESSAGE); while (!renderer.isReady() && isReadyStopWatch.ensureNotExpired()) { renderer.render( - /* positionUs= */ 350_000, + /* positionUs= */ 550_000, /* elapsedRealtimeUs= */ SystemClock.DEFAULT.elapsedRealtime() * 1000); } StopWatch isEndedStopWatch = new StopWatch(IS_ENDED_TIMEOUT_MESSAGE); - long positionUs = 350_000; + long positionUs = 550_000; while (!renderer.isEnded() && isEndedStopWatch.ensureNotExpired()) { renderer.render( positionUs, /* elapsedRealtimeUs= */ SystemClock.DEFAULT.elapsedRealtime() * 1000); @@ -529,7 +547,7 @@ public class ImageRendererTest { } assertThat(renderedBitmaps).hasSize(1); - assertThat(renderedBitmaps.get(0).first).isEqualTo(300_000L); + assertThat(renderedBitmaps.get(0).first).isEqualTo(500_000L); } @Test @@ -537,17 +555,19 @@ public class ImageRendererTest { throws Exception { FakeSampleStream fakeSampleStream = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); renderer.enable( RendererConfiguration.DEFAULT, - new Format[] {JPEG_FORMAT_WITH_FOUR_TILES}, + new Format[] {JPEG_FORMAT_WITH_SIX_TILES}, fakeSampleStream, /* positionUs= */ 0, /* joining= */ false, @@ -560,11 +580,11 @@ public class ImageRendererTest { StopWatch isReadyStopWatch = new StopWatch(IS_READY_TIMEOUT_MESSAGE); while (!renderer.isReady() && isReadyStopWatch.ensureNotExpired()) { renderer.render( - /* positionUs= */ 250_000L, + /* positionUs= */ 450_000L, /* elapsedRealtimeUs= */ SystemClock.DEFAULT.elapsedRealtime() * 1000); } StopWatch isEndedStopWatch = new StopWatch(IS_ENDED_TIMEOUT_MESSAGE); - long positionUs = 250_000L; + long positionUs = 450_000L; while (!renderer.isEnded() && isEndedStopWatch.ensureNotExpired()) { renderer.render( positionUs, /* elapsedRealtimeUs= */ SystemClock.DEFAULT.elapsedRealtime() * 1000); @@ -572,8 +592,8 @@ public class ImageRendererTest { } assertThat(renderedBitmaps).hasSize(2); - assertThat(renderedBitmaps.get(0).first).isEqualTo(200_000L); - assertThat(renderedBitmaps.get(1).first).isEqualTo(300_000L); + assertThat(renderedBitmaps.get(0).first).isEqualTo(400_000L); + assertThat(renderedBitmaps.get(1).first).isEqualTo(500_000L); } @Test @@ -582,17 +602,19 @@ public class ImageRendererTest { throws Exception { FakeSampleStream fakeSampleStream = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); renderer.enable( RendererConfiguration.DEFAULT, - new Format[] {JPEG_FORMAT_WITH_FOUR_TILES}, + new Format[] {JPEG_FORMAT_WITH_SIX_TILES}, fakeSampleStream, /* positionUs= */ 0, /* joining= */ false, @@ -616,10 +638,12 @@ public class ImageRendererTest { positionUs += 100_000; } - assertThat(renderedBitmaps).hasSize(3); + assertThat(renderedBitmaps).hasSize(5); assertThat(renderedBitmaps.get(0).first).isEqualTo(100_000L); assertThat(renderedBitmaps.get(1).first).isEqualTo(200_000L); assertThat(renderedBitmaps.get(2).first).isEqualTo(300_000L); + assertThat(renderedBitmaps.get(3).first).isEqualTo(400_000L); + assertThat(renderedBitmaps.get(4).first).isEqualTo(500_000L); } @Test @@ -628,17 +652,19 @@ public class ImageRendererTest { throws Exception { FakeSampleStream fakeSampleStream = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); renderer.enable( RendererConfiguration.DEFAULT, - new Format[] {JPEG_FORMAT_WITH_FOUR_TILES}, + new Format[] {JPEG_FORMAT_WITH_SIX_TILES}, fakeSampleStream, /* positionUs= */ 0, /* joining= */ false, @@ -662,10 +688,12 @@ public class ImageRendererTest { positionUs += 100_000; } - assertThat(renderedBitmaps).hasSize(3); + assertThat(renderedBitmaps).hasSize(5); assertThat(renderedBitmaps.get(0).first).isEqualTo(100_000L); assertThat(renderedBitmaps.get(1).first).isEqualTo(200_000L); assertThat(renderedBitmaps.get(2).first).isEqualTo(300_000L); + assertThat(renderedBitmaps.get(3).first).isEqualTo(400_000L); + assertThat(renderedBitmaps.get(4).first).isEqualTo(500_000L); } @Test @@ -673,17 +701,19 @@ public class ImageRendererTest { throws Exception { FakeSampleStream fakeSampleStream = createSampleStream( - JPEG_FORMAT_WITH_FOUR_TILES, + JPEG_FORMAT_WITH_SIX_TILES, ImmutableList.of( oneByteSample(/* timeUs= */ 0L, /* flags= */ C.BUFFER_FLAG_KEY_FRAME), emptySample(/* timeUs= */ 100_000L, /* flags= */ 0), emptySample(/* timeUs= */ 200_000L, /* flags= */ 0), emptySample(/* timeUs= */ 300_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 400_000L, /* flags= */ 0), + emptySample(/* timeUs= */ 500_000L, /* flags= */ 0), END_OF_STREAM_ITEM)); fakeSampleStream.writeData(/* startPositionUs= */ 0); renderer.enable( RendererConfiguration.DEFAULT, - new Format[] {JPEG_FORMAT_WITH_FOUR_TILES}, + new Format[] {JPEG_FORMAT_WITH_SIX_TILES}, fakeSampleStream, /* positionUs= */ 0, /* joining= */ false, @@ -696,7 +726,7 @@ public class ImageRendererTest { StopWatch isReadyStopWatch = new StopWatch(IS_READY_TIMEOUT_MESSAGE); while (!renderer.isReady() && isReadyStopWatch.ensureNotExpired()) { renderer.render( - /* positionUs= */ 330_000, + /* positionUs= */ 530_000, /* elapsedRealtimeUs= */ SystemClock.DEFAULT.elapsedRealtime() * 1000); } StopWatch isEndedStopWatch = new StopWatch(IS_ENDED_TIMEOUT_MESSAGE); @@ -708,7 +738,7 @@ public class ImageRendererTest { } assertThat(renderedBitmaps).hasSize(1); - assertThat(renderedBitmaps.get(0).first).isEqualTo(300_000L); + assertThat(renderedBitmaps.get(0).first).isEqualTo(500_000L); } private static FakeSampleStream.FakeSampleStreamItem emptySample(