关于CameraX是否可以打开多种特殊摄像头,例如广角、长焦、景深等等
虽然CameraSelector只简单定义了前置后置,没具体指明摄像头,但是可以跟Camera2 API的CameraCharacteristics结合使用,获取对应的cameraid,再传入CameraSelector中,最终实现cameraX打开特殊的摄像头。
CameraController与CameraProvider
两种方式都可以编写cameraX程序。前者较简单,后者可以实现更复杂需求。
当前demo开发基于CameraProvider,CameraController的待后面研究下。
CameraX实现预览
用ProcessCameraProvider去绑定多个usecase,usecase可以是预览、拍照,可以一次最多绑定三个usecase。创建预览的usecase时,需要用到Preview这个usecase,通过Preview.setSurfaceProvider将类型为SurfaceProvider传入,最终调用ProcessCameraProvider.bindToLifecycle绑定usecase时传入preview的usecase,这样就能接收预览数据了。
对于Preview,可以使用setTargetResolution与setTargetAspectRatio指定预览尺寸、预览比例,但是两者不能同时使用,若是使用setTargetAspectRatio,则会内部计算实际要设置的分辨率大小。
对于拍照的usecase,同样用setTargetResolution与setTargetAspectRatio,方法类似。
CameraX实现拍照
使用拍照的usecase类ImageCapture,配置时使用setTargetResolution指定拍照图片大小,最终调用ImageCapture.takePicture拍照。在ImageCapture.OnImageSavedCallback回调中,处理拍照回调。onImageSaved回调处理拍照完成回调。
CameraX实现触摸对焦
通过FocusMeteringAction.Builder传入对焦点坐标,构建一个对焦的action,然后再通过cameracontrol.startFocusAndMetering将这个action传入,(startFocusAndMetering执行的同时也会指定一个listener,该listener在对焦成功时、对焦取消时、对焦失败时会回调)去执行对焦动作。startFocusAndMetering返回值是ListenableFuture<FocusMeteringResult>,可以针对该返回值get().isFocusSuccessful()获取到对焦执行结果,get()是阻塞动作,需要等该动作。可以设置对焦的超时时间,超时时间到,底层会主动cancel对焦动作,默认是5s超时。底层执行cancel对焦最终也会回调到上文说的那个listener。
其与camera2实现该功能的对比,后者需要设置的参数较多。
CameraX实现持续对焦
CameraX没有跟camera2 API那样提供类似下面这种设置持续对焦的api。据说cameraX自动就做了持续对焦的事,而实际上在真机上面看也的确如此。
Camera2实现持续对焦的代码(拍照模式下):
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
CameraX的CaptureMode
拍照的usecase,imagecapture,在ImageCapture.builder里面提供setcapturemode接口,来设置拍照时基于拍照效率与拍照图片质量权衡的参数capturemode。
实际测试,ZSL是拍照效率最高的。如下图所示,同一场景同一机器同一时间三种不同capturemode的耗时。(测试环境,高通SM6475平台,后置4080*3060拍照尺寸)
CameraX实现AEAF锁定
经过确认,cameraX无api可以实现这个AEAF锁定。
不过对于锁AF,有间接的方法可以实现,以下是关键代码。
FocusMeteringAction focusAction = new FocusMeteringAction.Builder(
mPreviewView.getMeteringPointFactory().createPoint(x, y)).disableAutoCancel().build();
在之后mCameraControl.startFocusAndMetering(focusAction)触发对焦后,因为FocusMeteringAction.Builder.disableAutoCancel()的原因,使得af不会进行cancel,所以AF就间接锁住了。
补充下,经过在stackoverflow上咨询,有了AE锁定的方案,如下。
在startFocusAndMetering的对焦成功回调中,调用以下即可。
mCamera2Control = Camera2CameraControl.from(mCameraControl);
new CaptureRequestOptions.Builder()
.setCaptureRequestOption(CaptureRequest.CONTROL_AE_LOCK, true)
.build().setCaptureRequestOptions(options);
简单解释下,需要等AF对焦完成时,也就是AE收敛完毕,才去调用ae锁定。
而调用ae锁定,可以通过Camera2CameraControl.setCaptureRequestOption来实现,这个接口就类似于camera2 API的设参数的接口。
Camera2CameraControl.getCaptureRequestOptions().getCaptureRequestOption()则相当于camera2 API的获取参数的接口。
查看相关源码,发现google针对cameraX只能支持简单功能这个弱点,就是留有一手。
如图1,camera-camera2打头的文件夹内,是些可以让cameraX调用camera2接口的类,看类名有些可以很容易就联想到对应的camera2类名。
图1
犹如发现新大陆那样,那么估计很多cameraX没接口实现的,都可以通过这个机制来实现了。这个可以后面好好再研究下。
最后关于这个AE锁定的,再补充下,需要在相关地方做好AE锁定重置的处理,调用相同接口针对CaptureRequest.CONTROL_AE_LOCK参数赋值false即可。
附上源码:
ZZPCameraX: Implement the camera feature via android cameraX API.基于android cameraX API实现相机一些基本功能