androidGPUImage性能升级成纯GPU+ GPUImageRenderer解析 (一)

xiaoxiao2021-02-28  81

GPUImage 是我滤镜相机的启蒙框架  但是用着用着发现这个框架在相机方面有点慢    opengl不该这么慢的    至于原因一起看GPUImage核心类GPUImageRenderer  

首先我们到这个类先command+f搜一下onPreviewFrame   做过相机的小伙伴都知道这个是相机的回调方法    当新出现一帧图片的时候数据就会返回到第一个参数(byte[] data)里

@Override public void onPreviewFrame(final byte[] data, final Camera camera) { final Size previewSize = camera.getParameters().getPreviewSize(); if (mGLRgbBuffer == null) { mGLRgbBuffer = IntBuffer.allocate(previewSize.width * previewSize.height); } if (mRunOnDraw.isEmpty()) { runOnDraw(new Runnable() { @Override public void run() { GPUImageNativeLibrary.YUVtoRBGA(data, previewSize.width, previewSize.height, mGLRgbBuffer.array()); mGLTextureId = OpenGlUtils.loadTexture(mGLRgbBuffer, previewSize, mGLTextureId); camera.addCallbackBuffer(data); if (mImageWidth != previewSize.width) { mImageWidth = previewSize.width; mImageHeight = previewSize.height; adjustImageScaling(); } } }); } } 

看了这个回调  我们就知道GPUImage做了什么   把每一帧拿出来  拿出来的是YUV格式的图  转化成RBGA的图然后  扔到纹理缓存中  返回一个纹理id就是mGLTextureId 

然后我们搜下一个方法 

@Override public void onDrawFrame(final GL10 gl) { 。。。 mFilter.onDraw(mGLTextureId, mGLCubeBuffer, mGLTextureBuffer); 。。。 } 这个方法就是GlSurfaceView每次显示新的图片的时候回调的方法  在这里使用了上面的相机每帧图片数据  就是这个纹理mGLTextureId  

好到了这里我发现逻辑很通顺啊   没什么问题    但是我拿着我的红米700元手机就是很卡  没有自带相机快咋办   查了一些资料后我对他作出了优化

先分析问题为什么很卡     应为每一帧图片他都拿了出来在用cpu把YUV转化BGRA的图片  再转成纹理ID给mFiler用  人眼每秒识别24帧  再加上相机分辨率暂定1600*1200 就意味着cpu每秒至少要跑24*1600*1200大小的数组   哪能不慢吗 

接着就是解决方案 

/** * 创建OES纹理id * * @return */ public static int createOESTextureID() { final int[] tex = new int[1]; GLES20.glGenTextures(1, tex, 0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); return tex[0]; } 这个纹理属性很关键 GLES11Ext.GL_TEXTURE_EXTERNAL_OES就是个外部输入设备属性

public void initCamera(final Camera camera, SurfaceTexture.OnFrameAvailableListener listener) { // 生成纹理Id mGLTextureId = GLTextureUtil.createOESTextureID(); mGLTextureIdText = GLTextureUtil.createOESTextureID(); // 通过纹理Id,创建SurfaceTexture(该mSurfaceTexture与Camera进行绑定) mSurfaceTexture = new SurfaceTexture(mGLTextureId); mSurfaceTexture.setOnFrameAvailableListener(listener); try { camera.setPreviewTexture(mSurfaceTexture); } catch (IOException e) { e.printStackTrace(); } camera.startPreview(); } 这是我重载的设置Camera的方法   创建个oes的纹理id再生成SurfaceTexture塞给Camera    之后每次新的一帧图片生成就会直接写在这个纹理ID里  不用去cpu再转一次    setOnFrameAvailableListener里的listener我这么写的 new SurfaceTexture.OnFrameAvailableListener() { @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { mGlSurfaceView.requestRender(); } } 就是通知GLSurafecView更新视图

下一章讲OES属性的纹理ID对应的着色器怎么写

最后你的滤镜相机就会快的飞起  

http://blog.csdn.net/u010831488/article/details/71404412

转载请注明原文地址: https://www.6miu.com/read-96586.html

最新回复(0)