28 Commits

Author SHA1 Message Date
tonihei
7c274caa1f Update PlayerSurface to directly use AndroidView
The proxy classes Android(Embedded)ExternalSurface just provide a
simple API surface around AndroidView wrapping SurfaceView and
TextureView respectively. However, this prevents accessing the
underlying views directly, which is needed for full lifecycle
tracking by the Player and to access surface size updates (which
are not available when the API is reduced to just `Surface`).

Instead of the proxy classes, we can directly use AndroidView from
PlayerSurface. This allows to call the proper Player APIs to set
SurfaceView or TextureView, so that the Player can keep track of
the view lifecycle and update its internal state and size tracking
accordingly. Because the player keeps tracks of the lifecycle,
none of the callback structure in Android(Embedded)ExternalSurface
is needed, nor are the additional setters for options that are
all default.

PiperOrigin-RevId: 743079058
(cherry picked from commit a1ed0d4ff63fc9e359c8ef1bc53aae43e4b709e3)
2025-04-12 21:08:54 +01:00
jbibik
6b003993a5 [ui-compose] Move ComposeBom from implementation to api
PlayerSurface exposing the Modifier argument means the gradle dependency needs to be stricter

#cherrypick

PiperOrigin-RevId: 734237616
(cherry picked from commit 8dcfa1afbead8d7af1e11e871df9359052f107c6)
2025-03-17 14:00:26 +00:00
jbibik
d9deda7b6e [ui-compose] Add PlaybackSpeedState to control playbackParameters.speed
A state holder that handles interaction with a UI component that toggles through a range of playback speeds.

[demo-compose] Use PlaybackSpeedState to create PlaybackSpeedTextButton

Add the button to the bottom extra controls.

PiperOrigin-RevId: 731449526
(cherry picked from commit addf01b9a84bcea945107b3b2993540ec59fbb54)
2025-03-17 13:56:51 +00:00
jbibik
768f25e163 [ui-compose] Better KDoc formatting
#cherrypick

PiperOrigin-RevId: 731712846
(cherry picked from commit 66ef013cb85e8d7db5679242190202745abf3110)
2025-03-03 16:27:28 +00:00
jbibik
c7fa2c3de6 [ui-compose] Add KDoc to observe() methods for button states
#cherrypick

PiperOrigin-RevId: 731686021
(cherry picked from commit b465cbc22c61acc07875550d1c1f24aa5d080f13)
2025-03-03 16:27:28 +00:00
jbibik
f7479347c0 [ui-compose] Add default value to PlayerSurface's surfaceType
PlayerView's default surface type was also SURFACE_VIEW.

This allows for a simple `PlayerSurface(player)` usage by most developers.

The order of the arguments needs to be changed, because `modifier` should be the first default argument (https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-component-api-guidelines.md#parameter)

PiperOrigin-RevId: 731294658
(cherry picked from commit afea6962c254b6621eee2b8f075d6fdb5283602a)
2025-03-03 16:27:27 +00:00
jbibik
41062d3910 Fix Shuffle and Repeat references in tests
PiperOrigin-RevId: 728309204
(cherry picked from commit 4045acd13b17c68d7fe532cb7ba746517f83f089)
2025-03-03 16:26:30 +00:00
jbibik
d022b570f2 Upgrade Kotlin to 2.0.20
This upgrade allows us to use https://developer.android.com/develop/ui/compose/compiler as specified in https://developer.android.com/jetpack/androidx/releases/compose-kotlin#pre-release_kotlin_compatibility

kotlinOptions is considered deprecated in preference of kotlin.compilerOptions (https://kotlinlang.org/docs/gradle-compiler-options.html#how-to-define-options)

PiperOrigin-RevId: 725266131
2025-02-10 10:32:47 -08:00
rohks
4f3ed2490a Rollback of 99f2a9f152
PiperOrigin-RevId: 723496012
2025-02-05 07:06:09 -08:00
rohks
99f2a9f152 Remove publishing for media3-ui-compose temporarily
Disabled until we find a way to exclude it from media3 Javadoc prebuilts

PiperOrigin-RevId: 721765815
2025-01-31 07:27:59 -08:00
rohks
98f52a1dbb Rollback of 5c3c3b91f3
PiperOrigin-RevId: 720968647
2025-01-29 07:33:56 -08:00
jbibik
52387bb975 [ui-compose] Rename showSurface to coverSurface in PresentationState
This renaming helps prevent the consumer from including `PlayerSurface` in a Compose tree based on `state.showSurface`. This field intuitively felt like the default would be not to show the surface (correct), but had an unintended consequence of not initialising `AndroidExternal(Embedded)Surface` (since the PlayerSurface Composable would be omitted).

To avoid this confusion, the `PresentationState` should communicate to the consumer when the Surface is not ready and hence should be covered with some overlay (shutter) to prevent poor UX from observing Surface resizing/freezing/flickering.

PiperOrigin-RevId: 714951607
2025-01-13 06:59:44 -08:00
jbibik
28027c64fd [ui-compose] Add aspect ratio to PresentationState
It captures the information needed for the UI logic related to rendering of the video track (and later images) to the surface.

The video size will be correct only after the Player decoded the video onto the surface and can't be reliably extracted from MediaItem's metadata. The information about the video's true aspect ratio helps inform the UI elements (such as PlayerSurface Composable) how to customize the Modifiers.

Use this state in demo-compose to show off functionality of changing `PlayerSurface`'s aspectRatio

PiperOrigin-RevId: 714104260
2025-01-10 10:50:53 -08:00
jbibik
79d41aac7e [ui-compose] Fix PlayerSurface's use of Player
The new `currentPlayer` was only used to check the available command. It should also be used for setting and clearing the Surface.

The PlayerSurface was still behaving correctly, perhaps due to the lambda being reevaluated with the new player (since `currentPlayer` is of type MutableState). Which meant it was also using the latest `player` that `PlayerSurface` was recomposed with (in the argument), rather than holding onto the original object.

PiperOrigin-RevId: 713264041
2025-01-08 06:07:14 -08:00
jbibik
2dc6af1fae [ui-compose] Add PresentationState for first-frame info
It captures some information needed for the UI logic related to rendering of the video track (and later images) to the surface.

Supporting `EVENT_RENDERED_FIRST_FRAME` helps improve the UX by covering the surface with an overlay (scrim/shutter) until the first frame is ready. This helps avoid sudden flickering during MediaItem transitions.

PiperOrigin-RevId: 712889568
2025-01-07 06:34:02 -08:00
jbibik
575a2ebbd8 [ui-compose] Add gradle version to androidx.compose.foundation
This will ensure that the new `ui-compose` module gets published on Maven

The fix is not necessary for `demo-effect` and `demo-compose` because they are not publishable

PiperOrigin-RevId: 712555702
2025-01-06 09:34:44 -08:00
jbibik
d8333b37cf Upgrade compose bom to 2024.12.01
The latest version of `androidx.compose.foundation:foundation` fixed an issue where `AndroidEmbeddedExternalSurface` would not reset properly. This in turn prevented PlayerSurface Composable with type `SURFACE_TYPE_TEXTURE_VIEW` from being redrawn after returning to a stopped activity.

PiperOrigin-RevId: 712501647
2025-01-06 06:05:30 -08:00
rohks
5c3c3b91f3 Remove publishing for media3-ui-compose temporarily
This is due to a missing version error for the `androidx.compose.foundation` dependency.

PiperOrigin-RevId: 707944220
2024-12-19 09:54:59 -08:00
rohks
4b26eb2800 Fix lint errors
- Add required mutability flag to `ConnectionStateTest` to fix
  `Missing PendingIntent mutability flag`.
- Suppress `WrongConstant` lint error caused by Kotlin's spread operator
  not propagating the `@IntDef` annotation.

#cherrypick

PiperOrigin-RevId: 707061163
2024-12-17 05:53:19 -08:00
jbibik
beda44520a [ui-compose] Fix PlayerSurface's use of Player
When `PlayerSurface` composable gets a new `Player` object, it should initialise a new Android(Embedded)External Surface with it. However, the lambdas used for that are remembered with the reference to the old Player, even if it has been null'd and released properly.

Android(Embedded)ExternalSurface is an interop - `AndroidView` wrapping `SurfaceView` and `TextureView` under the hood. It uses the `onInit` lambda in its factory to create the View and reuses it on later recompositions, making it a longer-lived object than our Player.

`RememberUpdatedState` acts makes a mutable State out of the Player and always gets its latest value. One can think of it as creating a reference to the Player object and telling the lambdas to always resolve that reference in the moment, rather than hold onto the Player than was passed-by-value.

This change is a precursor to a better lifecycle management of Player and Surface in demo-compose.

PiperOrigin-RevId: 705529626
2024-12-12 09:22:40 -08:00
jbibik
77a215f39c [ui-compose] Check Player commands in PlayerSurface actions
Setting and destroying the Surface should only happen if the `Player` has the required command

PiperOrigin-RevId: 705488781
2024-12-12 06:57:47 -08:00
ibaker
3e94bd6125 Enable lint errors in tests for remaining playback modules
Also fix existing violations

This enables the lint for tests in:
* `decoder-iamf`
* `exoplayer-rtsp`
* `test-exoplayer-playback`
* `test-session-current`
* `ui-compose`

PiperOrigin-RevId: 702728438
2024-12-04 08:08:01 -08:00
ibaker
286273c10e Enable lint in tests for modules that require no fixes
PiperOrigin-RevId: 693313908
2024-11-05 05:40:03 -08:00
jbibik
0270267e08 Add ShuffleButtonState and RepeatButtonState to ui-compose
* Provide a helper Composable for remembering the state instance and launching the listening coroutine that observes the changes in the Player
* Add an example to demo-compose of using Shuffle- and Repeat- ButtonStates inside a Shuffle- and RepeatButton Composable.
* Reformat the MainActivity usage of `Shuffle` and `Repeat` buttons to form extra Player Controls and combine Prev/Play-Pause/Next with Shuffle/Repeat (Minimal controls + Extra controls = `PlayerControls`)

PiperOrigin-RevId: 692939825
2024-11-04 06:12:57 -08:00
jbibik
1b302e879a Add PreviousButtonState and NextButtonState to ui-compose
* Provide a helper Composable for remembering the state instance and launching the listening coroutine that observes the changes in the Player
* Add an example to demo-compose of using Previous- and Next- ButtonStates inside a Previous- and NextButton Composable.
* Reformat the MainActivity usage of `Previous`, `PlayPause`, `Next` buttons to form Minimal Player Controls

PiperOrigin-RevId: 691943147
2024-10-31 14:52:38 -07:00
jbibik
676a3872a5 Add PlayPauseButtonState to ui-compose
Provide a helper Composable for remembering the state instance and launching the listening coroutine that observes the changes in the Player

Add an example to demo-compose of using PlayPauseButtonState inside a PlayPauseButton Composable.

The smart State object has been deemed a preferred solution over collecting Flows due to queuing/timing/buffering limitations. Instead, it uses the new `Player.listen` suspending extension function to catch the relevant events.

PiperOrigin-RevId: 691879975
2024-10-31 11:42:14 -07:00
jbibik
7da71f792b Move PlayerSurface from demo-compose to media3-ui-compose
The new `media3-ui-compose` module does not have any Material library dependencies, but will rely on androidx.compose + foundation/runtime/ui and other non-theming/opinionated libraries. Surface handling is one such usecase.

PiperOrigin-RevId: 689004504
2024-10-23 10:00:07 -07:00
jbibik
a645f704b8 Create a new media3-ui-compose module
It will be used for UI components built with Jetpack Compose

`implementation("androidx.media3:media3-ui-compose:1.X.Y")`

PiperOrigin-RevId: 688595899
2024-10-22 10:14:26 -07:00