关于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 ...
随机推荐
- 利用 SPL 快速实现 Observer 设计模式
目录: 1.什么是 SPL 2.SplSubject 和 SplObserver 接口 3.为什么使用 SplObjectStorage 类 4.模拟案例 5.结束语 6.下载资源 什么是 SPL S ...
- 【UML】NO.49.EBook.5.UML.1.009-【UML 大战需求分析】- 包图(Package Diagram)
1.0.0 Summary Tittle:[UML]NO.49.EBook.1.UML.1.009-[UML 大战需求分析]- 包图(Package Diagram) Style:DesignPatt ...
- koa2的文件上传
使用koa2搭建文件上传服务,后端代码 const os = require('os'); const path = require('path'); const koaBody = require( ...
- Linux性能优化gprof使用
gprof用于分析函数调用耗时,可用之抓出最耗时的函数,以便优化程序. gcc链接时也一定要加-pg参数,以使程序运行结束后生成gmon.out文件,供gprof分析. gprof默认不支持多线程程序 ...
- Kotlin Linux下的环境搭建
Kotlin是JVM世界里的未来主宰,不管你信不信,我反正相信了! 好吧,如果你不糊涂,就跟着我一起学学吧,哈哈 一下载https://github.com/JetBrains/kotlin/rele ...
- 记录一则ORA-600 [13011]错误
环境:Solaris 10 + Oracle 11.2.0.1 现象:alert告警日志定期出现ORA-600 [13011]错误 1.故障现象 2.初步分析 3.匹配MOS 4.定位解决 1.故障现 ...
- MyBatis基础入门《十二》删除数据 - @Param参数
MyBatis基础入门<十二>删除数据 - @Param参数 描述: 删除数据,这里使用了@Param这个注解,其实在代码中,不使用这个注解也可以的.只是为了学习这个@Param注解,为此 ...
- windows8安装msi或exe软件提示2503错误的解决办法
windows8以后的版本安装msi软件(比如nodejs.msi.Git.msi.python.msi.T ortoiseSVN.msi)的时候老师出现2503.2502的错误,究其原因还是系统权限 ...
- mysql避免脏读
mysql避免脏读 在MySQL的InnoDB中,预设的Tansaction isolation level 为REPEATABLE READ(可重读) 在SELECT 的读取锁定主要分为两种方式 ...
- 20155228 2016-2017-2《Java程序设计》课程总结
20155228 2016-2017-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1 简要内容 了解「Trainer/Trainee」是最好的师生关系,对即将到来的翻转课堂有 ...