博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Android Camera2 API 的自动对焦的坑
阅读量:2384 次
发布时间:2019-05-10

本文共 6238 字,大约阅读时间需要 20 分钟。

一、使用。关于Camera2的API使用,参考Google官方的例子:

这是一手资料,配合官方的资料理解Camera2 API的底层原理:

二、关于Camera2 API 的一些坑。

本人应公司要求,预研Camera2 相关API以及封装。在参考 编写相机应用时,本人发现了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的坑相当的多,至少在使用的时候,注意一些深坑。

转载地址:http://ukdab.baihongyu.com/

你可能感兴趣的文章
代理服务器中的HTTP代理与SOCKS代理有什么区别?
查看>>
零基础Python学习路线,小白的进阶之路!
查看>>
CSS的23个垂直居中技巧,你都学会了吗?
查看>>
黑客攻击用的最短代码大揭秘,颠覆你的世界观!
查看>>
零基础的自学前端之路,当年的入坑之旅
查看>>
新手程序员?教你解决办法!基础都掌握了,动手敲代码就一脸懵逼
查看>>
程序员快速进阶学习到底要看书还是要看视频?
查看>>
web游戏框架哪家强?国内外精选优质框架分析及注意事项
查看>>
各行业都爱用什么编程语言开发?
查看>>
css3实现ps蒙版效果以及动画,炫酷吊炸天!
查看>>
程序员休息时间接私活遭公司辞退,不明觉厉?
查看>>
CSS 、JS实现浪漫流星雨动画
查看>>
花4万学代码,工资却只有5千,这个程序员做的..
查看>>
新手网站建设指南(2)
查看>>
新手网站建设优化,这些网站为你提供数之不尽的免费素材!(3)
查看>>
HTML特殊字符显示(常用到的特殊符号,箭头相关,数学相关,标点,符号相关等)...
查看>>
40岁的程序员找不到工作,原来码农真的是碗青春饭
查看>>
2018年前端性能优化总结,这也是我做程序员的第五个年头了
查看>>
前端进阶(三)从0到1学AJAX,这篇就够了!
查看>>
强大的CSS:实现平行四边形布局效果
查看>>