Android Camera1开发系列连载:
- Android Camera1详解
相机输出的预览画面最终都会绘制到指定的Surface,然后由SurfaceFlinger进行合成并发送给显示设备
Camera1支持两种方式设置预览的Surface:
- 通过Camera#setPreviewDisplay方法设置SurfaceHolder给相机,通常在使用SurfaceView作为预览控件时使用;
- 通过Camera#setPreviewTexture方法设置SurfaceTexture给相机,通常在使用TextureView或GLSurfaceView作为预览控件时使用;
基于以上两个接口,我们就有了三种方式来显示预览
方式一、使用SurfaceView
使用SurfaceView作为预览UI控件时,在SurfaceHolder#surfaceCreated回调中拿到准备好的SurfaceHolder设置给Camera即可
代码语言:javascript复制camera.setPreviewDisplay(surfaceHolder);
方式二、使用TextureView
使用TextureView作为预览UI控件时,在TextureView#onSurfaceTextureAvailable回调中拿到准备好的SurfaceTexture设置给Camera即可
代码语言:javascript复制camera.setPreviewTexture(surfaceTexture);
方式三、使用GLSurfaceView
使用GLSurfaceVIew作为预览UI控件时,将相机预览数据转化为纹理数据,然后利用OpenGL绘制到屏幕,核心流程:
代码语言:javascript复制 @Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
textureId = TextureHelper.createOesTexture();
st = new SurfaceTexture(textureId);
// config this st to camera
// ...
cameraRender = new CameraRender(context);
st.setOnFrameAvailableListener(this);
glSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
@Override
public void onDrawFrame(GL10 gl) {
st.updateTexImage();
st.getTransformMatrix(transformMatrix);
cameraRender.drawTexture(transformMatrix, textureId);
}
@Override
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
glSurfaceView.requestRender();
}
除了上面三种方式外,还有一种比较鸡肋的方案来实时显示预览
方式四、利用buffer数据
向Camera对象注册setPreviewCallback,可以获取到每一帧预览的NV21数据,利用OpenGL绘制NV21数据也可以显示预览(如何使用OpenGL渲染YUV数据)。最开始设想的挺好的,实际验证的时候发现不向Camera设置SurfaceHolder或SurfaceTexture,单独注册setPreviewCallback接口是不回调数据的。。。
所以这个方案就比较鸡肋了,需要自己构造一个SurfaceTexture设置给Camera,以便让Camera能回调每一帧预览数据给注册方
DEMO
代码语言:javascript复制// git branch -a
// remotes/origin/dev_camera_one_buffer
// remotes/origin/dev_camera_one_gl_surface_view
// remotes/origin/dev_camera_one_texture_view
// remotes/origin/master 默认SurfaceView
https://github.com/sifutang/Camera1Demo.git