You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Camera2 API中setPreviewTexture()的等效API及替代方案咨询

Camera2 API替代Camera.setPreviewTexture()的方案

在Camera2 API里,确实没有直接对应旧API的setPreviewTexture()方法——因为Camera2采用了更灵活的CaptureSession+Surface架构来管理相机输出。不过实现类似功能的思路很清晰,核心是把你的GL Texture包装成SurfaceTexture,再转换成Surface,然后将这个Surface作为相机预览的输出目标之一。

下面是具体的步骤和关键代码:

1. 创建并配置SurfaceTexture

首先,用你已经生成好的GL纹理ID初始化SurfaceTexture,并设置和相机输出匹配的缓冲区尺寸(这个尺寸最好从相机的CameraCharacteristics里获取官方支持的预览尺寸,避免画面拉伸):

// 假设glTextureId是你从GL程序中生成的有效纹理ID
SurfaceTexture surfaceTexture = new SurfaceTexture(glTextureId);
// 设置为相机支持的预览尺寸,previewWidth/previewHeight是提前获取的合适值
surfaceTexture.setDefaultBufferSize(previewWidth, previewHeight);

2. 将SurfaceTexture转为Surface

Camera2的CaptureSession只接受Surface作为输出目标,所以需要把上面的SurfaceTexture包装成Surface:

Surface previewSurface = new Surface(surfaceTexture);

3. 配置CameraCaptureSession并设置预览请求

在创建CameraCaptureSession时,把这个Surface加入到输出Surface列表中;之后创建预览的CaptureRequest,并将这个Surface设为目标,相机的预览帧就会输出到你的SurfaceTexture上:

// 假设已获取到CameraDevice实例cameraDevice,以及用于相机操作的后台Handler
cameraDevice.createCaptureSession(Arrays.asList(previewSurface), 
    new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            try {
                // 创建预览请求Builder
                CaptureRequest.Builder previewBuilder = 
                    cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
                // 将Surface设为预览输出目标
                previewBuilder.addTarget(previewSurface);
                
                // 启动重复预览请求,持续获取相机帧
                session.setRepeatingRequest(previewBuilder.build(), 
                    null, backgroundHandler);
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            // 处理配置失败的情况,比如提示用户相机不可用
        }
    }, backgroundHandler);

4. 在GL线程中更新纹理

当相机输出帧到SurfaceTexture后,你需要在GL线程中调用surfaceTexture.updateTexImage()来更新纹理内容,之后就可以在你的着色器中使用这个GL纹理ID进行自定义渲染了。注意这个操作必须在绑定了对应GL上下文的线程中执行。

额外注意事项

  • 尺寸匹配:一定要确保SurfaceTexture的缓冲区尺寸和相机输出的预览尺寸完全一致,否则会出现画面拉伸、裁剪或者无法输出的问题。
  • 生命周期管理:在相机关闭、页面销毁时,记得调用surfaceTexture.release()和previewSurface.release(),避免内存泄漏。
  • 线程安全:SurfaceTexture的操作(比如updateTexImage())必须在GL线程执行,不要在主线程或者相机回调线程随意调用。

内容的提问来源于stack exchange,提问作者Whoami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:01:25