Android SurfaceTexture簡(jiǎn)析

簡(jiǎn)介

最近工作中接觸到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的概念,由于本人對(duì)這塊不熟,等后續(xù)熟悉了再來分析Texture吧。

調(diào)用流程

一般SurfaceTexture的調(diào)用流程如下所示:

圖一

應(yīng)用程序會(huì)先創(chuàng)建一個(gè)SurfaceTexture,然后將SurfaceTexture傳遞給圖形生產(chǎn)者對(duì)象(比如Camera,通過調(diào)用setPreviewTexture傳遞),圖形生產(chǎn)者對(duì)象生產(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)容請(qǐng)見Android BufferQueue簡(jiǎn)析,GLConsumer就是SurfaceTexture的圖形消費(fèi)者,即通過調(diào)用opengl接口將圖形生產(chǎn)者的圖像數(shù)據(jù)送到Texture,JNISurfaceTextureContext是個(gè)簡(jiǎn)單的代理對(duì)象,持有java層的SurfaceTexture對(duì)象,完成幀可用事件回調(diào)。

主要類的關(guān)系如下所示,綠色的為java層的SurfaceTexture對(duì)象,黃色的都是native層的對(duì)象,可見SurfaceTexture功能基本都在native層實(shí)現(xiàn),java層的SurfaceTexture對(duì)象的mSurfaceTexture成員指向的是native層的GLConsumer對(duì)象,mProducer成員指向的是native層的BufferQueueProducer對(duì)象,當(dāng)將SurfaceTexture對(duì)象傳給圖形生產(chǎn)者對(duì)象比如Camera時(shí),就可以從該成員獲取到native層的BufferQueueProducer,用于生產(chǎn)者對(duì)象輸出。如下所示:

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對(duì)象,JNISurfaceTextureContext是OnFrameAvailableListener從native到j(luò)ava的跳板。

該類圖與Android BufferQueue簡(jiǎn)析圖三的類圖很像,那張類圖說的是顯示流程中的主要類之間的關(guān)系,可見SurfaceTexture和SurfaceView原理上基本相似,BufferQueue都是其核心,當(dāng)然也有一些不同的地方,比如SurfaceTexture的BufferQueue是在應(yīng)用程序進(jìn)程這邊創(chuàng)建的,而SurfaceView對(duì)應(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ù)熟悉了再抽空分析吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容