diff --git a/packages/video_player/video_player_android/CHANGELOG.md b/packages/video_player/video_player_android/CHANGELOG.md index 544dff2c94b7..6c9fdbb59001 100644 --- a/packages/video_player/video_player_android/CHANGELOG.md +++ b/packages/video_player/video_player_android/CHANGELOG.md @@ -1,7 +1,9 @@ -## NEXT +## 2.7.18 * Suppresses deprecation and removal warnings for `TextureRegistry.SurfaceProducer.onSurfaceDestroyed`. +* Changes plugin to use `TextureRegistry.SurfaceProducer.handlesCropAndRotation` + to detect the backend used to provide `Surface`s. ## 2.7.17 diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerEventListener.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerEventListener.java index df6115fd5846..57219077a65b 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerEventListener.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerEventListener.java @@ -19,6 +19,7 @@ final class ExoPlayerEventListener implements Player.Listener { private final VideoPlayerCallbacks events; private boolean isBuffering = false; private boolean isInitialized; + private boolean surfaceProducerHandlesCropAndRotation; private enum RotationDegrees { ROTATE_0(0), @@ -46,14 +47,15 @@ public int getDegrees() { } } - ExoPlayerEventListener(ExoPlayer exoPlayer, VideoPlayerCallbacks events) { - this(exoPlayer, events, false); + ExoPlayerEventListener(ExoPlayer exoPlayer, VideoPlayerCallbacks events, boolean surfaceProducerHandlesCropAndRotation) { + this(exoPlayer, events, false, surfaceProducerHandlesCropAndRotation); } - ExoPlayerEventListener(ExoPlayer exoPlayer, VideoPlayerCallbacks events, boolean initialized) { + ExoPlayerEventListener(ExoPlayer exoPlayer, VideoPlayerCallbacks events, boolean initialized, boolean surfaceProducerHandlesCropAndRotation) { this.exoPlayer = exoPlayer; this.events = events; this.isInitialized = initialized; + this.surfaceProducerHandlesCropAndRotation = surfaceProducerHandlesCropAndRotation; } private void setBuffering(boolean buffering) { @@ -97,9 +99,7 @@ private void sendInitialized() { rotationCorrection = 0; } } - // TODO(camsim99): Replace this with a call to `handlesCropAndRotation` when it is - // available in stable. https://github.com/flutter/flutter/issues/157198 - else if (Build.VERSION.SDK_INT < 29) { + else if (surfaceProducerHandlesCropAndRotation) { // When the SurfaceTexture backend for Impeller is used, the preview should already // be correctly rotated. rotationCorrection = 0; diff --git a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java index 3e855e53b7cd..b129daf09dc6 100644 --- a/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java +++ b/packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java @@ -112,7 +112,8 @@ private ExoPlayer createVideoPlayer() { exoPlayer.setVideoSurface(surfaceProducer.getSurface()); boolean wasInitialized = savedStateDuring != null; - exoPlayer.addListener(new ExoPlayerEventListener(exoPlayer, videoPlayerEvents, wasInitialized)); + boolean surfaceProducerHandlesCropAndRotation = surfaceProducer.handlesCropAndRotation(); + exoPlayer.addListener(new ExoPlayerEventListener(exoPlayer, videoPlayerEvents, wasInitialized, surfaceProducerHandlesCropAndRotation)); setAudioAttributes(exoPlayer, options.mixWithOthers); return exoPlayer; diff --git a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/ExoPlayerEventListenerTest.java b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/ExoPlayerEventListenerTest.java index 65dfb311c31c..6ed7a561ac7e 100644 --- a/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/ExoPlayerEventListenerTest.java +++ b/packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/ExoPlayerEventListenerTest.java @@ -42,14 +42,22 @@ public final class ExoPlayerEventListenerTest { @Rule public MockitoRule initRule = MockitoJUnit.rule(); - @Before - public void setUp() { - eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks); + @Test + @Config(maxSdk = 21) + public void onPlaybackStateChangedReadySendInitialized_belowAndroid21() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); + VideoSize size = new VideoSize(800, 400, 0, 0); + when(mockExoPlayer.getVideoSize()).thenReturn(size); + when(mockExoPlayer.getDuration()).thenReturn(10L); + + eventListener.onPlaybackStateChanged(Player.STATE_READY); + verify(mockCallbacks).onInitialized(800, 400, 10L, 0); } @Test - @Config(maxSdk = 28) - public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { + @Config(minSdk = 22) + public void onPlaybackStateChangedReadySendInitialized_whenSurfaceProducerHandlesCropAndRotation() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); VideoSize size = new VideoSize(800, 400, 0, 0); when(mockExoPlayer.getVideoSize()).thenReturn(size); when(mockExoPlayer.getDuration()).thenReturn(10L); @@ -59,9 +67,10 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { } @Test - @Config(minSdk = 29) + @Config(minSdk = 22) public void - onPlaybackStateChangedReadySendInitializedWithRotationCorrectionAndWidthAndHeightSwap_aboveAndroid29() { + onPlaybackStateChangedReadySendInitializedWithRotationCorrectionAndWidthAndHeightSwap_whenSurfaceProducerDoesNotHandleCropAndRotation() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, false); VideoSize size = new VideoSize(800, 400, 0, 0); int rotationCorrection = 90; Format videoFormat = new Format.Builder().setRotationDegrees(rotationCorrection).build(); @@ -78,6 +87,7 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { @Config(maxSdk = 21) public void onPlaybackStateChangedReadyInPortraitMode90DegreesSwapWidthAndHeight_belowAndroid21() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); VideoSize size = new VideoSize(800, 400, 90, 0); when(mockExoPlayer.getVideoSize()).thenReturn(size); when(mockExoPlayer.getDuration()).thenReturn(10L); @@ -87,9 +97,10 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { } @Test - @Config(minSdk = 22, maxSdk = 28) + @Config(minSdk = 22) public void - onPlaybackStateChangedReadyInPortraitMode90DegreesDoesNotSwapWidthAndHeight_aboveAndroid21belowAndroid29() { + onPlaybackStateChangedReadyInPortraitMode90DegreesDoesNotSwapWidthAndHeight_whenSurfaceProducerHandlesCropAndRotation() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); VideoSize size = new VideoSize(800, 400, 90, 0); when(mockExoPlayer.getVideoSize()).thenReturn(size); @@ -100,9 +111,10 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { } @Test - @Config(minSdk = 29) + @Config(minSdk = 22) public void - onPlaybackStateChangedReadyInPortraitMode90DegreesSwapWidthAndHeight_aboveAndroid29() { + onPlaybackStateChangedReadyInPortraitMode90DegreesSwapWidthAndHeight_whenSurfaceProducerDoesNotHandleCropAndRotation() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, false); VideoSize size = new VideoSize(800, 400, 0, 0); int rotationCorrection = 90; Format videoFormat = new Format.Builder().setRotationDegrees(rotationCorrection).build(); @@ -119,6 +131,7 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { @Config(maxSdk = 21) public void onPlaybackStateChangedReadyInPortraitMode270DegreesSwapWidthAndHeight_belowAndroid21() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); VideoSize size = new VideoSize(800, 400, 270, 0); when(mockExoPlayer.getVideoSize()).thenReturn(size); when(mockExoPlayer.getDuration()).thenReturn(10L); @@ -128,9 +141,10 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { } @Test - @Config(minSdk = 22, maxSdk = 28) + @Config(minSdk = 22) public void - onPlaybackStateChangedReadyInPortraitMode270DegreesDoesNotSwapWidthAndHeight_aboveAndroid21belowAndroid29() { + onPlaybackStateChangedReadyInPortraitMode270DegreesDoesNotSwapWidthAndHeight_whenSurfaceProducerHandlesCropAndRotation() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); VideoSize size = new VideoSize(800, 400, 270, 0); when(mockExoPlayer.getVideoSize()).thenReturn(size); when(mockExoPlayer.getDuration()).thenReturn(10L); @@ -140,9 +154,10 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { } @Test - @Config(minSdk = 29) + @Config(minSdk = 22) public void - onPlaybackStateChangedReadyInPortraitMode270DegreesSwapWidthAndHeight_aboveAndroid29() { + onPlaybackStateChangedReadyInPortraitMode270DegreesSwapWidthAndHeight_whenSurfaceProducerDoesNotHandleCropAndRotation() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, false); VideoSize size = new VideoSize(800, 400, 0, 0); int rotationCorrection = 270; Format videoFormat = new Format.Builder().setRotationDegrees(rotationCorrection).build(); @@ -158,6 +173,7 @@ public void onPlaybackStateChangedReadySendInitialized_belowAndroid29() { @Test @Config(maxSdk = 21) public void onPlaybackStateChangedReadyFlipped180DegreesInformEventHandler_belowAndroid21() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); VideoSize size = new VideoSize(800, 400, 180, 0); when(mockExoPlayer.getVideoSize()).thenReturn(size); when(mockExoPlayer.getDuration()).thenReturn(10L); @@ -168,6 +184,7 @@ public void onPlaybackStateChangedReadyFlipped180DegreesInformEventHandler_below @Test public void onPlaybackStateChangedBufferingSendsBufferingStartAndUpdates() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); when(mockExoPlayer.getBufferedPosition()).thenReturn(10L); eventListener.onPlaybackStateChanged(Player.STATE_BUFFERING); @@ -182,6 +199,7 @@ public void onPlaybackStateChangedBufferingSendsBufferingStartAndUpdates() { @Test public void onPlaybackStateChangedEndedSendsOnCompleted() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); eventListener.onPlaybackStateChanged(Player.STATE_ENDED); verify(mockCallbacks).onCompleted(); @@ -190,6 +208,7 @@ public void onPlaybackStateChangedEndedSendsOnCompleted() { @Test public void onPlaybackStateChangedEndedAfterBufferingSendsBufferingEndAndOnCompleted() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); when(mockExoPlayer.getBufferedPosition()).thenReturn(10L); eventListener.onPlaybackStateChanged(Player.STATE_BUFFERING); verify(mockCallbacks).onBufferingStart(); @@ -204,6 +223,7 @@ public void onPlaybackStateChangedEndedAfterBufferingSendsBufferingEndAndOnCompl @Test public void onPlaybackStateChangedIdleDoNothing() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); eventListener.onPlaybackStateChanged(Player.STATE_IDLE); verifyNoInteractions(mockCallbacks); @@ -211,6 +231,7 @@ public void onPlaybackStateChangedIdleDoNothing() { @Test public void onPlaybackStateChangedIdleAfterBufferingSendsBufferingEnd() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); when(mockExoPlayer.getBufferedPosition()).thenReturn(10L); eventListener.onPlaybackStateChanged(Player.STATE_BUFFERING); verify(mockCallbacks).onBufferingStart(); @@ -224,6 +245,7 @@ public void onPlaybackStateChangedIdleAfterBufferingSendsBufferingEnd() { @Test public void onErrorVideoErrorWhenBufferingInProgressAlsoEndBuffering() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); when(mockExoPlayer.getBufferedPosition()).thenReturn(10L); eventListener.onPlaybackStateChanged(Player.STATE_BUFFERING); verify(mockCallbacks).onBufferingStart(); @@ -237,6 +259,7 @@ public void onErrorVideoErrorWhenBufferingInProgressAlsoEndBuffering() { @Test public void onErrorBehindLiveWindowSeekToDefaultAndPrepare() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); eventListener.onPlayerError( new PlaybackException("SORT_OF_OK", null, PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW)); @@ -247,6 +270,7 @@ public void onErrorBehindLiveWindowSeekToDefaultAndPrepare() { @Test public void onIsPlayingChangedToggled() { + ExoPlayerEventListener eventListener = new ExoPlayerEventListener(mockExoPlayer, mockCallbacks, true); eventListener.onIsPlayingChanged(true); verify(mockCallbacks).onIsPlayingStateUpdate(true); diff --git a/packages/video_player/video_player_android/pubspec.yaml b/packages/video_player/video_player_android/pubspec.yaml index c32c49579d1f..d39c188a3bb5 100644 --- a/packages/video_player/video_player_android/pubspec.yaml +++ b/packages/video_player/video_player_android/pubspec.yaml @@ -2,7 +2,7 @@ name: video_player_android description: Android implementation of the video_player plugin. repository: https://github.com/flutter/packages/tree/main/packages/video_player/video_player_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+video_player%22 -version: 2.7.17 +version: 2.7.18 environment: sdk: ^3.6.0