Android Camera HAL3 hdr

HAL3的主要流程

  1. 获取现在设备上可用的相机设备,包括相机每一个相机的属性功能,get_number_of_camera。

  2. 获取想要打开的相机的Information,在调用中被定为 get_camera_info 函数。

  3. 打开一个设备,保存打开设备时获取的camera_module_t结构体,该结构体就是一个抽象的camera module的连接通道

  4. 通过新建一个设备camera device,来获取一个camera3_device_t结构体,该结构体主要用于获取notify和torch的状态。然后新建一个session,session就是后续需要与内部的camera硬件设备进行控制交互的抽象媒介。

  5. 通过session来配置一个stream,configure_streams函数可以完成此项工作。

  6. 向HAL内部发送控制命令,可以立即为融合了HAL1的各种控制参数,把他们作为一个总线形式的命令分发下去。相关函数调用就是procees_capture_request

  7. 内部HAL处理完毕之后会返回notify事件,一般就是帧的时间戳。并且通过process_capture_result来返回framework相关的结果数据,包括控制参数的内容返回,包括buffer返回等

  8. 重复6-7,直到用户想退出,此时就调用flush来进行整个工作队列的清洗操作。

  9. 关闭整个的camera设备,相关函数是close。

框架流程预览

  • 枚举、打开相机设备并创建有效的会话(session)

  • 在初始化完成之后(这个初始化我觉得是 framework 层的服务初始化完成),framework 就会监听多有的 camera provider,camera provider 是在 ICameraProvider 接口实现的(AIDL
    类型的接口),如果发现系统里面有的话就会建立一个连接。

  • framework 通过 ICameraProvider::getCameraIdList接口来进行设备的枚举,其实这里并没有调用到具体设备相关的 HAL3 内部,因为在 provider 初始化的时候就已经调用过了,这里只是把
    provider 里面保存下来的 camera list 返回给上层的 framework

  • framework 实例化一个新的 ICameraDevice,实例化过程是
    ICameraProvider::getCameraDeviceInterface_VX_X() 来完成的。

  • ramework 调用 ICameraDevice::open() 接口来打开并且创建一个新的 session 来完成后续的控制过程。

  • 使用刚刚创建好的 session 进行具体的业务逻辑处理

  • framework 通过 ICameraDeviceSession::configureStreams() 接口来向设备相关的 HAL
    层传递用户所需的 stream 配置,同时 HAL 内部会根据传递下来的 stream 来选择具体的业务进行配置。
    framework 通过 ICameraDeviceSession::constructDefaultRequestSettings()
    接口来获取一个默认的具体业务场景配置,这个操作可以在 ICameraDevice::open() 之后的任何时刻执行,后面说下这个
    constructDefaultRequestSettings() 接口的内容。

  • framework 使用上面构建的默认 setting,再佐以自己需要的特殊配置,然后发送第一个 request 请求到 HAL里面去。这个 request 里面必须包含至少一个之前配置好的 stream(没错,它们的地址必须相同,不能够使用 copy的方式重新新建一个 stream,并且这个 stream 地址与使用framework&app 去维护),因为要输出 buffer 给framework 那边。上面的 request 使用
    ICameraDeviceSession::processCaptureRequest() 进行传递,HAL 内部需要阻塞本次
    request 请求,直到准备好接受下一个 request 的时候才返回。

  • framework 持续调用 ICameraDeviceSession::processCaptureRequest() 进行
    request 的下发,如果需要切换其它场景的话就再次调用
    ICameraDeviceSession::constructDefaultRequestSettings() 进行具体场景的默认
    setting 构建。

  • 当本次 request 开始被 HAL 正式执行的时候,也就是 HAL 底下的硬件 sensor 开始曝光本帧的时候(sensor starts exposing for capture),HAL 需要调用 framework 实现的ICameraDeviceCallback::notify() 函数进行 SHUTTER 消息回调,这个消息里面包含了时间戳数据和 framenumber。这个是 HAL 层主动发起的回调,但是不需要再第一个 request 下发下去之前就开始回调,并且一个
    request 的 notify 完成之前,不要返回任何 result 给到 framework。

  • 经过几个 pipeline 延迟之后,HAL 开始向 framework 返回已经完成的结果,返回过程通过
    ICameraDeviceCallback::processCaptureResult() 函数完成。返回的顺序得是按照提交的
    request 请求的顺序来,request 也可以一次性下发多个,数量取决于 request 的队列深度,一般 6~8个吧,也取决于具体的平台和其代码实现。

上面的过程会不断地进行循环,等到一定时刻,会发生下面的事件

  • framework 停止下发 request 请求,然后等待所有的 buffer 被填充完毕并且所有的 result
    全部返回,这个时候再次调用 ICameraDeviceSession::configureStreams() 接口重新配置业务流,这在 HAL 内部会导致整个的硬件被重置一遍,然后用新的 stream
    重新配置,接下来继续上面的因果循环。这说白了就是场景的切换,比如从拍照切换到录像(不关闭 camera app)。

  • framework 可能会调用 ICameraDeviceSession::close()
    接口来结束整个会话,该函数可以在任何时候进行调用,但是 framework 在调用该函数的时候不可以继续下发request,并且所有其它的函数调用都不能够进行下去,在 close 函数返回之后,HAL 层不得再回调 framework 的函数。其实在 close 之前,通常会有 flush 函数调用,这个函数的调用要求与 close 差不多,close可以认为就是个收尾动作,flush 会等待所有的 request 完成并且所有的 result 全部返回到 framework。

  • 当发生错误或者其它异步事件的时候,HAL 必须调用 ICameraDeviceCallback::notify() 函数来返回错误消息给framework。如果 HAL 内部发生了严重的设备错误,HAL 内部在回复完错误消息之后需要按照 close函数被调用时候的动作来清理案发现场。同时,在调用 notify 之前,也应该停止所有的尚在队列中的 request请求响应,严重错误传递给 framework 的时候,HAL 不再返回任何结果给到 framework,并且在 framework尝试调用 close 的时候需要返回 -ENODEV 或者 NULL。

hdr
概念:HDR一般指高动态光照渲染。高动态范围图像(High-Dynamic Range,简称HDR)具体表现为几帧曝光不相等图片进行融合。

  • hdr分为很多种,早期的就是人为的多帧曝光。这种在动态画面,表现的不好,容易有鬼影,因为多帧曝光事件不一致,合成时,可以认为是不同时间的照片合成,人物跑步就会呈现前后相近的人影。

  • 基于这个原因,索尼的DOL出现了,当然还有很多种避免鬼影的hdr的输出模式,比如BME,每隔两行的曝光时间分别设为短曝光和长曝光,然后融合成为行数减半的hdr图像。当然还有QBC,MSE,都有点剑走偏锋,使用会比较少。

    说下DOL是如何输出的。

  • 索尼说的是准同时输出,所以简单理解,不是同时输出,但是接近同时输出。

    摄像头以行位单位交替进行曝光,长帧先进行曝光。为什么长帧先曝光?

  • 因为长帧先曝光,长帧和短帧的曝光时间差就是短帧的时间,这样时间差比较小。(实际上同一行的长短曝光并不一定是连续的,看有资料上说先开始曝光长帧,VBP行后开始曝光短帧.)那么我们看到,曝光并不是同时,也就是还是可能存在拖影的情况。反正是可以给你输出时间相差比较短的若干张不同曝光的图片。

  • 假设一张图片是raw10的图像,那么它显示的范围是0-1023,可以认为这是它的图像范围,假定我短曝光时1-1023,那么前面16倍的曝光就为16-16383,这样两帧之后的动态范围达到了1-16383,这样曝光不一样的多帧合成之后的动态范围将会很大。人眼的动态范围很大,但是摄像头不考虑hdr的时候,范围要么是1-1023或者16-16383,如果人眼观察的范围是1-2的18次方的范围,那么前面短曝光看不到亮度大的地方,后者可以认为中帧,亮度小的一部分和高亮部分都读不出来,如果我再来一个长帧曝光时中帧曝光的16倍,那么三张融合能看到眼睛看到的所有范围,实际上万物的动态范围远大于人眼范围,人眼范围大于camera范围,所以多帧融合只是在一定程度上可以让我们看到更多细节。具体算法大致时先确定相应曲线,可以拍摄多张其他参数一致,曝光时间不同的图片采样多个点,带入相应公式。然后根据相应曲线去合成hdr图片。

  • 合成之后有了很宽或者很高的范围,这个就叫宽动态图片。我们用了大量的数据补齐了看不见的范围,但是目前显示器很多只是8位的,为了能显示宽动态图片。我们需要将图片映射到显示器能显示的范围,通过算法映射,展示出我们实际上看到的宽动态图片。

usb camera在亮的地方能有30帧,到暗的地方会下降很多,原因?

  • 调试摄像头的时候曝光很多时候都是以行算的,也就是我们经常说的行曝光。曝光时间=曝光行*每行的时间

  • 一般曝光时间不超过vts,vts就是一帧花的总时间(包含每帧的无效信号)

  • 除了曝光能增加亮度之外,gain也能增加亮度,gain分为模拟gain和数字gain

  • 曝光时间引入的噪声最小,数字增益引入的噪声最大

  • 在比较暗的情况下,为了减少噪声,势必先增加曝光时间。因为增加曝光时间引入的噪声最小,可以忽略不计。但是当曝光时间超过当前vts的时候,曝光时间超过一帧的时间,这样会引起帧率降低,那么这个时候可以增加gain值,模拟gain和数字gain都是由最大限制的,所有的增加gain值都是优先使用模拟gain,当模拟gain增加到最大的时候,才会考虑使用数字gain

  • 关于3a中的ae,实际都有策略做曝光分解,在帧率与噪声中调和,在实际应用中,如果策略分解到曝光时间大于当前vts,那么正常需要先增加当前vts(每帧时间增加,也意味着帧率减小),然后加大曝光时间。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值