通過 perfetto分析預(yù)覽丟幀或者預(yù)覽卡頓的問題。
- 看 cameraservice 進(jìn)程稠集, 找到 frame capture 這個tag, 這個tag是在
Camera3Device
的sendRequestBatch
中處理的肴沫, 預(yù)覽也是走的這個流程叹话〉 這個tag的結(jié)束是在Camera3OutputUtil
中的removeInflightRequestIfNeeded
, 就是在底層處理完這個request之后驶忌。
這個tag的時長擂仍,就是 cameraservice發(fā)送到底層處理并返回image的總時長囤屹, 比如
上圖中這一幀就處理了324ms, 當(dāng)然這并不一定能說明預(yù)覽卡逢渔,只能說明當(dāng)前需要排隊(duì)處理的request比較多肋坚。 這個 frame capture也有30ms就處理完的肃廓, 就不一一列舉了智厌。
frame capture有明顯斷層的, 這就可能發(fā)生預(yù)覽卡頓了盲赊, 比如下面這兩個圖
-
當(dāng)出現(xiàn)了這種情況之后铣鹏, 我們就要看 cameraservice的 C3Dev-ReqQueu這個線程對應(yīng)的時間點(diǎn)是不是有request下發(fā), 這個是Queue里面的Request是App給的角钩×吣 如下圖
我們可以看到, 在預(yù)覽卡頓的時候递礼, App有一段時間就沒有給底層下發(fā)request.
因?yàn)锳pp的預(yù)覽流是repeating的惨险, 所以這段時間之內(nèi), 我們應(yīng)該是調(diào)用了stopReating脊髓, abortCapture等方法辫愉。
C3Dev-id-ReqQueu這種是對應(yīng)cameraid的requestThread打印的。在Camera3Device
中可以看到将硝。
尤其是我們放大觀察恭朗, 發(fā)現(xiàn)我們在waitForNextRequest的時候屏镊, 還調(diào)用了finishCameraStreamingOps
, 過了一段時間又調(diào)用startCameraStreamingOps
, 說明App肯定主動停止了預(yù)覽, 然后又開啟了
請注意finishCameraStreamingOps
這個有兩個調(diào)用時機(jī)痰腮, 一個是 cameraIdle的時候而芥, 一個是camera disconnect的時候。
- 如果說幀率有l(wèi)ag, 底層還甩鍋說他們的幀率是達(dá)標(biāo)的膀值, 怎么辦棍丐。
首先我們要在onDrawFrame的時候增加計數(shù), 看一下我們繪制的幀率是多少(可以看一下patch).
然后在找底層要一下底層返回image的log, 高通一般是:
ReturnFrameworkResult, ProcessCaptureResult 或者 process_capture_result沧踏, 證明我們的onDrawFrame和底層返回的是匹配的就可以歌逢。
我們還可以通過如下的截圖看到, 讀取yuv格式的Image到byte數(shù)組的時候是CPU密集型的任務(wù)翘狱, 然后 從byte數(shù)組生成 YUVImage秘案, 在用YUVImage compressJpeg的時候, 也是 CPU密集型的任務(wù)潦匈。