androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.69k stars 405 forks source link

setVideoEffects can take effect immediately #1717

Open GavinChu opened 1 month ago

GavinChu commented 1 month ago

[REQUIRED] Use case description

Before the player is prepared, setVideoEffect has been called to set an effect. When playback is paused, we call setVideoEffect again to update the effect chain:

We hope that the current screen will take effect immediately after calling setVideoEffect.

I took a preliminary look at the cause of the problem:

  1. After MediaCodec releases a frame, it cannot send the same frame to ExternalTextureManager again.
  2. The frame in ExternalTextureManager is released after being processed by the next GlShaderProgram.
  3. setVideoEffect will trigger ExternalTextureManager#signalEndOfCurrentInputStream and reconfigure the special effects chain.

Proposed solution

I can't think of a feasible solution for the time being. Do you have a plan or solution?

claincly commented 1 month ago

This is a known improvement and we have tracked it internally, but we don't have a timeline for it yet.

It's quite complexed to fix this, I had a prototype and here's roughly the steps to do it:

GavinChu commented 1 month ago

Thanks for your reply, your prototype is great.

I further analyzed and found some interesting problems:

  1. Cache inside the special effects chain Every time a GlShaderProgram is added, a FrameConsumptionManager is connected, and the FrameConsumptionManager can cache frames, which is basically 1 when playing the preview. This will cause FinalShaderProgramWrapper to render only one frame, but ExternalTextureManager may have advanced many frames. In this way, when caching unprocessed frames at the beginning of the processing pipeline, more frames need to be cached, which may affect memory.

  2. SurfaceTexture frames will be released As I said before, updating the special effects chain will trigger ExternalTextureManager#signalEndOfCurrentInputStream, which will execute removeAllSurfaceTextureFrames to clear all cached frames in SurfaceTexture, and cause ExternalTextureManager to never get these frames again.

claincly commented 1 month ago
nesyou01 commented 1 month ago

Same issue