5

I'm using Exoplayer and an GL SurfaceTexture (from a TextureView) to display a video. I'm reusing the same surface among video play.

I release the player and instantiate a new one. When the SurfaceTexture is displayed the second time, it display the old Texture from last video until the player begin to play and fill the Surface with black.

I'm looking for a way to draw a black rect to fill the surface with black, but unable to achieve this.

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Hugo Gresse
  • 17,195
  • 9
  • 77
  • 119

4 Answers4

18

Using @fadden link on Grafika, I've made my own script to clear the surface. It's compatible from API 16.

GIST

/**
 * Clear the given surface Texture by attaching a GL context and clearing the surface.
 * @param texture a valid SurfaceTexture
 */
private void clearSurface(SurfaceTexture texture) {
    if(texture == null){
        return;
    }

    EGL10 egl = (EGL10) EGLContext.getEGL();
    EGLDisplay display = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
    egl.eglInitialize(display, null);

    int[] attribList = {
            EGL10.EGL_RED_SIZE, 8,
            EGL10.EGL_GREEN_SIZE, 8,
            EGL10.EGL_BLUE_SIZE, 8,
            EGL10.EGL_ALPHA_SIZE, 8,
            EGL10.EGL_RENDERABLE_TYPE, EGL10.EGL_WINDOW_BIT,
            EGL10.EGL_NONE, 0,      // placeholder for recordable [@-3]
            EGL10.EGL_NONE
    };
    EGLConfig[] configs = new EGLConfig[1];
    int[] numConfigs = new int[1];
    egl.eglChooseConfig(display, attribList, configs, configs.length, numConfigs);
    EGLConfig config = configs[0];
    EGLContext context = egl.eglCreateContext(display, config, EGL10.EGL_NO_CONTEXT, new int[]{
            12440, 2,
            EGL10.EGL_NONE
    });
    EGLSurface eglSurface = egl.eglCreateWindowSurface(display, config, texture,
            new int[]{
                    EGL10.EGL_NONE
            });

    egl.eglMakeCurrent(display, eglSurface, eglSurface, context);
    GLES20.glClearColor(0, 0, 0, 1);
    GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    egl.eglSwapBuffers(display, eglSurface);
    egl.eglDestroySurface(display, eglSurface);
    egl.eglMakeCurrent(display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
            EGL10.EGL_NO_CONTEXT);
    egl.eglDestroyContext(display, context);
    egl.eglTerminate(display);
}
Hugo Gresse
  • 17,195
  • 9
  • 77
  • 119
  • Sorry, its working now. One have to import `javax.microedition.khronos.egl.*` imports. – Kaidul Jan 08 '16 at 01:59
  • This only worked on the first transition for me. All the subsequent transitions came back with `E/libEGL: eglCreateWindowSurface: native_window_api_connect failed (already connected to another API?)` – Andy M Mar 02 '16 at 11:41
  • 1
    @AndyM: the error indicates that something is already attached to the SurfaceTexture. The player needs to detach from SurfaceTexture before GLES can attach. – fadden Mar 03 '16 at 06:30
2

I'm not familiar with Exoplayer, but I suspect your options are the same as for playback with MediaPlayer, listed in this answer.

Summary:

  • You can attach GLES, clear the Surface, detach GLES (Grafika does this).
  • You can create a one-frame black video and play it.
  • You can create a second, empty View that overlays the first. Hide it while the video is playing, and show it when the video is done.

What you can't do is attach a Canvas and clear it, because once a Canvas is attached it never lets go.

Community
  • 1
  • 1
fadden
  • 51,356
  • 5
  • 116
  • 166
  • Grafika `clearSurface` and sub class use min API 17 for many function such as `EglCore#makeCurrent`. I'm targetting API 16 :/ The other method is really not the way I want to do it. – Hugo Gresse May 27 '15 at 07:51
  • API 17 is needed for EGL 1.4. You can replace the functions with EGL 1.0 equivalents, since you don't need anything 1.4-specific to simply clear the screen. See http://bigflake.com/mediacodec/#ExtractMpegFramesTest for an example of the same code written for both versions of EGL. – fadden May 27 '15 at 16:00
  • u_U I was trying to do it with Canvas but apparently "The trouble is that there is no way to detach a software-based (Canvas) buffer producer." says http://stackoverflow.com/a/24914966/1377145 – Hugo Gresse May 28 '15 at 08:55
  • So I've read http://stackoverflow.com/a/29243067/1377145 and made my own script for API min 16 : https://gist.github.com/HugoGresse/5ca05821444353a823bb – Hugo Gresse May 28 '15 at 10:03
  • I suggest you to include one of the link or I will post it in a new answer. – Hugo Gresse May 29 '15 at 14:42
0

Please call

GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

before draw new frame

desertnaut
  • 57,590
  • 26
  • 140
  • 166
Trung NT Nguyen
  • 403
  • 2
  • 14
0

Super Example code

Definitely works for clearing SurfaceView, used like that:

if (player != null) {
                player.stop();
                player.release();
            }

    if (binding.surfaceView.getHolder().getSurface().isValid()) {
                try {
                    clearSurface(binding.surfaceView);
                }catch (RuntimeException re){
                    re.printStackTrace();
                }
            }
desertnaut
  • 57,590
  • 26
  • 140
  • 166