最近在做相機(jī)開發(fā)的過程中,關(guān)于onPreviewFrame的問題必須單獨(dú)拿出來說一下的。
公司的相機(jī)項(xiàng)目,是通過兩個(gè)HandlerThread 來對Camera進(jìn)行控制以及對貼紙、美顏等進(jìn)行渲染,是通過SurfaceView來實(shí)現(xiàn)的。其中,一個(gè)HandlerThread 用來控制Camera打開、關(guān)閉等操作,另外一個(gè)HandlerThread用來控制渲染貼紙、濾鏡等操作。按照Google官方的說法,Camera 的控制最好開啟一個(gè)線程,而不是在UI線程操作,照理說,這樣的方案是沒什么問題的。但實(shí)際上,部分手機(jī)的幀率非常不自然,onPreviewFrame回調(diào)的幀率過低。
但為啥onPreviewFrame的幀率那么低?帶著這個(gè)問題,我對相機(jī)逐步進(jìn)行了拆解,一開始我以為是渲染上出現(xiàn)了問題,但事實(shí)證明并不是。我把所有的渲染部分操作都剔除,只保留渲染Camera相機(jī)流到SurfaceTexture,情況依舊,onPreviewFrame的回調(diào)時(shí)間一直在60多毫秒。只渲染了Camera相機(jī)流到SurfaceTexture,理論上是有20多幀的。這樣的情況很明顯不正常,我也排除了所有可能造成onPreviewFrame阻塞的情況。
而且,我自己的CainCamera項(xiàng)目中,onPreviewFrame的幀率是正常的,每一幀的回調(diào)時(shí)間在30多毫秒,有20多幀。通過對比,我發(fā)現(xiàn)自己的項(xiàng)目跟公司的項(xiàng)目方案是有差異的。我寫的CainCamera項(xiàng)目,是通過單一線程模型控制相機(jī)和渲染的,一個(gè)HandlerThread同時(shí)控制Camera操作和Render渲染。也就是說,這是因?yàn)殡pHandlerThread線程導(dǎo)致的問題?我自己又寫了一個(gè)Demo驗(yàn)證,發(fā)現(xiàn)果然跟我猜想的結(jié)論一致,單一線程模型,所有的手機(jī)都是正常的,但是雙HandlerThread模型下,部分手機(jī)的onPreviewFrame回調(diào)的幀率表現(xiàn)是一致的,幾乎正常的幀率慢了一倍。
我對手機(jī)進(jìn)行了分類,發(fā)現(xiàn)所有onPreviewFrame 回調(diào)幀率不正常的情況都是MTK的CPU。測試的設(shè)備結(jié)果如下:
高通:
VIVO X9i,高通625
紅米Note 4X,高通625
Nexus 5X,高通808
onPreviewFrame回調(diào)時(shí)間: 單一 HandlerThread, 30~40ms; 雙HandlerThread,30~40ms
preview size: 1280 x 720
聯(lián)發(fā)科:
紅米Note2, 聯(lián)發(fā)科X10
魅藍(lán)Note 2,聯(lián)發(fā)科 MTK6573
樂視 X620,聯(lián)發(fā)科X20
onPreviewFrame回調(diào)時(shí)間:單一HandlerThread, 30 ~ 40ms;雙HandlerThread,60~70ms
preview size: 1280 x 720
操作:
Camera數(shù)據(jù)流渲染到SurfaceTexture顯示到SurfaceView上,設(shè)置setPreviewCallbackWithBuffer,查看onPreviewFrame的幀率
發(fā)現(xiàn)了沒有,所有使用了MTK CPU的手機(jī),在單一HandlerThread線程模型上的表現(xiàn)跟高通CPU一致,但雙HandlerThread線程模型上,則會(huì)導(dǎo)致onPreviewFrame預(yù)覽回調(diào)的幀率降了差不多一倍左右。我只能說MTK的驅(qū)動(dòng)或者CPU的架構(gòu)有問題。