ZSL: zero shutter lag,零延时拍照
一、普通拍照和ZSL拍照区别
-
普通拍照
按下快门后需要进行一系列处理和校正再进行编码。如对焦、曝光、白平衡等。
由于需要对拍照命令等进行配置,所以导致实际的图片未必是按下快门时的图片
譬如在预览30fps下,按下快门时在第1帧,实际拍得的照片是第8帧的图像。 -
ZSL-0秒延时拍照
所拍即所得。按下快门那一刻拍到的照片就是当时所看到的照片。
ZSL模式拍照会缓存若干帧,在按下快门那一刻,直接提取缓存帧进行编码保存照片。
譬如在预览30fps的情况下,按下快门时是在第1帧,则实际上拍得的照片是第1帧的图像。
二、基本原理
其本质是在开始预览后,sensor和VFE会一直产生 preview 和 snapshot快照帧,通过buffer缓存最新的snapshot 帧数据。
当拍照被触发,系统按照实际的拍照时间,找出在buffer中的相应帧,然后返回帧到用户,所以返回的帧更迅速,基本就是按下快门时的图片。。
实现ZSL基本需要以下几点:
-
一个surfaceView用于预览
-
一个队列缓存snapshot的数据
-
拍照动作获取队列某桢数据作为拍照数据输出
-
输出的照片需要YUV->JPEG数据的转码
当然不同的Android版本实现方式可能不同
Android4.4的实现对于2)步和3)步都是在HAL层实现,HAL层在维护缓存队列,当接收倒take_picture 命令时直接取得某桢缓存数据,进行转码,然后以正常拍照的流程利用@link android.hardware.Camera.PictureCallback通知应用层拍照的数据。
Android5.0的实现对于2)步和3)步都是在应用层实现,应用层在启动预览时给HAL层传递2个surface给HAL层,HAL层利用其中一个surface用于预览数据填充,一个surface用于填充snapshot的数据填充。应用层不断读取surface中snapshot的数据去维护一个缓存队列,当用户执行take_picture,读取缓存队列的数据作为拍照数据。
MTK的底层实现
拍照过程会走p2Streaming和p2Capture两个HWnode节点。
ZSL有一个缓冲区HBC,该缓冲区来自带有预览请求的p1node。
ZSL捕获将从ZSL HBC中选择一个缓冲区来持续捕获管道。
代码路径:
三、分类
ZSL主要分为single shot和burst mode
-
single shot:
预览之后,sensor 和VFE 会产生快照和预览帧,并且会把最新的一些帧保留在图像buffer中。
一旦“取图”事件被触发,系统就会在第一时间内从图像buffer中把相关的图像找出并返回给用户。 -
Burst mode
是single shot 特征的自然延伸。此功能允许用户捕获的不仅是当前帧,但也有几个帧之前和之后的当前帧的少数几个帧,从而捕捉到一个序列的图像到内存。这将为用户提供不同的快照时间,从中选择一个或多个帧来保存。应用了多少帧的选择自由是多少追溯帧和未来帧在记忆的局限性上,追溯和未来帧是相对于真正的快门时间的。
参考
ZSL(zero shutter lag) 简介