MTK Camera 冷启动、前后摄切换性能优化分析

news2024/9/26 5:12:24

和你一起终身学习,这里是程序员Android

经典好文推荐,通过阅读本文,您将收获以下知识点:

一、背景
二、问题分解
三、工具分析
四、 traceView教程
五、surface create优化
六、systrace的教程
七、优化方案
八、前后切换速度优化
九、优化方案
十、热启动优化
十一、解决方案:
十二、驱动优化

一、背景

id5a、id6平台我们的相机,对比相同平台红米6a和6的相机,冷热启动,前后摄切换性能要差,对比竞品,我们期望优化的比红米6a和6的相机快10%.

二、问题分解

性能优化的核心就是找到影响性能的hotspot,查找hotspot也是有套路的,首先要把相机启动流程分解出来,一个阶段一个阶段分析。

相机的冷启动,可以分解如下几步:

1.AMS启动相机的Activity -> 相机的Activity收到onCreated消息 (可体现系统的性能)。
2.onCreate begin -> onCreate end(主要是ui的加载)
3.openCamera -> CameraOpened
4.TextureView add -> SurfaceTexture created (Surface的创建时间)
5.startPreview -> PreviewStarted
6.setWindow -> PreviewCallback

Log如下:

01-01 12:01:57.099   794  3012 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.mediatek.camera/.CameraLauncher bnds=[150,976][290,1202] (has extras)} from uid 10064
01-01 12:01:57.169  8261  8261 D CamAp_QuickActivity: [  0.000ms][BEGIN] onCreate
01-01 12:01:57.196  8261  8295 I CamAp_API1-Handler-0: [openCamera]+
01-01 12:01:57.217   532  2586 I mtkcam-dev1: [createSpecificCameraDevice1] dlopen libmtkcam_device1.so +
01-01 12:01:57.224   532  2586 I mtkcam-dev1: [createSpecificCameraDevice1] dlopen libmtkcam_device1.so -
01-01 12:01:57.259   532  2586 I mtkcam-dev1: [createSpecificCameraDevice1] - 0xe6a0ec00
01-01 12:01:57.260   532  2586 I mtkcam-dev1: 0[CameraDevice1Base::open] +
01-01 12:01:57.419   532  2586 I mtkcam-dev1: 0[CameraDevice1Base::open] Add new cameraId 0 - 0xe6a0ec00
01-01 12:01:57.419   532  2586 I mtkcam-dev1: 0[CameraDevice1Base::open] -

01-01 12:01:57.424  8261  8295 I CamAp_API1-Handler-0: [openCamera]-, executing time = 228ms.
01-01 12:01:57.537  8261  8261 D CamAp_QuickActivity: [367.294ms]  [END] onCreate
01-01 12:01:57.542  8261  8261 D CamAp_QuickActivity: [  0.000ms][BEGIN] onStart
01-01 12:01:57.546  8261  8261 D CamAp_QuickActivity: [  3.762ms]  [END] onStart
01-01 12:01:57.549  8261  8261 D CamAp_QuickActivity: [  0.000ms][BEGIN] onResume
01-01 12:01:57.552  8261  8261 D CamAp_QuickActivity: isKeyguardLocked = false
01-01 12:01:57.552  8261  8261 D CamAp_QuickActivity: onResume --> onPermissionResumeTasks()
01-01 12:01:57.600  8261  8261 D CamAp_QuickActivity: [ 50.774ms]  [END] onResume

01-01 12:01:57.685  8261  8294 I CamAp_API1-Handler-0: [setPreviewDisplay]+, pending time = 0ms.
01-01 12:01:57.686  8261  8294 I CamAp_API1-Handler-0: [setPreviewDisplay]-, executing time = 1ms.

01-01 12:01:57.700  8261  8294 I CamAp_API1-Handler-0: [startPreview]+, pending time = 0ms.
01-01 12:01:57.701   532  2586 W mtkcam-dev1: 0[CameraDevice1Base::initDisplayClient] NULL window is passed into...
01-01 12:01:57.701   532  2586 I mtkcam-dev1: 0[CameraDevice1Base::startPreview] +

01-01 12:01:57.720  8261  8261 I CamAp_TextureViewController: updatePreviewSize: new size (960 , 720 ) current size (0 , 0 ),mIsSurfaceCreated = false listener = com.mediatek.camera.common.mode.photo.PhotoMode$SurfaceChangeListener@a79ec89

01-01 12:01:57.735   532  2586 I mtkcam-dev1: 0[CameraDevice1Base::startPreview] - status(0)

01-01 12:01:57.736  8261  8294 I CamAp_API1-Handler-0: [startPreview]-, executing time = 36ms.
01-01 12:01:57.948   532  8363 I MtkCam/DCNode: [0::waitPreviewReady]wait for start preview done +
01-01 12:01:58.087   532  8363 I MtkCam/DCNode: [0::waitPreviewReady]wait for start preview done - , use 130 ms

01-01 12:01:58.053  8261  8261 D CamAp_TextureViewController: onSurfaceTextureAvailable surface  = android.graphics.SurfaceTexture@2d48d1c width 720 height 960

01-01 12:01:58.056  8261  8294 I CamAp_API1-Handler-0: [setPreviewTexture]+, pending time = 0ms.
01-01 12:01:58.087   532  8363 I MtkCam/CamAdapter: (8363)[transitState] StateIdle --> StatePreview
01-01 12:01:58.089   532  2586 I MtkCam/DisplayClient: [setWindow] + window(0xe6a0ecf0), WxH=960x720, count(6), iNativeWindowConsumerUsage(256)

01-01 12:01:58.093  8261  8294 I CamAp_API1-Handler-0: [setPreviewTexture]-, executing time = 37ms.

01-01 12:01:58.279  8261  8295 D CamAp_PhotoDeviceController: [onPreviewFrame] mModeDeviceCallback = com.mediatek.camera.common.mode.photo.PhotoMode@feb2273

其中OnCreate begin -> onCreate end:花了367ms

01-01 12:01:57.169  8261  8261 D CamAp_QuickActivity: [  0.000ms][BEGIN] onCreate
01-01 12:01:57.537  8261  8261 D CamAp_QuickActivity: [367.294ms]  [END] onCreate

其中openCamera: 花了238ms

01-01 12:01:57.196  8261  8295 I CamAp_API1-Handler-0: [openCamera]+
01-01 12:01:57.424  8261  8295 I CamAp_API1-Handler-0: [openCamera]-, executing time = 228ms.

其中Surface Create: 花了333ms

01-01 12:01:57.720  8261  8261 I CamAp_TextureViewController: updatePreviewSize: new size (960 , 720 ) current size (0 , 0 ),mIsSurfaceCreated = false listener = com.mediatek.camera.common.mode.photo.PhotoMode$SurfaceChangeListener@a79ec89
01-01 12:01:58.053  8261  8261 D CamAp_TextureViewController: onSurfaceTextureAvailable surface  = android.graphics.SurfaceTexture@2d48d1c width 720 height 960

其中startPreview:花386ms

01-01 12:01:57.701   532  2586 I mtkcam-dev1: 0[CameraDevice1Base::startPreview] +
01-01 12:01:58.087   532  8363 I MtkCam/CamAdapter: (8363)[transitState] StateIdle --> StatePreview

其中startWindow -> PreveiwCallback:花87ms

01-01 12:01:58.093  8261  8294 I CamAp_API1-Handler-0: [setPreviewTexture]-, executing time = 37ms.

01-01 12:01:58.279  8261  8295 D CamAp_PhotoDeviceController: [onPreviewFrame] mModeDeviceCallback = com.mediatek.camera.common.mode.photo.PhotoMode@feb2273

其中花时间的步骤,是2、3、4、5,主要ui加载,openCamera,surfaceCreated、startPreview。openCamera和startPreview花时间需要驱动优化。ui加载和surfaceCreate需要上层看。

三、工具分析

traceView分析ui加载,发现没有可优化的,现在加载的ui都是需要一进去就要看见的,不需要进去看见的view,都使用viewStub延时加载处理了,并且关于ui也优化了好几波。优化空间比较小。不过针对冷启动,可以使用内存常驻的方案,这样实际上冷启动就是热启动。主要原因是相机在手机启动时,收到启动广播会启动一个服务,用于检测是否温度过高,服务拉起了相机应用。内存常驻后,此应用就不被杀掉了。这样启动速度优化很大。
目前的方案:2G以上项目默认使用内存常驻方案。

四、 traceView教程

https://www.jianshu.com/p/f81b20b9a7e2
https://developer.android.com/studio/profile/traceview

五、surface create优化

现在主要的大头就是Surface create优化了。systrace分析创建surface过程,发现ArcFilter HandleThread一直在wait。

六、systrace的教程

https://developer.android.google.cn/studio/command-line/systrace

查看代码,是滤镜等待arc算法引擎初始化和GL引擎初始化。这里的设计是有争议的,其实相机启动的时候并没有开启滤镜,但是要初始化滤镜的引擎。做耗时benchmark:

01-02 01:22:07.991 23458-23554/? I/CamAp_TextureEnvExt: handleGlEnvInit(): Enter
01-02 01:22:07.991 23458-23458/? V/CamAp_TextureEnvExt: getCamSurfaceTexture:: in  -1
01-02 01:22:08.090 23458-23554/? I/CamAp_TextureEnvExt: handleGlEnvInit(): Exit with bRet = EGL_SUCCESS
01-02 01:22:08.091 23458-23554/? I/CamAp_TextureEnvExt: handleArcFilterEngine(): init begin 
01-02 01:22:08.095 23458-23458/? V/CamAp_TextureEnvExt: getCamSurfaceTexture:: ID=1
01-02 01:22:08.211 23458-23554/? I/CamAp_TextureEnvExt: handleArcFilterEngine(): init end engine = 0,prepareEngine=0

可以看出:初始化GLEnv需要99ms,初始引擎需要120ms.

七、优化方案

这有两种优化方案:

  1. 启动时,不加载滤镜引擎,切换到滤镜时加载。后果是切换滤镜时会卡一下,需要修改整个流程,代码修改量大。

  2. 分步初始化GLEnv和滤镜引擎,理论上可以优化120ms+,创建Surface和startPreview并行执行。代码改动小,并且能达到优化效果。

目前使用第二种方案,代码提交记录:

http://192.168.10.10/#/c/213235/

八、前后切换速度优化

前后切换速度对上层来说,主要有两个方面影响,一是翻转动画,一是高斯模糊。翻转动画使用高速相机测量,只有9帧,平台性能限制,有一种带不动的感觉,对标机也没有,和产品沟通去掉。能优化的就是高斯模糊了。

高斯模糊的耗时benchmark:

01-02 02:00:21.636 8089-8089/? I/CamAp_GaussianBlur: GaussianBlur,create render:42
01-02 02:00:21.636 8089-8089/? D/CamAp_GaussianBlur: preview width 750 height 1500
01-02 02:00:21.731 8089-8089/? I/CamAp_GaussianBlur: getPreview bitmap spent time: 125
01-02 02:00:21.821 8089-8089/? I/CamAp_GaussianBlur: blurBitmap,render bitmap:112

整个高斯模糊流程大概需要花279ms,主要耗时是getPreview和blurBitmap,还有init每次都要做。

九、优化方案

init需要花40多少ms,只做一次。getPreview,对于高斯模糊,我们不需要一张清晰的图片,反正后面也要做模糊。getPreview时,我们设置一个采样率,采样质量降低16倍,做高斯模糊时,我们设置一个较小模糊半径因子,目前为5,这样做模糊的速度快,模糊效果好。

优化后的耗时benchmark:

01-02 02:14:15.628 20947-20947/? D/CamAp_GaussianBlur: preview width 750 height 1500
01-02 02:14:15.632 20947-20947/? I/CamAp_GaussianBlur: getPreview bitmap spent time: 4
01-02 02:14:15.636 20947-20947/? I/CamAp_GaussianBlur: blurBitmap,render bitmap:4

代码提交记录:

http://192.168.10.10/#/c/213235/

十、热启动优化

热启动优化,和对比机不同的是,在预览没有出来之前,我们做了一个高斯模糊的盖板。和产品沟通需要去掉,去掉盖板比较容易。引发两个问题需要解决。

  1. TextureView没有被销毁,会保留上一帧。主要表现热启动会闪上一帧。

  2. framework会有一个screenshot界面,同样会闪上帧。

十一、解决方案:

  1. 在pause时,把TextureView的alpha设置为0,第一帧上来,再把alpha设置1,让其显示。

  2. 应用层关掉screenshot.

十二、驱动优化

关于openCamera和startPreview优化,底层优化了3a算法、加入了fastae和使用speed mode模式。详情可以咨询彭叶斌同学。

原文链接:https://www.jianshu.com/p/77d035588bd4

相关文章友情推荐 

1. Android开发干货分享

至此,本篇已结束。转载网络的文章,小编觉得很优秀,如有侵权,恳请联系小编删除,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

af6b43d28702ccfe4c496f3ea66f779d.jpeg

点个在看,方便您使用时快速查看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1920233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

旷野之间4 - 100 个 Kubernetes 面试问题及答案

100 个 Kubernetes 面试问题及答案 Kubernetes 简介 什么是 Kubernetes? Kubernetes 是一个开源容器编排平台,可自动部署、扩展和管理容器化应用程序。 什么是容器? 容器是一个轻量级、独立的、可执行软件包,其中包含运行应用…

学习笔记——动态路由——IS-IS中间系统到中间系统(特性之路由撤销)

6、路由撤销 ISIS路由协议的路由信息是封装在LSP报文中的TLV中的,但是它对撤销路由的处理和OSPF的处理方式类似。 在ISIS中撤销一条路由实则是将接口下的ISIS关闭: 撤销内部路由: 在ISIS中路由信息是由IP接口TLV和IP内部可达性TLV共同来描…

游戏AI的创造思路-技术基础-决策树(2)

上一篇写了决策树的基础概念和一些简单例子,本篇将着重在实际案例上进行说明 目录 8. 决策树应用的实际例子 8.1. 方法和过程 8.1.1. 定义行为 8.1.2. 确定属性 8.1.3. 构建决策树 8.1.4. 实施行为 8.1.5. 实时更新 8.2. Python代码 8. 决策树应用的实际例子…

hudi数据湖万字全方位教程+应用示例

1、时间轴(TimeLine) Hudi的核心是维护表上在不同的即时时间(instants)执行的所有操作的时间轴(timeline),这有助于提供表的即时视图 一个instant由以下三个部分组成: 1)…

YOLOv10改进 | Conv篇 | RCS-OSA替换C2f实现暴力涨点(减少通道的空间对象注意力机制)

一、本文介绍 本文给大家带来的改进机制是RCS-YOLO提出的RCS-OSA模块,其全称是"Reduced Channel Spatial Object Attention",意即"减少通道的空间对象注意力"。这个模块的主要功能是通过减少特征图的通道数量,同时关注空…

Android使用AndServer在安卓设备上搭建服务端(Java)(Kotlin)两种写法

一直都是通过OkHttp远程服务端进行数据交互,突发奇想能不能也通过OkHttp在局域网的情况下对两个安卓设备或者手机进行数据交互呢? 这样一方安卓设备要当做服务端与另一个安卓设备通过OkHttp进行数据交互即可 当然还可以通过 socket 和 ServerSocket 通…

IC后端设计中的shrink系数设置方法

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 在一些成熟的工艺节点通过shrink的方式(光照过程中缩小特征尺寸比例)得到了半节点,比如40nm从45nm shrink得到,28nm从32nm shrink得到,由于半节点的性能更优异,成本又低,漏电等不利因素也可以…

旷野之间5 - AI基础代理决策的范式转变

介绍 让我们来谈谈最近在人工智能领域引起轰动的一件事——基础代理及其彻底改变我们所知的决策的潜力。现在,我知道你可能会想,“另一天,又一个人工智能突破,乏味无趣。”但相信我,这是一个改变游戏规则的突破,值得你关注。 如果您一直在关注人工智能和人工智能代理的…

JupyterNotebook中导出当前环境,并存储为requirements.txt

​使用Anaconda管理Python环境时,可以轻松地导出环境配置,以便在其他机器或环境中重新创建相同的环境。可以通过生成一个environment.yml文件实现的,该文件包含了环境中安装的所有包及其版本。但是,常常在一些课程中JupyterNotebo…

synchronized关键字详解(全面分析)

目录 synchronized关键字详解1、synchronized关键字简介2、synchronized作用和使用场景作用使用场景①、用在代码块上(类级别同步)②、用在代码块上(对象级别同步)③、用在普通方法上(对象级别同步)④、用在静态方法上(类级别同步)总结: 3、synchronized底层原理&am…

记录些Redis题集(1)

为什么Redis要有淘汰机制? 淘汰机制的存在是必要的,因为Redis是一种基于内存的数据库,所有数据都存储在内存中。然而,内存资源是有限的。在Redis的配置文件redis.conf中,有一个关键的配置项: # maxmemory…

vue3<script setup>自定义指令

main.ts // 自定义指令 app.directive(color,(el,binding) > {el.style.color binding.value })这段代码定义了一个名为color的自定义指令,并将其注册到Vue应用实例app上。自定义指令接收两个参数:el和binding。el是绑定指令的元素,而bi…

240711_昇思学习打卡-Day23-LSTM+CRF序列标注(2)

240711_昇思学习打卡-Day23-LSTMCRF序列标注(2) 今天记录LSTMCRF序列标注的第二部分。仅作简单记录 Score计算 首先计算正确标签序列所对应的得分,这里需要注意,除了转移概率矩阵𝐏外,还需要维护两个大小…

解决鸿蒙开发中克隆项目无法签名问题

文章目录 问题描述问题分析解决方案 问题描述 在一个风和日丽的早晨,这是我学习鸿蒙开发的第四天,把文档过了一遍的我准备看看别人的项目学习一下,于是就用git去clone了一个大佬的开源项目,在签名的时候遇到了问题: h…

Codeforces Round 957 (Div. 3)(A~E题解)

这次比赛只能用抽象来形容,前五道题都没有什么算法,都是思维加模拟都能过,然后第四题卡住了,第五题不知道为什么做出来的人那么少,就是纯暴力就能过,但是没抓住上分的机会,有些可惜,…

Pytorch(笔记8神经网络nn)

1、nn.Module torch.nn是专门为深度学习而设计的模块。torch.nn的核心数据结构是Module,它是一个抽象的概念,既可以表示神经网络中的某个层(layer),也可以表示一个包含很多层的神经网络。在实际使用中,最常…

可视化学习:如何用WebGL绘制3D物体

在之前的文章中,我们使用WebGL绘制了很多二维的图形和图像,在学习2D绘图的时候,我们提过很多次关于GPU的高效渲染,但是2D图形的绘制只展示了WebGL部分的能力,WebGL更强大的地方在于,它可以绘制各种3D图形&a…

一行命令快速导出、导入Python的依赖环境(Python)

文章目录 一、pip1、导出2、导入 二、Conda(简)1、导出1、导入 一、pip 1、导出 在Pycharm的Terminal窗口输入如下命令,即可将环境导出至文件requirements.txt。 pip freeze > C:\Users\sdl\Deskto\requirements.txt也可以在DOS界面执行…

python:sympy 求解一元五次方程式

pip install sympy 或者 本人用的 anaconda 3 自带 sympy 在北大数学训练营,韦东奕 用卡丹公式 巧妙 求解一元五次方程式: \latex $x^510*x^320*x-4 0$ from sympy import *x symbols(x) expr x**5 10*x**3 20*x -4# 用卡丹公式 尝试化简 a sym…

【操作系统】进程管理——用信号量机制解决问题,以生产者-消费者问题为例(个人笔记)

学习日期:2024.7.10 内容摘要:利用信号量机制解决几个经典问题模型 目录 引言 问题模型 生产者-消费者问题(经典) 多生产者-多消费者问题 吸烟者问题 读者写者问题(难点) 哲学家进餐问题&#xff0…