Android camera2 同时打开两颗物理摄像头

您所在的位置:网站首页 什么叫开启相机权限 Android camera2 同时打开两颗物理摄像头

Android camera2 同时打开两颗物理摄像头

2023-07-15 23:43| 来源: 网络整理| 查看: 265

因业务需求,需要同时打开两颗物理摄像头。 从Camera2 api来看 SdkVersion 28 以后已经支持此功能。 但是不得不说api文档不友好,又或者说我实在是菜。

先来一张 这个我也不知道叫什么的  Camera2 的结构图吧。

 从这张图中,我们需要知道的其实就是  HAL层中的 Camera0,Camera1......是什么,又包含了什么。从官方的文档中,可以理解为

这些Camera 为逻辑摄像头。 什么是逻辑摄像头?   那就是软件层面的摄像头。  无论你的物理摄像头(手机上真实的摄像头)是什么样 你不需要考虑, 反正你拿到的只是这个逻辑摄像头。  

问题就来了  我现在要同时打开两颗物理摄像头啊 , 给我一堆逻辑摄像头有什么用?

不急 。。 继续讲。。

这个逻辑摄像头是对物理摄像头的封装。 意思就是  这个逻辑摄像头中会包含一个 或者多个物理摄像头。摄像头客户端可以通过调用 getPhysicalCameraIds() 就可以得到这颗逻辑摄像头下的物理摄像头(当然,也可能没有,也就是不提供)。  当这个getPhysicalCameraIds()返回的物理摄像头Id个数大于2  也就是这个逻辑摄像头下有两颗以上的物理摄像头, 那么就说明有机会将这两科物理摄像头一起打开。 只能是有机会啊 实测。

不多说废话了。  下面直接走流程

一、选出有多个物理摄像头的逻辑摄像头

双镜类

public class DualCamera { //逻辑相机ID(厂商分配) private String logicCameraId; //相机物理id 1 private String physicsCameraId1; //相机物理id 2 private String physicsCameraId2; public String getLogicCameraId() { return logicCameraId; } public void setLogicCameraId(String logicCameraId) { this.logicCameraId = logicCameraId; } public String getPhysicsCameraId1() { return physicsCameraId1; } public void setPhysicsCameraId1(String physicsCameraId1) { this.physicsCameraId1 = physicsCameraId1; } public String getPhysicsCameraId2() { return physicsCameraId2; } public void setPhysicsCameraId2(String physicsCameraId2) { this.physicsCameraId2 = physicsCameraId2; } }

得到可以开双镜的摄像头 

public static DualCamera getDualCamera(Context context){ DualCamera dualCamera = new DualCamera(); //获取管理类 CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); assert manager != null; try { //获取所有逻辑ID String[] cameraIdList = manager.getCameraIdList(); //获取逻辑摄像头下拥有多个物理摄像头的类 作为双镜类 for (String id : cameraIdList) { try { CameraCharacteristics cameraCharacteristics = manager.getCameraCharacteristics(id); Set physicalCameraIds = cameraCharacteristics.getPhysicalCameraIds(); Log.d(TAG, "逻辑ID:" + id + " 下的物理ID: " + Arrays.toString(physicalCameraIds.toArray())); if (physicalCameraIds.size() >= 2) { dualCamera.setLogicCameraId(id); Object[] objects = physicalCameraIds.toArray(); //获取前两个物理摄像头作为双镜头 dualCamera.setPhysicsCameraId1(String.valueOf(objects[0])); dualCamera.setPhysicsCameraId2(String.valueOf(objects[1])); return dualCamera; } } catch (CameraAccessException e) { e.printStackTrace(); } } } catch (CameraAccessException e) { e.printStackTrace(); } return null; }

二、打开多个物理摄像头

第一步  先开对应的逻辑摄像头

//开启摄像头 public void openCamera(){ HandlerThread thread = new HandlerThread("DualCamera"); thread.start(); handler = new Handler(thread.getLooper()); CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); try { //权限检查 if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { //否则去请求相机权限 ActivityCompat.requestPermissions(context,new String[]{Manifest.permission.CAMERA},PERMISSIONS_REQUEST_CODE); return; } manager.openCamera(dualCamera.getLogicCameraId(),AsyncTask.SERIAL_EXECUTOR, cameraOpenCallBack); } catch (CameraAccessException e) { e.printStackTrace(); } }

第二步、在开启的回调中指定打开对应的物理摄像头

//打开相机时候的监听器,通过他可以得到相机实例,这个实例可以创建请求建造者 private CameraDevice.StateCallback cameraOpenCallBack = new CameraDevice.StateCallback() { @Override public void onOpened(CameraDevice cameraDevice) { Log.d(TAG, "相机已经打开"); //当逻辑摄像头开启后, 配置物理摄像头的参数 config(cameraDevice); } @Override public void onDisconnected(@NonNull CameraDevice cameraDevice) { Log.d(TAG, "相机连接断开"); } @Override public void onError(@NonNull CameraDevice cameraDevice, int i) { Log.d(TAG, "相机打开失败"); } }; /** * 配置摄像头参数 * @param cameraDevice */ public void config(CameraDevice cameraDevice){ try { //构建输出参数 在参数中设置物理摄像头 List configurations = new ArrayList(); CaptureRequest.Builder mPreViewBuidler = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); //配置第一个物理摄像头 SurfaceTexture texture = textureView1.getSurfaceTexture(); OutputConfiguration outputConfiguration = new OutputConfiguration(new Surface(texture)); outputConfiguration.setPhysicalCameraId(dualCamera.getPhysicsCameraId1()); configurations.add(outputConfiguration); mPreViewBuidler.addTarget(Objects.requireNonNull(outputConfiguration.getSurface())); //配置第2个物理摄像头 SurfaceTexture texture2 = textureView2.getSurfaceTexture(); OutputConfiguration outputConfiguration2 = new OutputConfiguration(new Surface(texture2)); outputConfiguration2.setPhysicalCameraId(dualCamera.getPhysicsCameraId2()); configurations.add(outputConfiguration2); mPreViewBuidler.addTarget(Objects.requireNonNull(outputConfiguration2.getSurface())); //注册摄像头 SessionConfiguration sessionConfiguration = new SessionConfiguration( SessionConfiguration.SESSION_REGULAR, configurations, AsyncTask.SERIAL_EXECUTOR, new CameraCaptureSession.StateCallback() { @Override public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) { try { cameraSession = cameraCaptureSession; cameraCaptureSession.setRepeatingRequest(mPreViewBuidler.build(), null, handler); } catch (CameraAccessException e) { e.printStackTrace(); } } @Override public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) { } } ); cameraDevice.createCaptureSession(sessionConfiguration); } catch (CameraAccessException e) { e.printStackTrace(); } }

完成上面的操作,基本上就可以用camera2 打开两颗摄像头了, 文章写的比较粗略。

 

附上一份demo.    https://download.csdn.net/download/qq_32503365/12542520 

这个demo貌似有点问题, 授相机权限后需要重启应用才可以开启相机, 不过很明显我不准备修复它了。

最后付上一张 Huawei Mate30 的开双镜

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3