相機(jī)啟動(dòng),前后攝切換性能優(yōu)化報(bào)告

背景

id5a岖沛、id6平臺(tái)我們的相機(jī)暑始,對(duì)比相同平臺(tái)紅米6a和6的相機(jī),冷熱啟動(dòng)婴削,前后攝切換性能要差廊镜,對(duì)比競(jìng)品,我們期望優(yōu)化的比紅米6a和6的相機(jī)快10%.

問題分解

性能優(yōu)化的核心就是找到影響性能的hotspot,查找hotspot也是有套路的唉俗,首先要把相機(jī)啟動(dòng)流程分解出來嗤朴,一個(gè)階段一個(gè)階段分析。

相機(jī)的冷啟動(dòng)虫溜,可以分解如下幾步:

  1. AMS啟動(dòng)相機(jī)的Activity -> 相機(jī)的Activity收到onCreated消息 (可體現(xiàn)系統(tǒng)的性能)雹姊。
  2. onCreate begin -> onCreate end(主要是ui的加載)
  3. openCamera -> CameraOpened
  4. TextureView add -> SurfaceTexture created (Surface的創(chuàng)建時(shí)間)
  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

其中花時(shí)間的步驟,是2衡楞、3吱雏、4、5,主要ui加載瘾境,openCamera歧杏,surfaceCreated、startPreview寄雀。openCamera和startPreview花時(shí)間需要驅(qū)動(dòng)優(yōu)化得滤。ui加載和surfaceCreate需要上層看。

工具分析

traceView分析ui加載盒犹,發(fā)現(xiàn)沒有可優(yōu)化的懂更,現(xiàn)在加載的ui都是需要一進(jìn)去就要看見的眨业,不需要進(jìn)去看見的view,都使用viewStub延時(shí)加載處理了沮协,并且關(guān)于ui也優(yōu)化了好幾波龄捡。優(yōu)化空間比較小。不過針對(duì)冷啟動(dòng)慷暂,可以使用內(nèi)存常駐的方案聘殖,這樣實(shí)際上冷啟動(dòng)就是熱啟動(dòng)。主要原因是相機(jī)在手機(jī)啟動(dòng)時(shí)行瑞,收到啟動(dòng)廣播會(huì)啟動(dòng)一個(gè)服務(wù)奸腺,用于檢測(cè)是否溫度過高,服務(wù)拉起了相機(jī)應(yīng)用血久。內(nèi)存常駐后突照,此應(yīng)用就不被殺掉了。這樣啟動(dòng)速度優(yōu)化很大氧吐。
目前的方案:2G以上項(xiàng)目默認(rèn)使用內(nèi)存常駐方案讹蘑。

traceView教程

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

surface create優(yōu)化

現(xiàn)在主要的大頭就是Surface create優(yōu)化了。systrace分析創(chuàng)建surface過程筑舅,發(fā)現(xiàn)ArcFilter HandleThread一直在wait座慰。

systrace的教程

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

查看代碼,是濾鏡等待arc算法引擎初始化和GL引擎初始化翠拣。這里的設(shè)計(jì)是有爭(zhēng)議的版仔,其實(shí)相機(jī)啟動(dòng)的時(shí)候并沒有開啟濾鏡,但是要初始化濾鏡的引擎心剥。做耗時(shí)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.

優(yōu)化方案

這有兩種優(yōu)化方案:

  1. 啟動(dòng)時(shí)邦尊,不加載濾鏡引擎背桐,切換到濾鏡時(shí)加載优烧。后果是切換濾鏡時(shí)會(huì)卡一下,需要修改整個(gè)流程链峭,代碼修改量大畦娄。
  2. 分步初始化GLEnv和濾鏡引擎,理論上可以優(yōu)化120ms+,創(chuàng)建Surface和startPreview并行執(zhí)行弊仪。代碼改動(dòng)小熙卡,并且能達(dá)到優(yōu)化效果。

目前使用第二種方案励饵,代碼提交記錄:

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

前后切換速度優(yōu)化

前后切換速度對(duì)上層來說驳癌,主要有兩個(gè)方面影響,一是翻轉(zhuǎn)動(dòng)畫役听,一是高斯模糊颓鲜。翻轉(zhuǎn)動(dòng)畫使用高速相機(jī)測(cè)量表窘,只有9幀,平臺(tái)性能限制甜滨,有一種帶不動(dòng)的感覺乐严,對(duì)標(biāo)機(jī)也沒有,和產(chǎn)品溝通去掉衣摩。 能優(yōu)化的就是高斯模糊了昂验。

高斯模糊的耗時(shí)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
   

整個(gè)高斯模糊流程大概需要花279ms,主要耗時(shí)是getPreview和blurBitmap艾扮,還有init每次都要做既琴。

優(yōu)化方案

init需要花40多少ms,只做一次泡嘴。getPreview呛梆,對(duì)于高斯模糊,我們不需要一張清晰的圖片磕诊,反正后面也要做模糊填物。getPreview時(shí),我們?cè)O(shè)置一個(gè)采樣率霎终,采樣質(zhì)量降低16倍滞磺,做高斯模糊時(shí),我們?cè)O(shè)置一個(gè)較小模糊半徑因子莱褒,目前為5击困,這樣做模糊的速度快,模糊效果好广凸。

優(yōu)化后的耗時(shí)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/

熱啟動(dòng)優(yōu)化

熱啟動(dòng)優(yōu)化阅茶,和對(duì)比機(jī)不同的是,在預(yù)覽沒有出來之前谅海,我們做了一個(gè)高斯模糊的蓋板脸哀。和產(chǎn)品溝通需要去掉,去掉蓋板比較容易扭吁。引發(fā)兩個(gè)問題需要解決撞蜂。

  1. TextureView沒有被銷毀,會(huì)保留上一幀侥袜。主要表現(xiàn)熱啟動(dòng)會(huì)閃上一幀蝌诡。
  2. framework會(huì)有一個(gè)screenshot界面,同樣會(huì)閃上幀枫吧。

解決方案:

  1. 在pause時(shí)浦旱,把TextureView的alpha設(shè)置為0,第一幀上來,再把a(bǔ)lpha設(shè)置1九杂,讓其顯示颁湖。
  2. 應(yīng)用層關(guān)掉screenshot.

代碼提交記錄:

http://192.168.10.10/#/c/215036/
http://192.168.10.10/#/c/214142/

驅(qū)動(dòng)優(yōu)化

關(guān)于openCamera和startPreview優(yōu)化代兵,底層優(yōu)化了3a算法、加入了fastae和使用speed mode模式爷狈。詳情可以咨詢彭葉斌同學(xué)植影。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市涎永,隨后出現(xiàn)的幾起案子思币,更是在濱河造成了極大的恐慌,老刑警劉巖羡微,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谷饿,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡妈倔,警方通過查閱死者的電腦和手機(jī)博投,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盯蝴,“玉大人毅哗,你說我怎么就攤上這事∨跬Γ” “怎么了虑绵?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)闽烙。 經(jīng)常有香客問我翅睛,道長(zhǎng),這世上最難降的妖魔是什么黑竞? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任捕发,我火速辦了婚禮,結(jié)果婚禮上很魂,老公的妹妹穿的比我還像新娘扎酷。我一直安慰自己,他們只是感情好莫换,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布霞玄。 她就那樣靜靜地躺著,像睡著了一般拉岁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惰爬,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天喊暖,我揣著相機(jī)與錄音,去河邊找鬼撕瞧。 笑死陵叽,一個(gè)胖子當(dāng)著我的面吹牛狞尔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播巩掺,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼偏序,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了胖替?” 一聲冷哼從身側(cè)響起研儒,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎独令,沒想到半個(gè)月后端朵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡燃箭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年冲呢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片招狸。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡敬拓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出裙戏,到底是詐尸還是另有隱情恩尾,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布挽懦,位于F島的核電站翰意,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏信柿。R本人自食惡果不足惜冀偶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望渔嚷。 院中可真熱鬧进鸠,春花似錦、人聲如沸形病。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漠吻。三九已至量瓜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間途乃,已是汗流浹背绍傲。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人烫饼。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓猎塞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親杠纵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子荠耽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容