关于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 ...
随机推荐
- vue/cli 3.0 脚手架【进阶】 使用 amfe-flexible 和 postcss-px2rem进行移动端适
安装vue-cli3 npm install -g @vue/cli 创建项目 vue-cli-test 脚手架-项目-成功-运行项目 基于vue-cli配置移动端自适应 转自:http://hj ...
- [转]C++编译链接过程详解
C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接.编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程.链接是把目标文件.操作 ...
- IOT专用IOP平台
10.110.20.200(iot) root 789a? centos7 给展湾paul,iot-hub 10.110.20.199(iot) root ce ...
- Response实例
Response部分方法介绍及实例 客户端浏览器每访问一次web服务器的页面都会提交一次请求,与request对象对应的是response对象,该对象可以用来对客户的请求做出响应,向客户端发送数据.输 ...
- CentOS在VMware中 网络配置
一. 将centos安装好之后,发现ping, ifconfig等常见的命令都用不了,出现unknown service或command not found这样的字眼,这让我十分无语.查了一下资料,i ...
- jenkins集成sonar
用于我的sonar已经在一台机器上搭建好了,但是每次都要人工去执行sonar-run,很麻烦,所以就想着集成到jenkins上,在jenkins上点点按钮就可以看sonar结果,所以很抱歉,本博客不设 ...
- c# 判断文件是否发生了变化
你这个是想文件发生改变时,自动调用一个函数,做出一些操作呢. 还是有一个按钮(或者别的什么),你去点击一下,然后检测下一个文件,是否发生了变化? 下面的代码,监控d盘下的所有.txt文件的修改 1 2 ...
- android 通过页面上关键字快速定位代码
这里定位微信关于页面, 当然可以直接获取当前最顶层activity 反编译apk后 搜索 strings.xml,找到对应id 搜索文件到用到id对应的成员变量,通常 是在R*.smali文件中 字符 ...
- XML反序列化遇到数字型节点值为空导致反序列化异常
实体类: [XmlRoot("stream")] public class _30320DuisiFukuanQueryResponseModel : ResponseModelB ...
- 《2017年Q2中国城市研究报告
根据百度慧眼团队发布的<2017年Q2中国城市研究报告>,2017年第二季度人口吸引力排名前五的城市与第一季度相同,深圳继续保持第一的领先位置.