Android Camera2 + OpenGL离屏渲染示例_camerax+opengl 离屏渲染
-
初始化EGL环境
// 创建带 EGL 环境的 GL 线程class GLThread : HandlerThread(\"GLThread\") { private lateinit var eglDisplay: EGLDisplay private lateinit var eglContext: EGLContext private lateinit var handler: Handler override fun onLooperPrepared() { super.onLooperPrepared() initEGL() handler = Handler(looper) } private fun initEGL() { // 1. 获取 EGL Display eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY) // 2. 初始化 EGL val version = IntArray(2) EGL14.eglInitialize(eglDisplay, version, 0, version, 1) // 3. 选择配置 val configs = arrayOfNulls<EGLConfig>(1) val configAttribs = intArrayOf( EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT, EGL14.EGL_RED_SIZE, 8, EGL14.EGL_GREEN_SIZE, 8, EGL14.EGL_BLUE_SIZE, 8, EGL14.EGL_NONE ) EGL14.eglChooseConfig(eglDisplay, configAttribs, 0, configs, 0, 1, intArrayOf(0), 0) // 4. 创建 EGL Context val contextAttribs = intArrayOf( EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE ) eglContext = EGL14.eglCreateContext( eglDisplay, configs[0], EGL14.EGL_NO_CONTEXT, contextAttribs, 0 ) // 5. 创建虚拟 Surface (离屏渲染) val surfaceAttribs = intArrayOf(EGL14.EGL_WIDTH, 1, EGL14.EGL_HEIGHT, 1, EGL14.EGL_NONE) val eglSurface = EGL14.eglCreatePbufferSurface(eglDisplay, configs[0], surfaceAttribs, 0) // 6. 绑定上下文 EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) } fun runOnGLThread(runnable: Runnable) { handler.post { // 确保在当前线程绑定上下文 EGL14.eglMakeCurrent(eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, eglContext) runnable.run() } }}
-
在 GL 线程中初始化 SurfaceTexture
// 创建 GL 线程val glThread = GLThread().apply { start() }// 等待线程准备就绪Thread.sleep(300) // 简化的等待机制,实际应用中应使用回调// 在 GL 线程中创建 SurfaceTexturelateinit var mSurfaceTexture: SurfaceTextureglThread.runOnGLThread { // 在有效的 GL 环境中创建纹理 val textureIds = IntArray(1) GLES30.glGenTextures(1, textureIds, 0) GLES30.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureIds[0]) // 创建绑定到纹理的 SurfaceTexture mSurfaceTexture = SurfaceTexture(textureIds[0]).apply { setDefaultBufferSize(width, height) // 注意:监听器内部操作将在 GL 线程执行 setOnFrameAvailableListener({ surfaceTexture -> Log.i(TAG, \"onFrameAvailable in GL context\") try { surfaceTexture.updateTexImage() // 现在可以安全调用 // 可选:获取变换矩阵 val transformMatrix = FloatArray(16) surfaceTexture.getTransformMatrix(transformMatrix) // 处理帧数据... } catch (e: Exception) { Log.e(TAG, \"Error updating texture\", e) } }, null) // 不指定 Handler,使用当前线程 }}
-
在 Camera 配置中使用 Surface
// 创建 Surface 供相机使用val mSurface = Surface(mSurfaceTexture)// 配置相机输出目标mCaptureRequestBuild?.addTarget(mSurface)outputConfiguration.add(OutputConfiguration(mSurface))
-
注意事项
-
SurfaceTexture 的创建和销毁必须在同一个线程
-
updateTexImage() 必须在创建 SurfaceTexture 的线程调用
-
资源释放
fun release() { glThread.runOnGLThread { mSurfaceTexture.release() // 释放 EGL 资源 EGL14.eglDestroyContext(glThread.eglDisplay, glThread.eglContext) } glThread.quitSafely()}
-