Android 播放器SurfaceView播放后(前)清屏 Clear video frame from surfaceview on video complete, 播放开始出现上一次播放的残留画面

Android MediaPlayer某些播放场景下,由于SurfaceView的使用方式的问题,可能遇到 播放开始出现上一次播放的残留画面,为此需要在每次播放开始或结束时,对SurfaceView做清屏clear

 

方式一:  注意可能导致的问题 You can't clear it with Canvas draw commands because that will prevent you from playing movies on that surface again.

1 Paint paint = new Paint();
2 paint.setColor(0xff000000);
3 Canvas canvas = surface.lockCanvas(null);
4 canvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
5 canvas.drawRect(0, 0, 0 + canvas.getWidth(), 0 + canvas.getHeight(), paint);
6 surface.unlockCanvasAndPost(canvas);

使用如下这种方式,lockCanvas后清空再unlockCanvasAndPost,会导致后续播放出问题,也就是如果当前要清空的SurfaceView后续要去作为player的输出surface就不能采用这种方式了

原因:参考 https://stackoverflow.com/questions/24902114/mediaplayer-cannot-render-to-textureview-after-image-render/24914966#24914966

//You can't do this, due to a limitation of the Android app framework (as of //Android 4.4 at least).

//The SurfaceTexture that underlies the TextureView is a buffer consumer. //The MediaPlayer is one example of a buffer producer, Canvas is another. //Once you attach a producer, you have to detach it before you can attach //a second producer.

//The trouble is that there is no way to detach a software-based (Canvas) //buffer producer. There could be, but isn't. So once you draw with Canvas, //you're stuck. (There's a note to that effect here.)

//You can detach a GLES producer. For example, in one of Grafika's video //player classes you can find a clearSurface() method that clears the //surface to black using GLES. Note the EGL context and window are //created and explicitly released within the scope of the method. You could //expand the method to show an image instead.

 

方式二:使用GLES 来清除

https://stackoverflow.com/questions/25660994/clear-video-frame-from-surfaceview-on-video-complete

https://github.com/autumnqin/grafika/blob/master/src/com/android/grafika/PlayMovieSurfaceActivity.java

 

直接上代码:自己体会哈哈哈

 1 import android.opengl.EGL14;
 2 import android.opengl.EGLConfig;
 3 import android.opengl.EGLContext;
 4 import android.opengl.EGLDisplay;
 5 import android.opengl.EGLExt;
 6 import android.opengl.EGLSurface;
 7 import android.opengl.GLES20;
 8 
 9 //=====
10 
11 /**
12  * Clears the playback surface to black.
13  */
14 private void clearSurface(Surface surface) {
15     EGLDisplay display = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
16     int[] version = new int[2];
17     EGL14.eglInitialize(display, version, 0, version, 1);
18 
19     int[] attribList = {
20             EGL14.EGL_RED_SIZE, 8,
21             EGL14.EGL_GREEN_SIZE, 8,
22             EGL14.EGL_BLUE_SIZE, 8,
23             EGL14.EGL_ALPHA_SIZE, 8,
24             EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
25             EGL14.EGL_NONE, 0,
26             EGL14.EGL_NONE
27     };
28     EGLConfig[] configs = new EGLConfig[1];
29     int[] numConfigs = new int[1];
30     EGL14.eglChooseConfig(display, attribList, 0, configs, 0, configs.length, numConfigs, 0);
31 
32     EGLConfig config = configs[0];
33     EGLContext context = EGL14.eglCreateContext(display, config, EGL14.EGL_NO_CONTEXT, new int[]{
34             EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
35             EGL14.EGL_NONE
36     }, 0);
37 
38     EGLSurface eglSurface = EGL14.eglCreateWindowSurface(display, config, surface,
39             new int[]{
40                 EGL14.EGL_NONE
41             }, 0);
42 
43     EGL14.eglMakeCurrent(display, eglSurface, eglSurface, context);
44     GLES20.glClearColor(0, 0, 0, 1);
45     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
46     EGL14.eglSwapBuffers(display, eglSurface);
47     EGL14.eglDestroySurface(display, eglSurface);
48     EGL14.eglMakeCurrent(display, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
49     EGL14.eglDestroyContext(display, context);
50     EGL14.eglTerminate(display);
51 }

 

每次播放结束时都销毁SurfaceView 是不会出现上次播放的残留画面的,也就不用考虑清屏了

 

posted on 2021-07-02 14:12  二的次方  阅读(3917)  评论(2编辑  收藏  举报