Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Update video player
  • Loading branch information
stuartmorgan-g committed May 23, 2025
commit 87ab97b858e2abaef2dc9f0f76fec0e279459614
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ TextureRegistry getTextureRegistry() {
final TextureRegistry.SurfaceProducer.Callback callback = callbackCaptor.getValue();

// Verify callback's onSurfaceCleanup invalidates SurfaceRequest.
simulateSurfaceDestruction(callback);
simulateSurfaceCleanup(callback);
verify(mockSurfaceRequest).invalidate();

reset(mockSurfaceRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

public abstract class ExoPlayerEventListener implements Player.Listener {
private boolean isBuffering = false;
private boolean isInitialized;
private boolean isInitialized = false;
protected final ExoPlayer exoPlayer;
protected final VideoPlayerCallbacks events;

Expand Down Expand Up @@ -42,10 +42,9 @@ public int getDegrees() {
}

public ExoPlayerEventListener(
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events, boolean initialized) {
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events) {
this.exoPlayer = exoPlayer;
this.events = events;
this.isInitialized = initialized;
}

private void setBuffering(boolean buffering) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
* <p>It provides methods to control playback, adjust volume, and handle seeking.
*/
public abstract class VideoPlayer {
@NonNull private final ExoPlayerProvider exoPlayerProvider;
@NonNull private final MediaItem mediaItem;
@NonNull private final VideoPlayerOptions options;
@NonNull protected final VideoPlayerCallbacks videoPlayerEvents;
@Nullable protected final SurfaceProducer surfaceProducer;
@NonNull protected ExoPlayer exoPlayer;
Expand All @@ -47,22 +44,12 @@ public VideoPlayer(
@Nullable SurfaceProducer surfaceProducer,
@NonNull ExoPlayerProvider exoPlayerProvider) {
this.videoPlayerEvents = events;
this.mediaItem = mediaItem;
this.options = options;
this.exoPlayerProvider = exoPlayerProvider;
this.surfaceProducer = surfaceProducer;
this.exoPlayer = createVideoPlayer();
}

@NonNull
protected ExoPlayer createVideoPlayer() {
ExoPlayer exoPlayer = exoPlayerProvider.get();
exoPlayer = exoPlayerProvider.get();
exoPlayer.setMediaItem(mediaItem);
exoPlayer.prepare();
exoPlayer.addListener(createExoPlayerEventListener(exoPlayer, surfaceProducer));
setAudioAttributes(exoPlayer, options.mixWithOthers);

return exoPlayer;
}

@NonNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.annotation.VisibleForTesting;
import androidx.media3.common.Format;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.ExoPlayer;
Expand All @@ -15,15 +14,9 @@
import java.util.Objects;

public final class PlatformViewExoPlayerEventListener extends ExoPlayerEventListener {
@VisibleForTesting
public PlatformViewExoPlayerEventListener(
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events) {
this(exoPlayer, events, false);
}

public PlatformViewExoPlayerEventListener(
@NonNull ExoPlayer exoPlayer, @NonNull VideoPlayerCallbacks events, boolean initialized) {
super(exoPlayer, events, initialized);
super(exoPlayer, events);
}

@OptIn(markerClass = UnstableApi.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,6 @@ public static PlatformViewVideoPlayer create(
@Override
protected ExoPlayerEventListener createExoPlayerEventListener(
@NonNull ExoPlayer exoPlayer, @Nullable SurfaceProducer surfaceProducer) {
// Platform view video player does not suspend and re-create the exoPlayer, hence initialized
// is always false. It also does not require a reference to the SurfaceProducer.
return new PlatformViewExoPlayerEventListener(exoPlayer, videoPlayerEvents, false);
return new PlatformViewExoPlayerEventListener(exoPlayer, videoPlayerEvents);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.annotation.VisibleForTesting;
import androidx.media3.common.Format;
import androidx.media3.common.VideoSize;
import androidx.media3.exoplayer.ExoPlayer;
Expand All @@ -18,20 +17,11 @@
public final class TextureExoPlayerEventListener extends ExoPlayerEventListener {
private boolean surfaceProducerHandlesCropAndRotation;

@VisibleForTesting
public TextureExoPlayerEventListener(
@NonNull ExoPlayer exoPlayer,
@NonNull VideoPlayerCallbacks events,
boolean surfaceProducerHandlesCropAndRotation) {
this(exoPlayer, events, surfaceProducerHandlesCropAndRotation, false);
}

public TextureExoPlayerEventListener(
@NonNull ExoPlayer exoPlayer,
@NonNull VideoPlayerCallbacks events,
boolean surfaceProducerHandlesCropAndRotation,
boolean initialized) {
super(exoPlayer, events, initialized);
super(exoPlayer, events);
this.surfaceProducerHandlesCropAndRotation = surfaceProducerHandlesCropAndRotation;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
package io.flutter.plugins.videoplayer.texture;

import android.content.Context;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.annotation.VisibleForTesting;
import androidx.media3.common.MediaItem;
import androidx.media3.exoplayer.ExoPlayer;
import io.flutter.plugins.videoplayer.ExoPlayerEventListener;
import io.flutter.plugins.videoplayer.ExoPlayerState;
import io.flutter.plugins.videoplayer.VideoAsset;
import io.flutter.plugins.videoplayer.VideoPlayer;
import io.flutter.plugins.videoplayer.VideoPlayerCallbacks;
Expand All @@ -27,8 +27,8 @@
* the texture.
*/
public final class TextureVideoPlayer extends VideoPlayer implements SurfaceProducer.Callback {
@Nullable private ExoPlayerState savedStateDuring;

// True when the ExoPlayer instance has a null surface.
private boolean needsSurface = true;
/**
* Creates a texture video player.
*
Expand Down Expand Up @@ -70,7 +70,9 @@ public TextureVideoPlayer(

surfaceProducer.setCallback(this);

this.exoPlayer.setVideoSurface(surfaceProducer.getSurface());
Surface surface = surfaceProducer.getSurface();
this.exoPlayer.setVideoSurface(surface);
needsSurface = surface == null;
}

@NonNull
Expand All @@ -83,44 +85,31 @@ protected ExoPlayerEventListener createExoPlayerEventListener(
}
boolean surfaceProducerHandlesCropAndRotation = surfaceProducer.handlesCropAndRotation();
return new TextureExoPlayerEventListener(
exoPlayer,
videoPlayerEvents,
surfaceProducerHandlesCropAndRotation,
playerHasBeenSuspended());
exoPlayer, videoPlayerEvents, surfaceProducerHandlesCropAndRotation);
}

@RestrictTo(RestrictTo.Scope.LIBRARY)
public void onSurfaceAvailable() {
if (savedStateDuring != null) {
exoPlayer = createVideoPlayer();
if (needsSurface) {
// TextureVideoPlayer must always set a surfaceProducer.
assert surfaceProducer != null;
exoPlayer.setVideoSurface(surfaceProducer.getSurface());
savedStateDuring.restore(exoPlayer);
savedStateDuring = null;
needsSurface = false;
}
}

@RestrictTo(RestrictTo.Scope.LIBRARY)
// TODO(bparrishMines): Replace with onSurfaceCleanup once available on stable. See
// https://github.com/flutter/flutter/issues/161256.
@SuppressWarnings({"deprecation", "removal"})
public void onSurfaceDestroyed() {
// Intentionally do not call pause/stop here, because the surface has already been released
// at this point (see https://github.com/flutter/flutter/issues/156451).
savedStateDuring = ExoPlayerState.save(exoPlayer);
exoPlayer.release();
}

private boolean playerHasBeenSuspended() {
return savedStateDuring != null;
public void onSurfaceCleanup() {
exoPlayer.setVideoSurface(null);
needsSurface = true;
}

public void dispose() {
// Super must be called first to ensure the player is released before the surface.
super.dispose();

// TextureVideoPlayer must always set a surfaceProducer.
assert surfaceProducer != null;
surfaceProducer.release();
// TODO(matanlurey): Remove when embedder no longer calls-back once released.
// https://github.com/flutter/flutter/issues/156434.
surfaceProducer.setCallback(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public final class ExoPlayerEventListenerTest {
*/
private static final class TestExoPlayerEventListener extends ExoPlayerEventListener {
public TestExoPlayerEventListener(ExoPlayer exoPlayer, VideoPlayerCallbacks callbacks) {
super(exoPlayer, callbacks, false);
super(exoPlayer, callbacks);
}

@Override
Expand Down
Loading