关于Android Camera2 API 的自动对焦的坑
https://www.jianshu.com/p/280e5301b7b9
一、使用。关于Camera2的API使用,参考Google官方的例子:
Camera2Basic
Camera2Raw
Camera2Video
这是一手资料,配合官方的资料理解Camera2 API的底层原理:
3A 模式和状态转换
二、关于Camera2 API 的一些坑。
本人应公司要求,预研Camera2 相关API以及封装。在参考Camera2Basic 编写相机应用时,本人发现了Camera2 API 的关于自动对焦的一个非常严重的BUG。在此记录下来,希望后来者在使用Camera2 API时,慎重选择。
Camera2Basic 中出现问题的代码如下:
private CameraCaptureSession.CaptureCallback mCaptureCallback
= new CameraCaptureSession.CaptureCallback() {
private void process(CaptureResult result) {
switch (mState) {
case STATE_PREVIEW: {
// We have nothing to do when the camera preview is working normally.
break;
}
case STATE_WAITING_LOCK: {
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState == null) {
captureStillPicture();
} else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
mState = STATE_PICTURE_TAKEN;
captureStillPicture();
} else {
runPrecaptureSequence();
}
}
break;
}
case STATE_WAITING_PRECAPTURE: {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
mState = STATE_WAITING_NON_PRECAPTURE;
}
break;
}
case STATE_WAITING_NON_PRECAPTURE: {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
mState = STATE_PICTURE_TAKEN;
captureStillPicture();
}
break;
}
}
}
@Override
public void onCaptureProgressed(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull CaptureResult partialResult) {
process(partialResult);
}
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
process(result);
}
};
出现问题的代码如下:
case STATE_WAITING_LOCK: {
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState == null) {
captureStillPicture();
} else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null ||
aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
mState = STATE_PICTURE_TAKEN;
captureStillPicture();
} else {
runPrecaptureSequence();
}
}
break;
}
调用拍照方法后,会进入STATE_WAITING_LOCK状态,此时获取Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);的对焦状态afState 在某些机器上面,连续拍了几张图片之后,afState 会一直处于CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN状态,表示一个持续聚焦的算法正在做扫描。镜头正在移动中。然而实际上你并没有移动镜头。这里会导致后续的对焦完成ImageReader取出对焦完成的图像数据无法进行。也就是无法再拍照了。这是我测试得到的log:

afState 的状态为1,即CONTROL_AF_STATE_PASSIVE_SCAN。无法再继续走到后续的CONTROL_AF_STATE_FOCUSED_LOCKED 和 CONTROL_AF_STATE_NOT_FOCUSED_LOCKED 状态,导致无法取出图像数据,进而完成拍照功能。
测试设备:红米5 Plus
而且这个状态出错的情况一旦出现,就只能关掉相机重新打开才能恢复正常。由于手上的设备有限,无法做更多的测试。但至少这个情况在MIUI系统上非常大概率出现,基于MIUI国内的市场份额,对于这种情况,只有两种解决方案,要么放弃Camera2在拍照时的自动对焦,要么放弃使用Camera2 API。暂时没有找到满意的解决方法。
关于放弃拍照时自动对焦方案是:
// 等待对焦被锁定
case STATE_WAITING_LOCK: {
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState == null) {
Log.d(TAG, "STATE_WAITING_LOCK: mState = STATE_WAITING_LOCK;");
captureStillPicture();
} else if (
CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN == afState ||
CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
// CONTROL_AE_STATE can be null on some devices
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState == null || (CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN != afState
&& aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED)) {
mState = STATE_PICTURE_TAKEN;
captureStillPicture();
} else {
runPrecaptureSequence();
}
}
Log.d(TAG, "process: afState = " + afState);
break;
}
加入CONTROL_AF_STATE_PASSIVE_SCAN 状态的判断,对于出现一直出现CONTROL_AF_STATE_PASSIVE_SCAN的情况时,直接走下一层的AE曝光处理runPrecaptureSequence()流程,此时可能会因为无法对焦,画面层次感丢失的情况。
如果有人有更好的解决方案。希望能够分享一下。个人感觉目前Camera2 API的坑相当的多,至少在使用的时候,注意一些深坑。
作者:cain_huang
链接:https://www.jianshu.com/p/280e5301b7b9
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
关于Android Camera2 API 的自动对焦的坑的更多相关文章
- android Camera2 API使用详解
原文:android Camera2 API使用详解 由于最近需要使用相机拍照等功能,鉴于老旧的相机API问题多多,而且新的设备都是基于安卓5.0以上的,于是本人决定研究一下安卓5.0新引入的Came ...
- android camera2 Api(转载)
现在的手机一般都会提供相机功能,有些相机的镜头甚至支持1000万以上像素,有些甚至支持光学变焦,这些手机已经变成了专业数码相机.为了充分利用手机上的相机功能,Android应用可以控制拍照和录制视频. ...
- Android L Camera2 API 使用实例程序汇总
在网上发现几个使用Camera API2开发的实例程序,总结一下方便后续参考: 1.Camera2 Basic : https://github.com/googlesamples/android-C ...
- Android 用 camera2 API 自定义相机
前言 笔者因为项目需要自定义相机,所以了解了一下 Android 关于 camera 这块的 API.Android SDK 21(LOLLIPOP) 开始已经弃用了之前的 Camera 类,提供了 ...
- Android Camera API/Camera2 API 相机预览及滤镜、贴纸等处理
Android Lollipop 添加了Camera2 API,并将原来的Camera API标记为废弃了.相对原来的Camera API来说.Camera2是又一次定义的相机 API,也重构了相机 ...
- Android Camera2 预览功能实现
1. 概述 最近在做一些关于人脸识别的项目,需要用到 Android 相机的预览功能.网上查阅相关资料后,发现 Android 5.0 及以后的版本中,原有的 Camera API 已经被 Camer ...
- Android Camera2 预览,拍照,人脸检测并实时展现
https://www.jianshu.com/p/5414ba2b5508 背景 最近需要做一个人脸检测并实时预览的功能.就是边检测人脸,边在预览界面上框出来. 当然本人并不是专门做 ...
- Android Camera2拍照(一)——使用SurfaceView
原文:Android Camera2拍照(一)--使用SurfaceView Camera2 API简介 Android 从5.0(21)开始,引入了新的Camera API Camera2,原来的a ...
- Android Camera2 拍照入门学习
原文:Android Camera2 拍照入门学习 学习资料: 肾虚将军android camera2 详解说明 极客学院android.hardware.camera2 使用指南 Android 5 ...
随机推荐
- python的__new__方法
https://www.cnblogs.com/kex1n/p/5991249.html https://blog.csdn.net/wwx890208/article/details/8053445 ...
- vue-devtools : vue的调试工具及log显示工具 vconsole
使用 devtools 有很多好处,比如它可以让你能够实时编辑数据属性并立即看到其反映出来的变化.另一个主要的好处是能够为 Vuex 提供时间旅行式的调试体验. 注意:请留意如果页面使用了一个生产环境 ...
- 天气服务API文档 第1版
HTTP接口设计文档 此文档为开发HTTP接口的设计文档,目前用于提供天气查询的相关接口. 测试的时候使用 URL=http://www.dennisthink.com/test/api/weathe ...
- bat/cmd将命令执行的结果赋值给变量
比如我想把git代码的commitid获取以后加到文件夹上来标记文件夹中的包是哪个git 节点构建得到的. git 命令是git rev-parse --short HEAD 再linux系统下,只需 ...
- iOS 聊天表情键盘
具体思路 通过UIKeyboardWillChangeFrameNotification通知,监听键盘的改变,同时可以得到键盘的Frame和动画的持续时间, 新建键盘顶部工具条YSComposeToo ...
- Windows(华硕/联想)笔记本上安装黑苹果与win双系统教程
声明:电脑小白者请谨慎安装,如有需要可私聊或留言提供安装工具 首先说明:Windows PC的文件操作系统也就是磁盘格式是FAT32或 NTFS ,而 Mac 的文件操作系统格式是 HFS ,所以这时 ...
- 部署一个不依赖tomcat容器的应用
一个task项目,应用里边都是一些定时任务.我和新入职的高开商定程序部署不依赖于tomcat. 计划赶不上变化,任务开发完成还没等上线呢,哥们要离职了.工作交接时大概说了一下上线怎么部署. 结果呢,当 ...
- Java中通过Class类获取Class对象的方法详解
方式1:通过Object类的getObject()方法 Person p = new Person(); Class c = p.getClass(); 方式2: 通过 类名.class 获取到字节码 ...
- mysql group_concat用法
MySQL中group_concat函数 完整的语法如下: group_concat([DISTINCT] 要连接的字段 [Order BY ASC/DESC 排序字段] [Separator '分隔 ...
- windows编程之Windows Shell 编程
参考书<VC++ Windows Shell Programming> 这里仅仅是记录下该资源,推荐到下文列出的连接进行查看 用VC++ 进行Windows Shell 扩展编成 ...