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就不能采用这种方式了
//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
直接上代码:自己体会哈哈哈
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 是不会出现上次播放的残留画面的,也就不用考虑清屏了