文章目录
一、常用缩略语
缩写 | 全称 |
---|---|
CHI | Camera Hardware Interface |
IFE | Image Front End |
IPE | Image processing engine |
BPS | Bayer processing segment |
TFE | Thin Front End |
OPE | Offline Processing Engine |
UMD | User Mode Driver |
KMD | Kernal Mode Driver |
RDI | Raw Dump Interface |
RTB | Real Time Bokeh |
MFNR | Multi Frame Noise Reduction |
MCTF | Motion Compensation Temporal Filtering |
QCFA | Quad (Bayer Coding) Color Filter Arrangement/Array |
ASD | Auto Scene Detection |
AFD | Auto Flicker Detection |
ABF | Auto Bayer Filter |
ISP | image signal processor |
CCD | Chagre Couled Device |
CMOS | Complementary Metal-Oxide Semiconductor |
二、为什么Android要采用Binder作为IPC机制?
(1)从性能的角度
数据拷贝次数:Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,但共享内存方式一次内存拷贝都不需要;从性能角度看,Binder性能仅次于共享内存。
(2)从稳定性的角度
Binder是基于C/S架构的,简单解释下C/S架构,是指客户端(Client)和服务端(Server)组成的架构,Client端有什么需求,直接发送给Server端去完成,架构清晰明朗,Server端与Client端相对独立,稳定性较好;而共享内存实现方式复杂,没有客户与服务端之别, 需要充分考虑到访问临界资源的并发同步问题,否则可能会出现死锁等问题;从这稳定性角度看,Binder架构优越于共享内存。
(3)从安全的角度传统
Linux IPC的接收方无法获得对方进程可靠的UID/PID,从而无法鉴别对方身份;而Android作为一个开放的开源体系,拥有非常多的开发平台,App来源甚广,因此手机的安全显得额外重要;对于普通用户,绝不希望从App商店下载偷窥隐射数据、后台造成手机耗电等等问题,传统Linux IPC无任何保护措施,完全由上层协议来确保。
Android为每个安装好的应用程序分配了自己的UID,故进程的UID是鉴别进程身份的重要标志,前面提到C/S架构,Android系统中对外只暴露Client端,Client端将任务发送给Server端,Server端会根据权限控制策略,判断UID/PID是否满足访问权限,目前权限控制很多时候是通过弹出权限询问对话框,让用户选择是否运行。Android 6.0,也称为Android M,在6.0之前的系统是在App第一次安装时,会将整个App所涉及的所有权限一次询问,只要留意看会发现很多App根本用不上通信录和短信,但在这一次性权限权限时会包含进去,让用户拒绝不得,因为拒绝后App无法正常使用,而一旦授权后,应用便可以胡作非为。
针对这个问题,google在Android M做了调整,不再是安装时一并询问所有权限,而是在App运行过程中,需要哪个权限再弹框询问用户是否给相应的权限,对权限做了更细地控制,让用户有了更多的可控性,但同时也带来了另一个用户诟病的地方,那也就是权限询问的弹框的次数大幅度增多。对于Android M平台上,有些App开发者可能会写出让手机异常频繁弹框的App,企图直到用户授权为止,这对用户来说是不能忍的,用户最后吐槽的可不光是App,还有Android系统以及手机厂商,有些用户可能就跳果粉了,这还需要广大Android开发者以及手机厂商共同努力,共同打造安全与体验俱佳的Android手机。
4)从语言层面的角度
大家多知道Linux是基于C语言(面向过程的语言),而Android是基于Java语言(面向对象的语句),而对于Binder恰恰也符合面向对象的思想,将进程间通信转化为通过对某个Binder对象的引用调用该对象的方法,而其独特之处在于Binder对象是一个可以跨进程引用的对象,它的实体位于一个进程中,而它的引用却遍布于系统的各个进程之中。可以从一个进程传给其它进程,让大家都能访问同一Server,就像将一个对象或引用赋值给另一个引用一样。Binder模糊了进程边界,淡化了进程间通信过程,整个系统仿佛运行于同一个面向对象的程序之中。从语言层面,Binder更适合基于面向对象语言的Android系统,对于Linux系统可能会有点“水土不服”。
另外,Binder是为Android这类系统而生,而并非Linux社区没有想到Binder IPC机制的存在,对于Linux社区的广大开发人员,我还是表示深深佩服,让世界有了如此精湛而美妙的开源系统。也并非Linux现有的IPC机制不够好,相反地,经过这么多优秀工程师的不断打磨,依然非常优秀,每种Linux的IPC机制都有存在的价值,同时在Android系统中也依然采用了大量Linux现有的IPC机制,根据每类IPC的原理特性,因时制宜,不同场景特性往往会采用其下最适宜的。比如在Android OS中的Zygote进程的IPC采用的是Socket(套接字)机制,Android中的Kill Process采用的signal(信号)机制等等。而Binder更多则用在system_server进程与上层App层的IPC交互。
三、相机架构及名词
1、相机架构
Android手机中Camera软件主要有大体上有4层:
(1)应用层
应用开发者调用AOSP提供的接口即可,AOSP的接口即Android提供的相机应用的通用接口,这些接口将通过Binder与Framework层的相机服务进行操作与数据传递;
(2)Framework层
位于 frameworks/av/services/camera/libcameraservice/CameraService.cpp ,相机Framework服务是承上启下的作用,上与应用交互,下与HAL曾交互。
(3)Hal层
硬件抽象层,Android 定义好了Framework服务与HAL层通信的协议及接口,HAL层如何实现有各个Vendor自己实现,如Qcom的老架构mm-Camera,新架构Camx架构,Mtk的P之后的Hal3架构.
(4)Driver层
驱动层,数据由硬件到驱动层处理,驱动层接收HAL层数据以及传递Sensor数据给到HAL层,这里当然是各个Sensor芯片不同驱动也不同.
2、常见的node及作用
Node | 作用 |
---|---|
BPS | Bayer Processing Segment,Bayer处理阶段。仅做snapshot的噪点降低和Bayer处理,不良像素、PDAF、LSC校正,绿色不平衡校正,黑色级别,通道增益,demosaic,Down scaler,HDR的合并与记录,Bayer混合降噪等 |
IFE | Image front-end engine,图像前端引擎。仅做video/preview的Bayer处理,做些颜色校正,Down scaler,demosaic,统计3A数据等 |
IPE | Image-processing engine,图像处理引擎。由NPS、PPS两部分组成,主要做些硬件降噪(MFNR、MFSR)、调整大小、噪声处理、颜色处理(色差校正、色度抑制)、细节增强(肤色增强) |
STATS | for 3A,ISP硬件给出的3A数据,用于后面的3A算法 |
IS 图像稳定 (Image Stabilization)
RDI 原始数据转储接口 (Raw Dump Interface)
RoI AF 感兴趣区域 (AF Region of Interest)
SNoC 系统 NoC (System NoC)
SOF:start of frame
ANR:application not response
MCC: mutil camera control
LPM: low power manager(低功耗下运行)
CTS/ITS :Android Camera Image Test Suite (ITS) is part of Android Compatibility Test Suite (CTS)
Android相机图像测试套件(ITS)是Android兼容性测试套件(CTS)的一部分
验证程序,包括验证图像内容的测试。从CTS 7.0_r8开始,CTS Verifier通过一体式摄像机ITS支持ITS测试自动化。
继续支持手动测试,以确保涵盖所有Android设备尺寸。
HAF:混合自动变焦
CRM: camera request manager
Sensor CRA(主光线角)
从镜头的传感器一侧,可以聚焦到像素上的光线的最大角度被定义为一个参数,称为主光角(CRA)。对于主光角的一般性定义是:此角度处的像素响应降低为零度角像素响应(此时,此像素是垂直于光线的)的80%
https://blog.csdn.net/weixin_39839293/article/details/82118991
lens CRA与sensor 不配会使sensor 的pixel 出现在光检测区域周围,使pixel 曝光不足,亮度不够,会使整个画面造成亮度不均匀的情况。还有可能造成chroma shading 或局部色偏。局部色偏比较严重,无法用算法补偿
Sensor HDR:
sensor在一幅图像里能够同时体现高光和阴影部分内容的能力
lens fov:视场角
视场角与焦距的关系:一般情况下,视场角越大,焦距就越短
IFE :Image Front End, Bayer processing for video/preview only, HDR/De-mosic, color correction ,scaler,也可以直接输出Raw到RDI
RDI : Raw Dump Interface,直接从IFE吐出来用于capture的
STATS:for 3A,ISP硬件给出的3A数据,用于后面的3A算法
PDPC:PhaseDetection Pixel Correction,相位检测像素校正
ASD: Auto scene detection,自动场景检测
CSIC:Camera serial interface decoder,摄像机串行接口解码器
CAMIF: Ideal Raw的第一个dump点
FD: Face-based,基于人脸,也就是人脸识别
ICA:图像校正和调整 是一个硬件单元,主要用于由镜头和运动引起的几何扭曲
LENR:低/中频增强和降噪
TMC:色调映射控制
CSID:摄像机串行接口解码器模块
IFE:图像前端
IFE_Lite:?
BPS:Bayer处理段
IPE:图像处理引擎
VPU:视频处理单元
DPU:显示处理单元
BPC:坏像素校正
BCC:坏群集校正
ABF:自适应拜耳滤波器
GIC:绿色不平衡校正
GTM:全局色调映射
HNR:混合降噪
ANR:先进的降噪功能
TF:时间过滤器
MFNR:多帧降噪
LTM:局部色调映射
CS:色度抑制
ASF:自适应空间滤波器
Upscaler:升频器
GRA:Grain Adder(纹理增加器?)??
CPAS:相机外围设备和支持
CAMIF:摄像头接口???它是VFE(video front-end)硬件的第一部分,主要任务是同步sensor发送数据过程中涉及到的行、场同步信号。另外它还具有图像提取和图像镜像能力,CAMIF hardware使外部camera sensor能够通过一些简单的外部协议链接到用户单元。为camera提供了数据和时钟接口,但并没有提供控制接口,最具代表行的是用I2C做配置和状态接口。当然,也可以是其他的一次控制信号做一些静态控制。例如:睡眠唤醒模式控制。
NPS:噪声处理部分
PPS:后处理部分
MCTF:运动补偿时间滤波
CAC、CCM、GLUT、2D LUT(二维查找表?)、CV(颜色转换)、CC(颜色校正)、SCE(肤色增强)、MCE(记忆色彩增强):???
SIMO:单输入多输出
Pedestal Correction:基座校正
Down Scaler:降低规模(尺寸)
Chroma Enhancement:色度增强
Chroma Suppression:色度抑制
PDAF:相位检测自动对焦
LSC:镜头阴影校正
PNR:峰值降噪
ADRC:自动动态范围压缩
Backlit scene:背光场景
Garage scene:车库场景
HNR:降低亮度噪声,但保持纹理细节
LDC:镜头畸变校正
EIS:电子稳像
Multi pass spatial noise filtering:多通空间噪声滤波
LNR:镜头降噪
Invert gamma:反转伽玛
hue, saturation, lightness:色调,饱和度,亮度
Upscaler:升频器
ACE:高级色度增强
CPP:相机后处理器(相当于新版的BPS、IPE)
BSP
board support package,板级支持安装包?
也就是“做出支持安装包,来实现手机上各个硬件的基本功能”。
CCT:correlated color temperature,相关色温,具体不详;
chi-cdk:Camera Hardward Interface,相机硬件接口;Camera Development Kit,相机开发包;
HFR:High Frame Rate, min HFR=90, means>=90时,需要enable HFR高帧率,目前最高960,但是是利用插值算法计算得出的,非实际960
四、Android Camera2流程
1、概述
Camera2 的 API 模型被设计成一个 Pipeline(管道),它按顺序处理每一帧的请求并返回请求结果给客户端。
(1)相机功能的强大与否和硬件息息相关,不同厂商对 Camera2 的支持程度也不同,所以 Camera2 定义了一个叫做 Supported Hardware Level 的重要概念,截止到 Android P 为止,从低到高一共有 LEGACY、LIMITED、FULL 和 LEVEL_3 四个级别:
LEGACY:向后兼容的级别,处于该级别的设备意味着它只支持 Camera1 的功能,不具备任何 Camera2 高级特性。
LIMITED:除了支持 Camera1 的基础功能之外,还支持部分 Camera2 高级特性的级别。
FULL:支持所有 Camera2 的高级特性。
LEVEL_3:新增更多 Camera2 高级特性,例如 YUV 数据的后处理等。
(2)相机的所有操作和参数配置最终都是服务于图像捕获,例如对焦是为了让某一个区域的图像更加清晰,调节曝光补偿是为了调节图像的亮度。因此,在 Camera2 里面所有的相机操作和参数配置都被抽象成 Capture(捕获)。
2、开关相机
创建项目,注册权限,配置相机特性,获取CameraManager 实例,获取相机ID列表
, 根据相机 ID 获取 CameraCharacteristics,开启相机,关闭相机
3、预览
(1)获取预览尺寸
CameraCharacteristics 是一个只读的相机信息提供者,其内部携带大量的相机信息,包括代表相机朝向的 LENS_FACING;判断闪光灯是否可用的FLASH_INFO_AVAILABLE;获取所有可用 AE 模式的CONTROL_AE_AVAILABLE_MODES 等等。
CameraCharacteristics 以键值对的方式提供相机信息,你可以通过 CameraCharacteristics.get() 方法获取相机信息。
(2)配置预览尺寸
Camera2 把尺寸信息设置给 Surface。
(3)创建 CameraCaptureSession
(4)创建 CaptureRequest
(5)开启和停止预览
在 Camera2 里,预览本质上是不断重复执行的 Capture 操作,每一次 Capture 都会把预览画面输出到对应的 Surface 上。
(6)适配预览比例
4、拍照
无论 Capture 以何种模式被提交,它们都是按顺序串行执行的,不存在并行执行的情况。
拍摄单张照片是最简单的拍照模式,它使用的就是单次模式的 Capture,我们会使用 ImageReader 创建一个接收照片的 Surface,并且把它添加到 CaptureRequest 里提交给相机进行拍照,最后通过 ImageReader 的回调获取 Image 对象,进而获取 JPEG 图像数据进行保存。
定义回调接口
创建 ImageReader
创建 CaptureRequest
矫正 JPEG 图片方向
设置缩略图尺寸
设置定位信息
播放快门音效
拍照并保存图片,前置摄像头镜像。
连续拍摄就是采用了多次模式的 Capture。
切换摄像头:关闭当前摄像头,开启新的摄像头,创建新的Session,开启预览
注:
重复模式和多次模式都可以实现连拍功能,其中重复模式适合没有连拍上限的情况,而多次模式适合有连拍上限的情况。
一个 CaptureRequest 可以添加多个 Surface,这就意味着你可以同时拍摄多张照片。
拍照获取 CaptureResult 和 Image 对象走的是两个不同的回调接口,灵活运用子线程的阻塞操作可以简化你的代码逻辑。
五、高通Camx架构
1、CamX-CHI基本目录
该部分代码主要位于 vendor/qcom/proprietary/ 目录
camx 代表了通用功能性接口的代码实现集合(CamX)
chi-cdk代表了可定制化需求的代码实现集合(CHI)
2、数字成像系统简介
(1)基本硬件
镜头,光圈快门:光圈控制着瞬时进光量,快门控制着曝光时间,对焦马达:自动对焦策略,其中包括了相位对焦和对比度对焦,感光器,滤光片,闪光灯,图像处理器(ISP)
(2)系统
手机的相机系统可以分为两个部分,一个是相机模组,一个是图像处理器ISP,相机模组是用来进行进行光电转换的,而图像处理器正如之前所介绍那样是用于图像处理的。
手机镜头参数:
视场角FOV,该参数表明了通过镜头可以成像多大范围的场景,一般FOV越大就越能看到大范围的景物,但是有可能会带来严重的畸变,通常使用后期的畸变矫正算法来修正大FOV所带来的畸变。
焦距F,规定所有平行于透镜主轴的光线汇聚到的那点叫做焦点,而焦点到透镜中心的距离便是这里的焦距,一般焦距越大,镜头的FOV也就越小。而越短的焦距,往往FOV越大。
光圈值f,通过镜头焦距与实际光圈的直径比值来指定,该值越小,说明进光量也就越大,手机镜头一般采用f/2.0的固定光圈。
(3)双摄
背景虚化(RGB+RGB)
暗光提升(RGB+MONO)
光学变焦(广角+长焦)
3、CamX关键流程
当系统启动的时候,Camera Provider主程序会被运行,在整个程序初始化的过程中会通过获取到的camera_module_t调用其get_number_of_camera接口获取底层支持的camera数量,由于是第一次获取,所以在CamX-CHI中会伴随着很多初始化动作。另外在初始化阶段还有一个比较重要的操作就是CamX 与CHI是通过互相dlopen对方的So库,获取了对方的入口方法,最后通过彼此的入口方法获取了对方操作方法集合,之后再通过这些操作方法与对方进行通讯。
注:
Linux/unix 提供了使用 dlopen 和 dlsym 方法动态加载库和调用函数,这套方法在 macOS 和 iOS 上也支持。
dlopen 打开一个库,获取句柄。
dlsym 在打开的库中查找符号的值。
dlclose 关闭句柄。
dlerror 返回一个描述最后一次调用dlopen、dlsym,或 dlclose 的错误信息的字符串。
(1)Open Camera
remap()图像的重映射,可以把一幅图像中某位置的像素放置到另一个图片指定位置的过程。可以实现图像的变形,扭曲,反转等操作。实现图像数据的增强,提升深度模型的泛化能力。可以根据自己设定的函数将图像进行变换,较常见的功能有关于x轴翻转,关于y轴翻转,关于x、y轴翻转;(仿射变换在图像处理中的主要功能为:对图像进行缩放、旋转、平移、扭曲等)。
(2)Configure Streams
!根据operation_mode、camera 个数以及stream的配置信息选取了对应的UsecaseId
!根据所选取的UsecaseId,使用UsecaseFactory简单工厂类创建了用于管理整个场景下所有资源的AdvancedCameraUsecase对象。
!创建AdvancedCameraUsecase对象是通过调用其Create()方法完成,该方法中获取了common_usecase.xml定义的关于Usecase的配置信息,之后又根据需要创建了Feature并选取了Feature所需的pipeline,并通过Override机制将Feature中所需要的Pipeline加入重建后的Usecase中。
!最后通过调用CameraUsecaseBaese的initialize方法依次创建了各个pipeline以及Session,并且将AdvancedCameraUsecase的成员方法注册到Session,用于Session将数据返回给Usecase中。
(3)ProcessCaptureRequest
没太懂
(4)ProcessCaptureResult
每一个Request对应了三个Result,分别是partial metadata、metadata以及image data,对于每一个Result,上传过程可以大致分为以下两个阶段:
Session内部完成图像数据的处理,将结果发送至Usecase中
Usecase接收到来自Session的数据,并将其上传至Provider
4、KMD框架
六、各种拍照模式
1、相机拍照的八种模式:
(1)风景模式:拍摄风景名胜时,数码相机会把光圈调到最小以增加景深,另外对焦也变成无限远,使相片获得最清晰的效果。
人像模式:用来拍摄人物相片,如证件照。数码相机会把光圈调到最大,做出浅景深的效果。而有些相机还会使用能够表现更强肤色效果的色调、对比度或柔化效果进行拍摄,以突出人像主体。
夜景模式:夜景模式一般有两种,前者使用1/10秒左右的快门进行拍摄,从而有可能导致曝光不足。而后者则使用数秒长的快门曝光时间,以保证相片充分曝光,相片画面也会比较亮。上述两种都使用较小的光圈进行拍摄,同时闪光灯也会关闭。
夜景人像模式:在夜景中拍摄人物(如逛灯会),数码相机通常会使用数秒至1/10秒左右的快门拍摄远处的风景,并使用闪光灯照亮前景的人物主体,闪光灯通常会在快闪关闭前被触发。
动态模式(运动模式):用来拍摄高速移动的物体,数码相机会把快门速度调到较快(1/500秒),或提高ISO感光值。
微距模式:用来拍摄细微的目标如花卉、昆虫等等,数码相机会使用“微距”焦距,并关闭闪光灯。
逆光模式:在一些背光的环境下使用,即主体的背后有较强的光线。相机会采用重点测光以增强曝光的准确性、并增加EV值以避免主体过暗,有些相机还会使用闪光灯进行补光。
全景模式:拍摄超宽幅度的画面(如山脉、大海)时,数码相机会在每张相片后留出多余位置,帮助摄影者连续拍摄多张风景相片,再组成一张超宽的风景照。
(2)延时摄影
延时摄影是一种时间压缩拍摄技术,拍摄延时摄影主要有三种方法:录像加速、延时摄影功能、照片合成。
录像加速能把整个过程都拍摄下来,还有现场的声音。在拍朝霞、晚霞、流星雨这种瞬息万变的场景下,能保留最美的瞬间。后期也可以挑选精彩片段进行延时视频制作。缺点就是需占用很大的存储空间,并且功耗比较大,长时间录像,手机容易发烫过热导致关机。在夜景弱光场景下画质比较差,噪点会很明显。视频画面也会被裁切,在近距离构图时,拍的景可能没法完全展示在画面中。
延时摄影功能自动帮你完成了录像加速处理。
照片合成画质好,RAW文件非常大,1秒30张照片。
拍摄延时摄影对稳定性有很高的要求。
(3)人像模式
大光圈浅景深
(4)慢动作
fps(frames per second 每秒传输帧数)
实现慢动作,需要高帧率,拍摄帧率越高,越能流畅地实现更有逼格的慢动作效果。但是高幁率拍摄会严重影响画质,低光效果不佳,失去电影感,
2、HDR拍照模式
(High Dynamic Range Imaging)高动态范围成像,用来实现比普通数字图像技术更大曝光动态范围(即更大的明暗差别)的一组技术。相比普通的图像,可以提供更多的动态范围和图像细节,根据不同的曝光时间的LDR(Low-Dynamic Range)图像,利用每个曝光时间相对应最佳细节的LDR图像来合成最终HDR图像。比较适合在阴暗变化明显的场景下使用,这样能使明处的景物不致过曝,而使得暗处的景物不致欠曝。
实现方法:其实现方法是通过设三组 ev 值来对当前拍摄的景物曝光,一张照片是使用当前测光从而算出来的正常情况下的ev值曝光,另外两张则分别使用其0.5倍的ev值和2倍的ev值进行曝光。最终对三张照片按某种算法进行合成,暗处的景物使用2倍ev曝光的局部照片,而亮处的物体则使用0.5倍ev曝光的局部照片。这样就能使得整个照片的场景都不致于太亮或太暗。
3、荣耀50pro
大光圈、夜景、人像、全景、HDR、延时摄影、微距、高像素、PRO(手动调节测光方式、ISO感光度、快门、曝光补偿、对焦方式、白平衡等)。
4、Android Camera 曝光
曝光三要素:光圈大小、快门速度、感光度(ISO)。光圈指曝光瞬间开孔大小;快门速度指快门开启时间;感光度指图像传感器对光线的敏感程度。
光圈F值 = 镜头焦距/镜头光圈直径
光圈值系列:F1.0,F1.4,F2.0,F2.8,F4.0,F5.6,F8.0,F11,F16,F22,F32,F44,F64
光圈F值越小,光圈越大,进光量越多,反之相反。在夜拍或暗光环境下,大光圈的成像优势就更显著。
快门时间以秒为单位,常见为:
16,8,4,2,1,1/2,1/4,1/8,1/15,1/30,1/60,1/125,1/250,1/500,1/1000,1/4000。
快门时间就是相机里控制的曝光时间,曝光控制(光圈+快门控制) 传感器中,感光二极管加电工作的时间,就是曝光时间,也就是所谓的快门时间。Sensor的曝光方式有几种,全帧曝光和逐行曝光:
1)全帧曝光:Sensor通电后,所有的感光二极管是同时开始工作的,只要控制Sensor加电时间的长短,就能控制曝光时间了。
2)逐行曝光:Sensor通电后,感光二极管是一行一行开始工作的,你必须控制是哪一行曝光,然后计算总的曝光时间。AEC中的max_linecount为曝光时间的最大值。因为一秒能接收的像素点以及一行存储的像素点是固定的,那接收到的像素点占的行数就可以体现曝光时间的长短,max_linecount越大,说明接收到的像素点越多,也就说明曝光时间越长。
例如:
.line_lenth_pclk = 6004; //每一帧每一行多少个pixels
.frame_length_lines = 3284; //每一帧多少行
.max_fps = 30.00;//最大帧数
.min_fps = 10.00;//最小帧数
max_Linecount = frame_length_lines * fps * max_time
如公式,max_time为快门时间的最大时间,与sensor输出帧数、每帧行数、最大接收行数有关。
感光度(ISO)
ISO决定CCD/CMOS的感光速度,ISO值越大,感光越快,不过图像质量会有些许下降。
5、拍照流程
1)按照常规方式打开预览
2)设置好相应的全局变量:
CameraDevice的cameraDevice
CameraCaptureSession的mPreviewSession
CaptureRequest.Builder的captureRequestBuilder
ImageReader的imageReader
等
3)定义一个类似takePicture()的开始拍照方法
4)自动对焦, 直接开始拍照, 调用类似captureStillPicture()的方法
5)自动对焦
// 设置自动对焦模式
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
6)拍摄前, 如果需要闪光的, 需要设置,下面这条语句会触发闪光的开启动作
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
7)添加拍摄图片的输出
captureRequestBuilder.addTarget(mImageReader.getSurface());
8)设置当前的拍摄意图,下面这条设置页会影响到闪光的正常开启. 如果不需要闪光灯的话, 设置了也没事。
captureRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CameraMetadata.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
9)设置图片的方向
因为物理相机的镜头方向可能和手机的朝向不一致(手机倒着拿), 所以设置这个是确保拍摄出来的图片永远是正向的
int sensorOrientation = mCameraCharacteristics.get(
CameraCharacteristics.SENSOR_ORIENTATION);
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION,
(sensorOrientation +
mDisplayOrientation * (mFacing == Constants.FACING_FRONT ? 1 : -1) +
360) % 360);
10)停止画面预览
mPreviewSession.stopRepeating();
也可以不调用这条,不停止画面,不过这样会出现闪光灯闪烁2次的问题。
11)开始拍照
mPreviewSession.capture(captureRequestBuilder.build(),
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
@NonNull CaptureRequest request,
@NonNull TotalCaptureResult result) {
//移除输出到ImageReader, 不移除的话,会造成拍照停不下来的问题
captureRequestBuilder.removeTarget(imageReader.getSurface());
//恢复相机预提为预览
captureRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CameraMetadata.CONTROL_CAPTURE_INTENT_PREVIEW);
try {
//不加这句话, 闪光灯无法正常工作, 如果不适用闪光等, 可以不加
mPreviewSession.capture(mPreviewRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
}, null);
/**拍照*/
private void takePicture()
{
try
{
if (cameraDevice == null)
}
// 创建拍照请求
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
// 设置自动对焦模式
captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
// 将imageReader的surface设为目标
captureRequestBuilder.addTarget(imageReader.getSurface());
// 获取设备方向
int rotation = getWindowManager().getDefaultDisplay().getRotation();
// 根据设备方向计算设置照片的方向
captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION
, ORIENTATIONS.get(rotation));
mCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, 5);
// 停止连续取景
mPreviewSession.stopRepeating();
mPreviewSession.abortCaptures();
//拍照
CaptureRequest captureRequest = captureRequestBuilder.build();
//设置拍照监听
mPreviewSession.capture(captureRequest,captureCallback, null);
}
catch (CameraAccessException e)
{
e.printStackTrace();
}
}
七、vi、git命令和adb命令
1、VI
VI命令
(1)vi 编辑器有 3 种基本工作模式,分别是命令模式、文本输入模式和末行模式。
命令行模式该模式是进入 vi 编辑器后的默认模式。任何时候,不管用户处于何种模式,按下Esc键即可进入命令模式。
在命令模式下输入插入命令i、附加命令a、打开命令o、修改命令c、取代命令r或替换命令s都可以进入文本输入模式。
末行模式也称 ex 转义模式,在命令模式下,用户按:键即可进入末行模式下,末行命令执行完后,vi 自动回到命令模式。
(2)进入
打开一个 shell 终端,在说明符后输入 vi和 想要编辑(或建立)的文件名,便可进入 vi 编辑器,其格式如下:vi filename
最后一行也称状态行,显示当前正在编辑的文件名及其状态。
(3)文本修改
插入文本:屏幕最下行显示 “–INSERT–”说明信息,i 命令将文本插入到光标所在位置前,I 命令将文本插入当前行的行首。
追加文本:a 命令将新文本追加到光标当前所在位置之后,A 命令将新文本追加到所在行的行尾。
空行插入:o 命令将在光标所在行的下面插入一个空行,并将光标置于该行的行首,O 命令在光标所在行的上面插入一个空行,并将光标置于该行的行首。
(4)文本删除
编辑模式下,使用退格键或 Del 键删除文本。
命令模式下:
x 删除光标处的字符
X 删除光标前面的字符
d( 删除到上一句开始的所有字符
d) 删除到下一句开始的所有字符
dd 删除光标所在的整行
d{ 删除到上一段开始的所有字符
D 或 d$ 删除从光标所在处开始到行尾 的内容
d} 删除到下一段开始的所有字符
d0 删除从光标前一个字符开始到 行首的内容
d 删除包括当前行在内的两行字符
dw 删除一个单词
删除文本的命令可以分为删除单个字符和删除多个字符两类。其中,删除单个字符的命令包括下面两种情况。
x 命令:删除光标处的字符。若在 x 之前加上一个数字 n,则删除从光标所在位置开始向右的 n 个字符。
X 命令:删除光标前面的字符。若在 X 之前加上一个数字 n,则删除从光标前面那个字符开始向左的 n 个字符。
(5)文本复制
可以在编辑模式和命令模式下复制文本。
命令模式下常用的文本复制命令:
yy 复制光标所在的整行
y{ 复制到上一段的开始
Y 或 y$ 复制从光标所在处开始到行尾的内容
y} 复制到下一段的开始
y0 复制从光标前一个字符开始到行首的内容
y 复制包括当前行在内的两行内容
y( 复制到上一句的开始 yw 复制一个单词
y) 复制到下一句的开始
文本粘贴命令
p 命令:粘贴命令,粘贴当前缓冲区中的内容。
文本选择命令
v 命令:在命令模式下进行文本选择。在需要选择的文本的起始处按下 v 键进入块选择模式,然后移动光标到块尾处。这之间的部分被高亮显示,表示被选中。
V 命令:在命令模式下按行进行文本选择。在需要选择的文本的第一行按下 V 键,然后移动光标到块的最后一行。这之间的所有行被高亮显示,表示被选中。
(6)文本撤销
u 命令:该命令撤销上一次所做的操作。多次使用 u 命令会一步一步依次撤销之前做过的操作(在一次切换到文本输入模式中输入的所有文本算一次操作)。
U 命令:该命令会一次性撤销自上次移动到当前行以来做过的所有操作,再使用一次 U 命令则撤销之前的 U 命令所做的操作,恢复被撤销的内容。
(7)重复上次操作
重复命令只能在命令模式下工作,在该模式下按下.键即可。
(8)退出命令
末行模式下
:q,如果退出时当前编辑文件尚未保存,则 vi 并不退出,而是继续等待用户的命令;
:q!该命令不论文件是否改变都会强行退出 vi 编辑器;
:w 新文件名,vi 保存当前编辑文件,但并不退出,而是继续等待用户输入命令;
:w! 新文件名,即使指定的新文件存在,vi 编辑器也会用当前编辑文件对其进行替换,而不再询问用户;
:wq ,vi 将先保存文件,然后退出 vi 返回到 shell。如果当前文件尚未取名,则需要现指定一个文件名;
:x,若当前编辑文件曾被修改过,则 vi 会保存该文件。否则 vi 直接退出,不保存该文件。
(9)字符替换
r,该命令将当前光标所指的字符替换为提供的字符。可以在该命令之前加上数字 n,表示将从当前字符开始的 n 个字符替换为提供的字符。
R,该命令会让 vi 进入 replace 模式。在此模式下,每个输入的字符都会替换当前光标下的字符,直到输入 结束该模式。
(10)光标移动
h 光标左移一个字符
k 光标上移一行
j 光标下移一行
l 光标右移一个字符
H 将光标移至当前屏幕的第 1 行,而不是整个文件的第 1 行。若在 H 命令之前加 上数字 n,则将光标移至第 n 行的行首。
M将光标移至屏幕显示文件的中间行的行首。
L将光标移至屏幕显示文件的最底行的行首。
G在全文的范围内移动光标,此时的光标移动范围不再受屏幕的限制。
w 和 W 命令将光标右移至下一个字的字首。w 命令所指的字是指英文单词、标点符号和非字母字符;W 命令所指的字是指两个空格之间的任何内容。
e和E命令,如果光标起始位置处于字内,则 e 和 E 命令将把光标移到本字字尾;如果光标起始位置处于字尾,则 e 和 E 命令将把光标移动到下一个字的字尾。
b和B命令,如果光标处于所在字内,则 b 和 B 命令将把光标移至本字字首;如果光标处于所在字字首,则 b 和 B 命令将把光标移到上一个字的字首。
(11)按段落移动
在 vi 编辑器中,一个段落被定义为是以一个空白行开始和结束的片段。按段落移动光标的命令有以下两种。
{命令:该命令将光标向前移至上一个段落的开头。
}命令:该命令将光标向后移至下一个段落的开头。
(12)文本移动
右移命令将指定的正文行向右移动,通常是右移 8 个空格。移动正文行的范围由光标所在行和随后输入的光标移动命令所限定。
双右移也是将光标所在行右移 8 个空格,但是前面加数字,表示将当前行下面的n行都移动。
m 命令实现文本的跨行移动。该命令的使用方法为:imj,表示把第 i 行移至第 j 行的下方。下面实例演示了 m 命令的使用。
(13)屏幕滚动
使用屏幕命令可以以屏幕为单位移动光标,方便地完成文件的滚屏和分页。
Ctrl+u 将屏幕向前(文件头方向)翻滚半屏
Ctrl+d 将屏幕向后(文件尾方向)翻滚半屏
Ctrl+f 将屏幕向文件尾方向翻滚一整屏
Ctrl+b 将屏幕向文件首方向翻滚一整屏
(14)字符检索
末行模式下
/string 从光标处开始向后寻找字符串string
?string从光标处开始向前寻找字符串 string
n 命令重复上一条检索命令
N 命令重复上一条检索命令,但检索方向改变
g/stringg/命令使光标停止在第一个检索到的 string 串的行首
(15)字符串替换
末行模式下
[range]s/s1/s2/ [option]
[range] 表示检索范围,省略时表示当前行。下面是一些检索范围的例子。
1,10表示从第 1 行到 10 行。
%表示整个文件,同1,。
. ,$从当前行到文件尾。
s 为替换命令。
s1 要被替换的串,s2 为替换的串。
option 表示选项:
/g表示在全局文件中进行替换。
/c表示在每次替换之前需要用户进行确认。
省略时仅对每行第一个匹配串进行替换。
(16)属性设置
末行模式下
:set nu (nonu)显示行号(或者不显示行号)。
:set hlsearch (nohlsearch)设定搜寻字符串反白显示(或者不反白显示)。
:set autoindent显示程序语法自动缩进。
:set backup(nobackup)自动储存备份文件(或者不自动备份文件)。
:set all显示所有的选项。
:syntax on (off)实现程序语法高亮显示(或者不高亮显示)。
:set ignorecase(noignorecase)忽略大小写(或者区分大小写)。
2、adb
adb操作命令及用法大全
(1)Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令可用于执行各种设备操作(例如安装和调试应用),并提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。它是一种客户端-服务器程序,包括以下三个组件:
客户端:用于发送命令。客户端在开发机器上运行。您可以通过发出 adb 命令从命令行终端调用客户端。
守护程序 (adbd):用于在设备上运行命令。守护程序在每个设备上作为后台进程运行。
服务器:用于管理客户端与守护程序之间的通信。服务器在开发机器上作为后台进程运行。
主要功能有:
在设备上运行Shell命令;
将本地APK软件安装至模拟器或Android设备;
管理设备或手机模拟器上的预定端口;
在设备或手机模拟器上复制或粘贴文件。
命令语法:
adb [-d|-e|-s ]
多个设备:
-d 指定当前唯一通过 USB 连接的 Android 设备为命令目标
-e 指定当前唯一运行的模拟器为命令目标
-s 指定相应设备序列号的设备/模拟器为命令目标
(2)常用命令
adb devices #查看连接设备
adb -s cf27456f shell # 指定连接设备使用命令
adb install test.apk # 安装应用
adb install -r demo.apk #安装apk 到sd 卡:
adb uninstall cn.com.test.mobile #卸载应用,需要指定包
adb uninstall -k cn.com.test.mobile #卸载app 但保留数据和缓存文件
adb shell pm list packages #列出手机装的所有app 的包名
adb shell pm list packages -3 #列出除了系统应用的第三方应用包名
adb shell pm clear cn.com.test.mobile #清除应用数据与缓存
adb shell am start -ncn.com.test.mobile/.ui.SplashActivity #启动应用
adb shell dumpsys package #包信息Package Information
adb shell dumpsys meminfo #内存使用情况Memory Usage
adb shell am force-stop cn.com.test.mobile #强制停止应用
adb logcat #查看日志
adb logcat -c #清除log 缓存
adb reboot #重启
adb get-serialno #获取序列号
adb shell getprop ro.build.version.release #查看Android 系统版本
adb shell top -s 10 #查看占用内存前10 的app
adb push #从本地复制文件到设备
adb pull #从设备复制文件到本地
adb bugreport #查看bug 报告
adb help #查看ADB 帮助
3、git
Linux命令