Here is my theory based on a quick scan of the frame code.
The canvas lock operation (eventually) calls the Surface::lock() code ( here ). This has a piece of code that reads:
if (!mConnectedToCpu) { int err = Surface::connect(NATIVE_WINDOW_API_CPU);
This is the connection of the "processor manufacturer", that is, the code that runs on the processor and generates graphic data, to the producer side of the buffer queue, which is fed to the surface. This manufacturer is not disabled in unlockAndPost() . In fact, you can find the disconnect call in the Surface destructor, which is a bit late for your purposes.
You cannot have two producers in the same buffer queue, so when you pass Surface to the MediaCodec decoder, it cannot connect.
I believe that you have several options:
- Remove surface using OpenGL ES. When you destroy the
EGLSurface , it will shut down. To do this, you need to configure EGL / GLES and get the EGL release code correctly. - Place an empty rectangle using an approach different from the drawing of
SurfaceView itself (h / t is my office assistant).
For approach # 2, you just need a second view (possibly ImageView ) with the same position and dimensions as the SurfaceView , and fill it with opaque black. The SurfaceView level SurfaceView always underneath everything else (assuming you haven't configured it on top), so the user interface elements will be drawn on top of it. When it's time to start playing the movie, you turn off the other view.
Update: Now you can see approach number 1 in Grafika . In the "Play Movie (SurfaceView)" action, it creates an EGL context, cleans the surface and destroys the context. (You must immediately destroy the EGL context and surface to avoid the "two-producer" problem.)
fadden
source share