forked from flutter/packages
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move
Player.Listener
impl, remove `@VisibleForTesting isInitialized…
…`. (flutter#6922) Similar to flutter#6908, as part of flutter/flutter#148417. I'm working on re-landing flutter#6456, this time without using the `ActivityAware` interface (see flutter/flutter#148417). As part of that work, I'll need to better control the `ExoPlayer` lifecycle and save/restore internal state. In this PR, I've removed the concept of the class being "initialized" or not - the only thing "initialized" means is "for a given instance of `ExoPlayer`, has received the `'initialized'` event. As a result I removed the quasi-public API that was used for testing only and replaced it with observing what the real production instance does (`Player.STATE_READY`). After this PR, I'll likely do one more pass around the constructors - the constructor that takes an `ExoPlayer` that is marked `@VisibleForTesting` _also_ doesn't make sense once we'll support suspending/resuming video players, so it will need to get reworked (probably into taking a factory method).
- Loading branch information
1 parent
a0f2552
commit dd04ab1
Showing
4 changed files
with
167 additions
and
129 deletions.
There are no files selected for viewing
101 changes: 101 additions & 0 deletions
101
..._android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package io.flutter.plugins.videoplayer; | ||
|
||
import androidx.annotation.NonNull; | ||
import androidx.media3.common.PlaybackException; | ||
import androidx.media3.common.Player; | ||
import androidx.media3.common.VideoSize; | ||
import androidx.media3.exoplayer.ExoPlayer; | ||
|
||
final class ExoPlayerEventListener implements Player.Listener { | ||
private final ExoPlayer exoPlayer; | ||
private final VideoPlayerCallbacks events; | ||
private boolean isBuffering = false; | ||
private boolean isInitialized = false; | ||
|
||
ExoPlayerEventListener(ExoPlayer exoPlayer, VideoPlayerCallbacks events) { | ||
this.exoPlayer = exoPlayer; | ||
this.events = events; | ||
} | ||
|
||
private void setBuffering(boolean buffering) { | ||
if (isBuffering == buffering) { | ||
return; | ||
} | ||
isBuffering = buffering; | ||
if (buffering) { | ||
events.onBufferingStart(); | ||
} else { | ||
events.onBufferingEnd(); | ||
} | ||
} | ||
|
||
@SuppressWarnings("SuspiciousNameCombination") | ||
private void sendInitialized() { | ||
if (isInitialized) { | ||
return; | ||
} | ||
isInitialized = true; | ||
VideoSize videoSize = exoPlayer.getVideoSize(); | ||
int rotationCorrection = 0; | ||
int width = videoSize.width; | ||
int height = videoSize.height; | ||
if (width != 0 && height != 0) { | ||
int rotationDegrees = videoSize.unappliedRotationDegrees; | ||
// Switch the width/height if video was taken in portrait mode | ||
if (rotationDegrees == 90 || rotationDegrees == 270) { | ||
width = videoSize.height; | ||
height = videoSize.width; | ||
} | ||
// Rotating the video with ExoPlayer does not seem to be possible with a Surface, | ||
// so inform the Flutter code that the widget needs to be rotated to prevent | ||
// upside-down playback for videos with rotationDegrees of 180 (other orientations work | ||
// correctly without correction). | ||
if (rotationDegrees == 180) { | ||
rotationCorrection = rotationDegrees; | ||
} | ||
} | ||
events.onInitialized(width, height, exoPlayer.getDuration(), rotationCorrection); | ||
} | ||
|
||
@Override | ||
public void onPlaybackStateChanged(final int playbackState) { | ||
switch (playbackState) { | ||
case Player.STATE_BUFFERING: | ||
setBuffering(true); | ||
events.onBufferingUpdate(exoPlayer.getBufferedPosition()); | ||
break; | ||
case Player.STATE_READY: | ||
sendInitialized(); | ||
break; | ||
case Player.STATE_ENDED: | ||
events.onCompleted(); | ||
break; | ||
case Player.STATE_IDLE: | ||
break; | ||
} | ||
if (playbackState != Player.STATE_BUFFERING) { | ||
setBuffering(false); | ||
} | ||
} | ||
|
||
@Override | ||
public void onPlayerError(@NonNull final PlaybackException error) { | ||
setBuffering(false); | ||
if (error.errorCode == PlaybackException.ERROR_CODE_BEHIND_LIVE_WINDOW) { | ||
// See https://exoplayer.dev/live-streaming.html#behindlivewindowexception-and-error_code_behind_live_window | ||
exoPlayer.seekToDefaultPosition(); | ||
exoPlayer.prepare(); | ||
} else { | ||
events.onError("VideoError", "Video player had error " + error, null); | ||
} | ||
} | ||
|
||
@Override | ||
public void onIsPlayingChanged(boolean isPlaying) { | ||
events.onIsPlayingStateUpdate(isPlaying); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.