Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate video_player/android from SurfaceTexture->SurfaceProducer. #6456

Merged
merged 20 commits into from
May 29, 2024

Conversation

matanlurey
Copy link
Contributor

WIP: We do not plan to land this PR until the next stable release (>= April 3rd 2024).

Work towards flutter/flutter#145930.

Details

Migrates uses of createSurfaceTexture to createSurfaceProducer, which is intended to have no change in behavior, but does change the backend rendering path, so it will require more testing (and we're also open to minor API renames or changes before it becomes stable).

Background

Android plugins previously requested a SurfaceTexture from the Android embedder, and used that to produce a Surface to render external textures on (i.e. video_player). This worked because 100% of Flutter applications on Android used OpenGLES (via our Skia backend), and SurfaceTexture is actually an (opaque) OpenGLES-texture.

Starting soon (roughly ~Q3, this is not a guarantee and just an estimate), Flutter on Android will start to use our new Impeller graphics backend, which on newer devices (>= API_VERSION_28), will default to the Vulkan, not OpenGLES. In other words, SurfaceTexture will cease to work (it is possible, but non-trivial, to map an OpenGLES texture over to Vulkan).

After consultation with the Android team, they helped us understand that vending SurfaceTexture (the consumer-side API) was never the right abstraction, and we should have been vending the producer-side API, or Surface directly. The new SurfaceProducer API is exactly that - it generates a Surface, and similar to our platform view strategy, picks the "right" consumer-side implementation details for the user/plugin packages.

The new SurfaceProducer API has 2 possible rendering types (as an implementation detail):

  • SurfaceTexture, for older OpenGLES devices, which works exactly as it does today.
  • ImageReader, for newer OpenGLES or Vulkan devices.

These are some subtle nuances in how these two APIs work differently (one example: flutter/flutter#144407), but our theory at this point is we don't expect these changes to be observed by any users, and we have other ideas if necessary.

Note

These invariants are tested on CI in flutter/engine.

Points of contact:

Copy link
Contributor

@johnmccutchan johnmccutchan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woo hoo

@matanlurey matanlurey marked this pull request as ready for review May 16, 2024 19:50
@matanlurey matanlurey requested a review from camsim99 as a code owner May 16, 2024 19:50
@matanlurey
Copy link
Contributor Author

Due to a release hiccup, the stable branch (3.22) is temporarily ahead of the master branch (3.22.0-35.0.pre.34), leading to CI failures (see discord discussion). I've merged back into HEAD and updated the pubspec/CHANGELOG - the rest might be done by someone else while I'm on vacation for a couple of weeks.

@@ -186,7 +186,7 @@ public void onCancel(Object o) {
}
});

surface = new Surface(textureEntry.surfaceTexture());
surface = surfaceProducer.getSurface();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, the returned Surface may become invalid after a suspend / resume. Is there a place in the plugin that will be notified when we resume? We should update the video surface in that callback.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to look at this still.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've made this activity aware. It now tears down the exoplayer on pause and recreates on reusme.

@@ -48,16 +48,16 @@ final class VideoPlayer {

private ExoPlayer exoPlayer;

private Surface surface;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't need to cache surface.

}

public void pauseSurface() {
eventChannel.setStreamHandler(null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried just calling exoPlayer.setSurface again with a new surface, however the old surface being disposed seems to break some internal state, so I have to recreate the exo instance. This might imply some loss of state.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree but I'm not sure because I'm not deeply familiar with ExoPlayer. Does the case where a video is playing and then the app is moved to the background and brought back get impacted by this, i.e. the video is no longer playing from the point it was stopped?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me investigate this .

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at this and it seems like the video state is reset. I'm going to see if there is a way to restore it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added logic to restore all of the visible exo state when re-creating exo player.

Copy link
Contributor

@camsim99 camsim99 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label May 29, 2024
@auto-submit auto-submit bot merged commit a5dd314 into main May 29, 2024
74 checks passed
@auto-submit auto-submit bot deleted the video-player-surface-producer branch May 29, 2024 21:18
@johnmccutchan
Copy link
Contributor

@jonahwilliams Just flagging that if we decide to back out our fix that forces ImageReaders to be recreated, we should revert parts of the PR.

engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request May 30, 2024
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request May 30, 2024
flutter/packages@31d3329...910fabb

2024-05-29 58529443+srujzs@users.noreply.github.com Amend package:web tweaks to allow package:web roll (flutter/packages#6793)
2024-05-29 matanlurey@users.noreply.github.com Migrate `video_player/android` from `SurfaceTexture`->`SurfaceProducer`. (flutter/packages#6456)
2024-05-29 joonas.kerttula@codemate.com [google_maps_flutter] Undeprecate BitmapDescriptor methods (flutter/packages#6832)
2024-05-29 matanlurey@users.noreply.github.com Migrate CameraX from SurfaceTexture to SurfaceProducer. (flutter/packages#6462)
2024-05-29 matanlurey@users.noreply.github.com Migrate `camera/android` from `SurfaceTexture`->`SurfaceProducer`. (flutter/packages#6461)
2024-05-29 katelovett@google.com [dynamic_layouts] Remove the dynamic_layouts package (flutter/packages#6830)
2024-05-29 43054281+camsim99@users.noreply.github.com [camerax] Add notes about Android permissions (flutter/packages#6741)
2024-05-29 43054281+camsim99@users.noreply.github.com [Re-land] Bump legacy all_packages project AGP version to 7.0.0, Gradle version to 7.0.2 (flutter/packages#6742)
2024-05-29 engine-flutter-autoroll@skia.org Roll Flutter from a1a33e6 to c85fa6a (20 revisions) (flutter/packages#6829)
2024-05-29 katelovett@google.com [rfw] Migrate deprecated doc references (flutter/packages#6744)
2024-05-29 katelovett@google.com [flutter_adaptive_scaffold] Migrate MaterialStateProperty to WidgetStateProperty (flutter/packages#6743)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com,rmistry@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/flutter that referenced this pull request May 31, 2024
…er#149321)

flutter/packages@31d3329...910fabb

2024-05-29 58529443+srujzs@users.noreply.github.com Amend package:web tweaks to allow package:web roll (flutter/packages#6793)
2024-05-29 matanlurey@users.noreply.github.com Migrate `video_player/android` from `SurfaceTexture`->`SurfaceProducer`. (flutter/packages#6456)
2024-05-29 joonas.kerttula@codemate.com [google_maps_flutter] Undeprecate BitmapDescriptor methods (flutter/packages#6832)
2024-05-29 matanlurey@users.noreply.github.com Migrate CameraX from SurfaceTexture to SurfaceProducer. (flutter/packages#6462)
2024-05-29 matanlurey@users.noreply.github.com Migrate `camera/android` from `SurfaceTexture`->`SurfaceProducer`. (flutter/packages#6461)
2024-05-29 katelovett@google.com [dynamic_layouts] Remove the dynamic_layouts package (flutter/packages#6830)
2024-05-29 43054281+camsim99@users.noreply.github.com [camerax] Add notes about Android permissions (flutter/packages#6741)
2024-05-29 43054281+camsim99@users.noreply.github.com [Re-land] Bump legacy all_packages project AGP version to 7.0.0, Gradle version to 7.0.2 (flutter/packages#6742)
2024-05-29 engine-flutter-autoroll@skia.org Roll Flutter from a1a33e6 to c85fa6a (20 revisions) (flutter/packages#6829)
2024-05-29 katelovett@google.com [rfw] Migrate deprecated doc references (flutter/packages#6744)
2024-05-29 katelovett@google.com [flutter_adaptive_scaffold] Migrate MaterialStateProperty to WidgetStateProperty (flutter/packages#6743)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com,rmistry@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
auto-submit bot pushed a commit that referenced this pull request Jun 6, 2024
auto-submit bot pushed a commit that referenced this pull request Jun 13, 2024
…#6908)

Part of flutter/flutter#148417.

I'm working on re-landing #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.

These are some proposed refactors to limit how much work `VideoPlayer` is doing, so I can better understand what needs to be reset (or not) internally. Specifically, `VideoPlayer` no longer knows what an `EventChannel` or `EventSink` is, and does not need to manage the lifecycle (it stores a `private final VideoPlayerCallbacks` instead), and instead there is a `VideoPlayerCallbacks` interface that does all that.

I'm totally open to:
- Landing this as-is (+/- nits) and making minor improvements in follow-up PRs
- Making more significant changes to this PR and then landing it
- Not landing this PR at all because it doesn't follow the approach the folks who maintain the plugin prefer

Also happy to chat in VC/person about any of the changes.
auto-submit bot pushed a commit that referenced this pull request Jun 13, 2024
…`. (#6922)

Similar to #6908, as part of flutter/flutter#148417.

I'm working on re-landing #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).
arc-yong pushed a commit to Arctuition/packages-arc that referenced this pull request Jun 14, 2024
…r`. (flutter#6456)

_**WIP**: We do not plan to land this PR until the next stable release (>= April 3rd 2024)_.

Work towards flutter/flutter#145930.

## Details

Migrates uses of `createSurfaceTexture` to `createSurfaceProducer`, which is intended to have no change in behavior, but _does_ change the backend rendering path, so it will require more testing (and we're also open to minor API renames or changes before it becomes stable).

## Background 

Android plugins previously requested a `SurfaceTexture` from the Android embedder, and used that to produce a `Surface` to render external textures on (i.e. `video_player`).  This worked because 100% of Flutter applications on Android used OpenGLES (via our Skia backend), and `SurfaceTexture` is actually an (opaque) OpenGLES-texture.

Starting soon (roughly ~Q3, this is not a guarantee and just an estimate), Flutter on Android will start to use our new Impeller graphics backend, which on newer devices (`>= API_VERSION_28`), will default to the Vulkan, _not_ OpenGLES. In other words, `SurfaceTexture` will cease to work (it is possible, but non-trivial, to map an OpenGLES texture over to Vulkan).

After consultation with the Android team, they helped us understand that vending `SurfaceTexture` (the _consumer-side_ API) was never the right abstraction, and we should have been vending the _producer-side_ API, or `Surface` directly. The new `SurfaceProducer` API is exactly that - it generates a `Surface`, and similar to our platform view strategy, picks the "right" _consumer-side_ implementation details _for_ the user/plugin packages.

The new `SurfaceProducer` API has 2 possible rendering types (as an implementation detail):

- `SurfaceTexture`, for older OpenGLES devices, which works exactly as it does today.
- `ImageReader`, for newer OpenGLES _or_ Vulkan devices.

These are some subtle nuances in how these two APIs work differently (one example: flutter/flutter#144407), but our theory at this point is we don't expect these changes to be observed by any users, and we have other ideas if necessary. 

> [!NOTE]
> These invariants are [tested on CI in `flutter/engine`](https://github.com/flutter/engine/tree/main/testing/scenario_app/android#ci-configuration).

Points of contact: 
- @matanlurey or @jonahwilliams  (Flutter Engine)
- @johnmccutchan or @reidbaker  (Flutter on Android)
arc-yong pushed a commit to Arctuition/packages-arc that referenced this pull request Jun 14, 2024
arc-yong pushed a commit to Arctuition/packages-arc that referenced this pull request Jun 14, 2024
…flutter#6908)

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.

These are some proposed refactors to limit how much work `VideoPlayer` is doing, so I can better understand what needs to be reset (or not) internally. Specifically, `VideoPlayer` no longer knows what an `EventChannel` or `EventSink` is, and does not need to manage the lifecycle (it stores a `private final VideoPlayerCallbacks` instead), and instead there is a `VideoPlayerCallbacks` interface that does all that.

I'm totally open to:
- Landing this as-is (+/- nits) and making minor improvements in follow-up PRs
- Making more significant changes to this PR and then landing it
- Not landing this PR at all because it doesn't follow the approach the folks who maintain the plugin prefer

Also happy to chat in VC/person about any of the changes.
arc-yong pushed a commit to Arctuition/packages-arc that referenced this pull request Jun 14, 2024
…`. (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).
matanlurey added a commit that referenced this pull request Jun 25, 2024
…allback`. (#6982)

I'm working on re-landing #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.

Follows the patterns of some of the previous PRs, i.e.

- #6922
- #6908

The changes in this PR are _mostly_ tests, it was extremely difficult to
just add more tests to the already very leaky `VideoPlayer` abstraction
which had lots of `@VisibleForTesting` methods and other "holes" to
observe state. This PR removes all of that, and adds test coverage where
it was missing.

Namely it:

- Adds a new class, `VideoAsset`, that builds and configures the media
that `ExoPlayer` uses.
- Removes all "testing" state from `VidePlayer`, keeping it nearly
immutable.
- Added tests for most of the classes I've added since, which were
mostly missing.

That being said, this is a large change. I'm happy to sit down with
either of you and walk through it.

---

Opening as a draft for the moment, since there is a pubspec change
needing I want to handle first.
gabbopalma pushed a commit to gabbopalma/packages that referenced this pull request Jun 26, 2024
…allback`. (flutter#6982)

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.

Follows the patterns of some of the previous PRs, i.e.

- flutter#6922
- flutter#6908

The changes in this PR are _mostly_ tests, it was extremely difficult to
just add more tests to the already very leaky `VideoPlayer` abstraction
which had lots of `@VisibleForTesting` methods and other "holes" to
observe state. This PR removes all of that, and adds test coverage where
it was missing.

Namely it:

- Adds a new class, `VideoAsset`, that builds and configures the media
that `ExoPlayer` uses.
- Removes all "testing" state from `VidePlayer`, keeping it nearly
immutable.
- Added tests for most of the classes I've added since, which were
mostly missing.

That being said, this is a large change. I'm happy to sit down with
either of you and walk through it.

---

Opening as a draft for the moment, since there is a pubspec change
needing I want to handle first.
auto-submit bot pushed a commit that referenced this pull request Aug 24, 2024
…`setCallback` for suspend/resume lifecycles. (#6989)

_� BLOCKED: I guess this can't land until the new API makes it into stable in a week or two?_

---

Effectively enough towards flutter/flutter#148417, but we still need to document it on flutter.dev.

This is the last _technical_ PR I'll work on towards the plugin work (assuming we don't find additional bugs/issues).

/cc @jonahwilliams @chinmaygarde @johnmccutchan.
LinXunFeng added a commit to LinXunFeng/packages that referenced this pull request Aug 26, 2024
…this time with `setCallback` for suspend/resume lifecycles. (flutter#6989)"

This reverts commit 62b4cb0.
auto-submit bot pushed a commit that referenced this pull request Aug 26, 2024
abdelaziz-mahdy added a commit to abdelaziz-mahdy/packages that referenced this pull request Aug 26, 2024
…ucer, this time with setCallback for suspend/resume lifecycles" (flutter#7497)"

This reverts commit f61a98a.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autosubmit Merge PR when tree becomes green via auto submit App p: video_player platform-android
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants