AlynxZhou / alynx-live-wallpaper

An android app that allows you choose a video as wallpaper.
https://livewallpaper.alynx.xyz/
Apache License 2.0
94 stars 37 forks source link

Bug: unable to show videos with transparency (WEBM) #20

Open AndroidDeveloperLB opened 2 years ago

AndroidDeveloperLB commented 2 years ago

The background becomes gray, instead of letting us choose which color to show behind (or at least have it black).

Example of such a file can be found here:

https://simpl.info/videoalpha/

Attached a sample file from there.

Video alpha channel.zip

AlynxZhou commented 2 years ago

I am afraid that there is no layer behind wallpaper, so you can never control what color it shows with a transparent video.

It is meaningless to make wallpaper transparent, maybe you should edit the video on PC to add background color for it.

AndroidDeveloperLB commented 2 years ago

@AlynxZhou It's not meaningless if you show something behind. Can you please show how to add a layer in code? For example a color or an image? Maybe even show it while the video is loaded.

I don't even know if it's possible for ExoPlayer (or the Android framework) to handle transparent colors of video files. It's weird because Chrome can do it fine (you can check via the website)... Also checking the Internet, sadly the only video file that supports transparency and is supported on Android is WEBM.

Can you please check it out, if it's possible ?

AlynxZhou commented 2 years ago

@AlynxZhou It's not meaningless if you show something behind. Can you please show how to add a layer in code? For example a color or an image?

It's not about how to add a layer because there is actually no such thing called "layer" under your wallpaper. The only thing you can do to show color or images under video is to draw them with OpenGL under video's z-axis. And to archieve this 1. you need to add UI elements to let user set image in app, 2. you need to implement the actual draw function.

I don't think those things are useful, this app is not a video composition app, and most videos on Internet are not transparent. If you really want to show image under transparent video, it's easy to edit your video on PC, instead of drawing the image 60fps on your mobile phone. It maybe also make users confused because they don't understand why there's a image chooser for an video wallpaper app?

Maybe even show it while the video is loaded.

Videos are loaded from disk, and it's fast to read and decode video on modern SoCs, so there is simply no "loading time" for user.

I don't even know if it's possible for ExoPlayer (or the Android framework) to handle transparent colors of video files. It's weird because Chrome can do it fine (you can check via the website)... Also checking the Internet, sadly the only video file that supports transparency and is supported on Android is WEBM.

Can you please check it out, if it's possible ?

Currently we have nothing about ExoPlayer, it's not used to draw wallpaper, it's only used to decode video frames (which means if your video is transparent, ExoPlayer should just return transparent). The wired color you see has nothing with this app, it might be the default color of OpenGL implementation. I just ignore it because most videos are not transparent.

AndroidDeveloperLB commented 2 years ago

I didn't say the app should compose a new video. I asked how to show this kind of content as an optional layer behind the video. Maybe I could even show it instead of the video, so the app could choose to show color/image/video or a combination of color/image and the video on top.

This could be useful not just for transparent videos, but also for when you wish to avoid center-crop of the video, meaning you'd wish to show 100% of it on a single page, so you need to show something around (unless the video is of the exact resolution of the device, of course).

About ExoPlayer, are you saying that it creates a bitmap, one frame after another, to be sent to the live wallpaper?

AlynxZhou commented 2 years ago

I didn't say the app should compose a new video. I asked how to show this kind of content as an optional layer behind the video.

"as an optional layer behind the video" just means composite when drawing. Even if you create a class Layer, you need to draw in your self, which we called composite. Layer does not draw itself if you don't manually composite it with video. Forget about your layer, it's only an abstraction, not actually exists until you code it yourself.

Maybe I could even show it instead of the video, so the app could choose to show color/image/video or a combination of color/image and the video on top.

It's horrible to fight against Android UI, so I just don't want to make those complex selectors myself.

This could be useful not just for transparent videos, but also for when you wish to avoid center-crop of the video, meaning you'd wish to show 100% of it on a single page, so you need to show something around (unless the video is of the exact resolution of the device, of course).

My suggestion is just using a video that has similar ratio to phone screen.

About ExoPlayer, are you saying that it creates a bitmap, one frame after another, to be sent to the live wallpaper?

Yes, it has nothing with actually drawing.

AndroidDeveloperLB commented 2 years ago

Really? Where is the bitmap? I don't think i see it in code. Can you please point me to the part that I can draw the background layer, too? As for the suggestion of a video to choose, this is on user's side, and most videos aren't 100% the same as the resolution of the device. On some launchers the user could even change the orientation of them (meaning including the wallpaper).

AlynxZhou commented 2 years ago

Really? Where is the bitmap? I don't think i see it in code.

https://github.com/AlynxZhou/alynx-live-wallpaper/blob/master/app/src/main/java/xyz/alynx/livewallpaper/GLES30WallpaperRenderer.java#L131

https://github.com/AlynxZhou/alynx-live-wallpaper/blob/master/app/src/main/java/xyz/alynx/livewallpaper/GLES30WallpaperRenderer.java#L218

https://github.com/AlynxZhou/alynx-live-wallpaper/blob/master/app/src/main/java/xyz/alynx/livewallpaper/GLES30WallpaperRenderer.java#L316-L331

Can you please point me to the part that I can draw the background layer, too?

https://github.com/AlynxZhou/alynx-live-wallpaper/blob/master/app/src/main/java/xyz/alynx/livewallpaper/GLES30WallpaperRenderer.java

Added enable alpha blend, create another texture object, calculate another matrix to correctly crop image, and translate it to lower of the video rect using matrix, then pass those to shader adain and call shader again to draw it.

For color you may need another shader or modify current shader, because current shader only accept textures.

As for the suggestion of a video to choose, this is on user's side, and most videos aren't 100% the same as the resolution of the device.

Resolution does not matter, ratio matters, and why not edit it on PC?

On some launchers the user could even change the orientation of them (meaning including the wallpaper).

Make a square video and use it. There is no perfect way to show video on both orientation, either cropping or only showing it in center is not perfect, I prefer cropping.

AndroidDeveloperLB commented 2 years ago

Resolution determines both quality and aspect-ratio. From resolution you can know the aspect-ratio, and how good the content will look like on the device in terms of quality. when users download images, they don't often look/calculate at the aspect ratio compared to the device, and what they see is resolution. It's easier to find by resolution. I don't think there are websites that give you the option to search by aspect-ratio, either. But technically I get your point. Out of the resolution, what's important is the aspect ratio in this matter.

As for the links to the code, thank you. Wouldn't creation of Bitmaps mean it constantly have to do GC ? Or is it efficient and uses a buffer (maybe double-buffer), meaning a single instance of a Bitmap that keeps updating ?

If I fail, would you consider creating a fork of this, showing how it's done? I can donate you a bit if it will encourage you... It's just that I'm less familiar with this kind of programming (OpenGL etc...).

AndroidDeveloperLB commented 2 years ago

Looking a bit in the code you've shown me, I think that each time there is a new frame, updatedFrame is increased, and then on onDrawFrame , it gets the new frame and binds to it using surfaceTexture.updateTexImage() . Is it true? Sadly my knowledge of OpenGL is useless, as it was of the first version, and from OpenGL 2, everything changed. Still seems like a lot of boilerplate code to me though. I hope I can find how to add what I wrote.