簡介
最近工作中接觸到SurfaceTexture诫钓,因此打算分析一下SurfaceTexture的原理赋咽,提到SurfaceTexture一般會(huì)提到與它相關(guān)的SurfaceView、GLSurfaceView芹扭、TextureView麻顶,這幾個(gè)都可以將圖形生產(chǎn)者的數(shù)據(jù)(比如Camera)送到SurfaceFlinger中顯示,而SurfaceTexture可以看做Surface和Texture的組合舱卡,是將圖形生產(chǎn)者的數(shù)據(jù)送到Texture辅肾,然后是由應(yīng)用程序自己來處理。這里的Texture應(yīng)該是屬于opengl的概念轮锥,由于本人對這塊不熟矫钓,等后續(xù)熟悉了再來分析Texture吧。
調(diào)用流程
一般SurfaceTexture的調(diào)用流程如下所示:
應(yīng)用程序會(huì)先創(chuàng)建一個(gè)SurfaceTexture舍杜,然后將SurfaceTexture傳遞給圖形生產(chǎn)者對象(比如Camera新娜,通過調(diào)用setPreviewTexture傳遞),圖形生產(chǎn)者對象生產(chǎn)一幀數(shù)據(jù)后既绩,會(huì)回調(diào)onFrameAvailable通知應(yīng)用程序有新的圖像數(shù)據(jù)可以使用杯活,應(yīng)用程序就可以調(diào)用updateTexImage將圖像數(shù)據(jù)先送到Texture,之后就可以調(diào)用opengl接口做些具體的業(yè)務(wù)了熬词。
下面說說具體的流程吧。
step1到step13
這幾個(gè)流程就是初始化SurfaceTexture吸重,在native層創(chuàng)建了BufferQueue互拾、GLConsumer、JNISurfaceTextureContext嚎幸,BufferQueue提供圖形生產(chǎn)者消費(fèi)者機(jī)制颜矿,具體內(nèi)容請見Android BufferQueue簡析,GLConsumer就是SurfaceTexture的圖形消費(fèi)者嫉晶,即通過調(diào)用opengl接口將圖形生產(chǎn)者的圖像數(shù)據(jù)送到Texture骑疆,JNISurfaceTextureContext是個(gè)簡單的代理對象,持有java層的SurfaceTexture對象替废,完成幀可用事件回調(diào)箍铭。
主要類的關(guān)系如下所示,綠色的為java層的SurfaceTexture對象椎镣,黃色的都是native層的對象诈火,可見SurfaceTexture功能基本都在native層實(shí)現(xiàn),java層的SurfaceTexture對象的mSurfaceTexture成員指向的是native層的GLConsumer對象状答,mProducer成員指向的是native層的BufferQueueProducer對象冷守,當(dāng)將SurfaceTexture對象傳給圖形生產(chǎn)者對象比如Camera時(shí)刀崖,就可以從該成員獲取到native層的BufferQueueProducer,用于生產(chǎn)者對象輸出拍摇。如下所示:
static void android_hardware_Camera_setPreviewTexture(JNIEnv *env,
jobject thiz, jobject jSurfaceTexture)
{
ALOGV("setPreviewTexture");
sp<Camera> camera = get_native_camera(env, thiz, NULL);
if (camera == 0) return;
sp<IGraphicBufferProducer> producer = NULL;
if (jSurfaceTexture != NULL) {
producer = SurfaceTexture_getProducer(env, jSurfaceTexture);
if (producer == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException",
"SurfaceTexture already released in setPreviewTexture");
return;
}
}
if (camera->setPreviewTarget(producer) != NO_ERROR) {
jniThrowException(env, "java/io/IOException",
"setPreviewTexture failed");
}
}
mFrameAvailableListener成員指向的是native層的JNISurfaceTextureContext對象亮钦,JNISurfaceTextureContext是OnFrameAvailableListener從native到j(luò)ava的跳板。
該類圖與Android BufferQueue簡析圖三的類圖很像充活,那張類圖說的是顯示流程中的主要類之間的關(guān)系蜂莉,可見SurfaceTexture和SurfaceView原理上基本相似,BufferQueue都是其核心堪唐,當(dāng)然也有一些不同的地方巡语,比如SurfaceTexture的BufferQueue是在應(yīng)用程序進(jìn)程這邊創(chuàng)建的,而SurfaceView對應(yīng)的BufferQueue是在SurfaceFlinger進(jìn)程創(chuàng)建的淮菠。
step14到step16
這幾個(gè)流程就是圖形生產(chǎn)者生產(chǎn)一幀數(shù)據(jù)后男公,通過BufferQueueCore層層調(diào)用,最后回調(diào)OnFrameAvailableListener的onFrameAvailable合陵,通知Listener有新的圖像數(shù)據(jù)可以使用枢赔,一般應(yīng)用程序會(huì)實(shí)現(xiàn)該Listener以接收通知。
step17到step35
這幾個(gè)流程就是從BufferQueueCore取出圖形生產(chǎn)者生產(chǎn)的幀數(shù)據(jù)GraphicBuffer拥知,然后調(diào)用opengl接口將GraphicBuffer更新到Texture上踏拜,等熟悉了opengl再來分析。
step36到step36
應(yīng)用程序一般還會(huì)根據(jù)需要調(diào)用getTransformMatrix低剔、getTimestamp獲取矩陣和時(shí)間戳信息速梗,這些信息是在調(diào)用updateTexImage時(shí)更新的。
通過以上分析襟齿,可見要理解SurfaceTexture的關(guān)鍵是要理解BufferQueue和opengl姻锁,BufferQueue已經(jīng)分析過了,opengl等后續(xù)熟悉了再抽空分析吧猜欺。