(一)Android camera2 实现相机预览及获取预览帧数据流

一、本文重点说明

  1. 本文基于 android camera2 实现视频预览,暂未兼容 camera1 API,基础实现可以参考 googlesample Camera2 例子 android-Camera2Basic ,本文以工具类形式实现一步调用。
  2. 谷歌例子中没有具体指明预览帧的获取,即 camera1 setPreviewCallback 类似功能实现,具体是通过 ImageReader 中的 OnImageAvailableListener 来实现的,重点来了,获取帧数据不能用 ImageFormat.JPEG 格式,否则你会发现预览非常卡的,因为渲染 JPEG 数据量过大,导致掉帧,所以预览帧请使用其他编码格式。简单代码如下:
public void init(){
	ImageReader imageReader = ImageReader.newInstance(width, height, ImageFormat.YV12, 1);//预览数据流最好用非JPEG
	imageReader.setOnImageAvailableListener(new OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
        	Image image = reader.acquireLatestImage();//最后一帧
        	//do something
        	int len = image.getPlanes().length;
	        byte[][] bytes = new byte[len][];
	        int count = 0;
	        for (int i = 0; i < len; i++) {
	            ByteBuffer buffer = image.getPlanes()[i].getBuffer();
	            int remaining = buffer.remaining();
	            byte[] data = new byte[remaining];
	            byte[] _data = new byte[remaining];
	            buffer.get(data);
	            System.arraycopy(data, 0, _data, 0, remaining);
	            bytes[i] = _data;
	            count += remaining;
	        }
	        //数据流都在 bytes[][] 中,关于有几个plane,可以看查看 ImageUtils.getNumPlanesForFormat(int format);
	        // ...
	        image.close();//一定要关闭
        }
     }, handler);
}

到这里,重点已讲完,下面仅仅是我对 Camera2 的封装,如不需要,可以暂停往下阅读,节省您的时间。

二、预览数据流说明

不同编码的数据通道数不同,具体可以通过 ImageUtils.getNumPlanesForFormat(int format) 查看,一通道的话一般是包含所有数据,可以通过 Bitmap 直接保存出一帧的数据,三通道输出是 YUV 数据,如果要输出图片,需要转码为 RGB 格式。

三、camera2 API 简单说明

  1. 说明
    Camera1 区别较大,主要建立会话机制,通过 Session 完成对相机请求操作,更具体的原理说明请使用 csdn 的搜索功能。流程说明:
    openCamera() -> CameraDevice.StateCallback 中创建 CameraCaptureSession -> CameraCaptureSession.StateCallback 中发起请求。
  2. 工具类使用 CameraUtil,调用示例
private CameraUtil cameraUtil;
//初始化,传入你预览的控件,目前支持 TextureView 暂未支持到 SurfaceView
//如不需要预览可以传null
protected void onCreate(@Nullable Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     TextureView textureView = findViewById(R.id.textureView);
     //自行判断是否有相机权限
     //前预览,后预览,可共用一个,不需预览可传 null
     cameraUtil = new CameraUtil(this, textureView, null);
     //预览帧获取
    cameraUtil.setPreviewFrameCallback(new CameraUtil.OnPreviewFrameCallback() {
                @Override
                public void onCameraFront(byte[][] bytes, int orientation) {
                    //前预览回调
                }

                @Override
                public void onCameraBack(byte[][] bytes, int orientation) {
					//后预览回调
                }

                @Override
                public void onCameraFront(byte[] bytes, int orientation) {
                	//前预览回调
                }

                @Override
                public void onCameraBack(byte[] bytes, int orientation) {
                	//后预览回调
                }
            });
 }
@Override
protected void onResume() {
    super.onResume();
    //启动预览
    cameraUtil.startPreview(this);
}
//在 onPause 或者 onDestroy 中释放资源
//建议在 onPause 中,因为 onDestroy 中系统已先断开与相机的连接
@Override
protected void onPause() {
    if (cameraUtil != null) {
        cameraUtil.release();
    }
    super.onPause();
}

接口说明:
这里的预览帧回调主要是两个,一个前置,一个后置,其中每一个回调都分两种,一个是把所有数据用一个byte数组返回,另一个是各通道区分返回,主要用于 YUV 编码类型。

四、效果示意图:

  1. 两个摄像头使用同一个 TextureView 显示
  2. 两个摄像头使用不同的 TextureView 显示
  3. 没有预览画面,通过预览回调显示

----对比
TextureView 预览 + 回调预览 GLSurefaceView 直接将 YUV 显示出来,这里回调数据流需要更加传感器方向做旋转,暂未做完,待 libyuv 库写完再更新。这里的数据回调显示,用的是 opneGLGLSurdfaceView直接绘制 YUV 数据,使用的是 李狗蛋52635 的Android上使用OpenGLES2.0显示YUV数据 可以在这里查看

结语

到此本文已结束,目前仅适用 camera2 API,但不够好,后续会添加更基础的功能,如拍照、兼容 camera1、数据帧方向处理等操作。本文仅仅是做一个总结,希望都对您有所帮助。
下面贴上我的 CameraUtil 类地址,因为还没完善,所以没有剥离,暂放在我的 github测试项目中,项目地址 >> 戳我

camera2 >> com.zhou.android.camera2 地址
opengl >> com.zhou.android.opengl 地址

示例 Activity 在 main 包中 CameraUtilTestActivity

说明 包 Package 类Class
相机工具类 com.zhou.android.camera2 CameraUtil
相机配置 com.zhou.android.camera2 CameraConfig
数据回调接口 com.zhou.android.camera2 OnImageAvailableListener
GL 渲染器 com.zhou.android.opengl GLFrameRenderer
yuv 转换器 com.zhou.android.opengl GLProgram

不会从github下的话,从 CSDN camera2 这里下载
opengl 这里下载

未完,待续

你可能感兴趣的:(Android开发)