media icon indicating copy to clipboard operation
media copied to clipboard

Video is cut on the edge when using Compose and uses RESIZE_MODE_ZOOM - Only Android 14

Open jdelga opened this issue 1 year ago • 10 comments

Version

Media3 1.2.1

More version details

Reproduced also in latest version of Exoplayer, and Media3 1.3.0-beta01

Devices that reproduce the issue

Any device or emulator running Android 14

Devices that do not reproduce the issue

Any device or emulator running Android 13 or lower

Reproducible in the demo app?

No

Reproduction steps

Reproduced in Demo Project: Demo project

Just open the app and check the video dimensions

The bug happens in the following conditions:

  • PlayerView is inside an AndroidView in Compose
  • The Composable function is inside a component with fillMaxSize() modifier
  • The video is using UnstableApi RESIZE_MODE_ZOOM

(It also happens in RESIZE_MODE_FIXED_HEIGHT, RESIZE_MODE_FIXED_WIDTH and RESIZE_MODE_FIT, but does not happen with RESIZE_MODE_FILL)

Expected result

The video is not cut on the edge.

Actual result

The video is cut:

Captura de pantalla 2024-02-22 a las 13 33 49

You can check closer to the status bar to identify the issue

Captura de pantalla 2024-02-22 a las 13 13 05

Just change the resizeMode in the demo app to check the issue with other resize modes: https://github.com/jdelga/Media3ComposeDemo/blob/main/app/src/main/java/com/javierdelgado/media3composedemo/VideoScreen.kt#L21

Media

Not applicable, but a media item is already added to the demo project

Bug Report

  • [X] You will email the zip file produced by adb bugreport to [email protected] after filing this issue.

Comments

It would be very useful to add full support to resizeMode (currently as UnstableApi) and add a proper Compose player.

jdelga avatar Feb 22 '24 12:02 jdelga

In the bugreport there is an AspectRatioFrameLayout that doesn't fit with its parent PlayerView:

            androidx.compose.ui.platform.ComposeView{56f1745 V.E...... ........ 0,0-1080,2270}
              androidx.compose.ui.platform.AndroidComposeView{6ba67ab VFED..... ........ 0,0-1080,2270}
                androidx.compose.ui.platform.AndroidViewsHandler{745e9fd V.E...... ......ID 0,0-1080,2270}
                  androidx.compose.ui.viewinterop.ViewFactoryHolder{5747a8 V.E...... ......I. 0,0-1080,2270}
                    androidx.media3.ui.PlayerView{84a4c6d V.E...... ........ 0,0-1080,2270}
                      androidx.media3.ui.AspectRatioFrameLayout{439f0a2 V.E...... ........ -58,0-1139,2270 #7f07003d app:id/exo_content_frame}

jdelga avatar Feb 22 '24 13:02 jdelga

According to: https://github.com/androidx/media/blob/d13a0f4ec62ca092b79746a5725b62a3244cc5b4/libraries/ui/src/main/java/androidx/media3/ui/AspectRatioFrameLayout.java#L174-L209

RESIZE_MODE_FILL is actually not doing any resizing ("Ignore target aspect ratio" branch)

RESIZE_MODE_ZOOM in the case of your media will increase the width (since AspectDeformation>0)

And you are right, AspectRatioFrameLayout will be bigger than PlayerView, but that's ok, because the parent will end up cropping it.

Pixel5 API34 Pixel5 API30
Android 14 11
View
width 1080 1080
height 2138 2072
View aspect ratio 0.505145 0.5212355
Video aspect ratio 0.52734375 0.52734375
AspectDeformation 0.043945312 0.01171875
New view width 1127 1092
AspectRatioFrameLayout
x -8dp -2dp
y 49dp 49p
width 1127/2.75=409 1092/2.75=397
heigth 2138/2.75=777 2072/2.75=753

Given that the screen width is only 392dp, Android tries to position the ARFL in the centre by:

  • leaving 8dp and 9dp on each side (8+392+9 = 409)
  • leaving 2dp and 3dp on each side (2+392+3 = 397)

Screenshot 2024-03-19 at 22 10 56

My guess is that since the stretch in Android14 is bigger, there is some delay in stretching the view?

I managed to reproduce your issue, but it disappears so quickly that I cannot catch the setup in the state where the width:

https://github.com/androidx/media/assets/19333204/80e6befd-e8d0-43f8-bfd4-e211bc630d75

oceanjules avatar Mar 19 '24 22:03 oceanjules

Thank you very much for testing it. Have you tried the uploaded Demo Project? I am using useController = false and the video is not adjusted to its correct location. The controller may be interacting somehow and after it appears, the video is adjusted.

useController = false

https://github.com/androidx/media/assets/36664452/9c0087cb-4a9e-4b1b-a871-39a81c11d379

useController = true

https://github.com/androidx/media/assets/36664452/8f8b6d7c-0dcf-4fca-8b5c-5b0b001b5eee

jdelga avatar Mar 20 '24 09:03 jdelga

I'm +1 - ing this issue. I ran into this earlier this week where my video would be rendered stretched and it seems to be related. Setting 'controllerAutoShow' to true triggers a re-layout of the PlayerView, thus correcting its size.

Below is a sample project which is essentially this box in an activity;

            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .background(Color.Black),
                contentAlignment = Alignment.Center
            ) {
                AndroidView(
                    factory = { ctx ->
                        PlayerView(ctx).apply {
                            useController = true
                            // Setting controllerAutoShow to true fill show the controller automatically
                            // Having it auto-show triggers a re-layout of the PlayerView
                            // which causes the layout to be corrected
                            controllerAutoShow = false
                            resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
                        }
                    },
                    update = {
                        it.player = exoPlayer
                        exoPlayer.setMediaItem(
                            MediaItem.fromUri("https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
                        )
                        exoPlayer.playWhenReady = true
                        exoPlayer.prepare()
                    },
                )
            }

media3sample.zip

MaxMaesLW avatar Mar 29 '24 10:03 MaxMaesLW

I'm also seeing this issue on my app. it seems 100% linked to having a parent with fillMaxSize(). In my case, I have a single activity with a NavHost() that handles the whole navigation. Therefore, this issue is a big problem as the only solution I've found is to create a second activity to host the PlayerView

Also, please note that it happens a lot on Android 14 devices, but ALSO on Android 13 and lower, when playing HLS and when a track change occurs (linked to available bandwidth).

phcannesson avatar Apr 02 '24 14:04 phcannesson

I'm also facing this issue. resizeMode is set to AspectRatioFrameLayout.RESIZE_MODE_ZOOM. parent view is set to fillMaxSize(). Is there a workaround for now to make the PlayerView fill the entire screen on all devices without changing the aspect ratio?

f4bsn avatar Apr 11 '24 14:04 f4bsn

I'm also facing this issue. resizeMode is set to AspectRatioFrameLayout.RESIZE_MODE_ZOOM. parent view is set to fillMaxSize(). Is there a workaround for now to make the PlayerView fill the entire screen on all devices without changing the aspect ratio?

This one might work https://github.com/androidx/media/issues/1237#issuecomment-2049992538

promanowicz avatar Apr 20 '24 22:04 promanowicz

@jdelga Could you try setting app:surface_type="texture_view" to see if we can isolate this issue as a SurfaceView in Compose issue instead?

oceanjules avatar May 07 '24 13:05 oceanjules

As you can see in the Demo project, the issue happens when using a full Compose implementation. The only AndroidView is added to work with PlayerView inside compose. Where should I place the attribute surfaceType for the PlayerView in code ?

jdelga avatar May 08 '24 10:05 jdelga

My current solution is use fillXXX in the specific case. For example. if i want RESIZE_MODE_FIXED_WIDTH i use the container with fillMaxWith() and not fillMaxSize(). that works to solve my use cases.

fresnohernandez99 avatar May 25 '24 04:05 fresnohernandez99

I'm also facing this issue. resizeMode is set to AspectRatioFrameLayout.RESIZE_MODE_ZOOM. parent view is set to fillMaxSize(). Is there a workaround for now to make the PlayerView fill the entire screen on all devices without changing the aspect ratio?

This one might work #1237 (comment)

I used this solution in my compose project, it works perfectly.

First, i created a new layout called video_player.xml in the layout directory of my project:

<?xml version="1.0" encoding="utf-8"?>

<androidx.media3.ui.PlayerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/custom_video_player"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:surface_type="texture_view"
    app:use_controller="false" />

As mentioned by @promanowicz, the property app:surface_type="texture_view" is the key to solve the issue.

Then i inflated that file in compose:

@Composable
fun VideoComponent() {
    val context = LocalContext.current

    val exoplayer = remember {
        ExoPlayer.Builder(context)
            .setTrackSelector(trackSelector)
            .build()
            .apply {
                setMediaItem(MediaItem.fromUri("your_video_url"l))
                prepare()
                play()
                playWhenReady = true
            }
    }

    var exoPlayerView = remember {
        val view = View.inflate(context, R.layout.video_player, null)
        val playerView = view.findViewById<PlayerView>(R.id.custom_video_player)
        playerView.resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
        playerView.player = exoplayer
        playerView
    }

    AndroidView(
        modifier = Modifier.fillMaxSize()
        factory = { exoPlayerView }
    )
}

emenjivar avatar Jun 13 '24 02:06 emenjivar

This is almost certainly a duplicate of https://github.com/androidx/media/issues/1237, which is fixed in Android 15 and a workaround for Android 14 is in https://github.com/androidx/media/commit/968f72fec6d5452a34976824ac822782eeeb8f45 which will be released in media3 1.4.0-rc01.

icbaker avatar Jun 20 '24 11:06 icbaker