Android SurfaceTexture簡析

https://www.jianshu.com/p/b19a0f49d4ac

 

Android SurfaceTexture簡析

96 Jimmy2012 關注

 0.3 2017.10.29 23:48* 字數 879 閱讀 5169評論 1喜歡 5

簡介

最近工作中接觸到SurfaceTexture,因此打算分析一下SurfaceTexture的原理,提到SurfaceTexture一般會提到與它相關的SurfaceView、GLSurfaceView、TextureView,這幾個都可以將圖形生產者的數據(比如Camera)送到SurfaceFlinger中顯示,而SurfaceTexture可以看做Surface和Texture的組合,是將圖形生產者的數據送到Texture,然後是由應用程序自己來處理。這裏的Texture應該是屬於opengl的概念,由於本人對這塊不熟,等後續熟悉了再來分析Texture吧。

調用流程

一般SurfaceTexture的調用流程如下所示:

圖一

應用程序會先創建一個SurfaceTexture,然後將SurfaceTexture傳遞給圖形生產者對象(比如Camera,通過調用setPreviewTexture傳遞),圖形生產者對象生產一幀數據後,會回調onFrameAvailable通知應用程序有新的圖像數據可以使用,應用程序就可以調用updateTexImage將圖像數據先送到Texture,之後就可以調用opengl接口做些具體的業務了。

下面說說具體的流程吧。

step1到step13

這幾個流程就是初始化SurfaceTexture,在native層創建了BufferQueue、GLConsumer、JNISurfaceTextureContext,BufferQueue提供圖形生產者消費者機制,具體內容請見Android BufferQueue簡析,GLConsumer就是SurfaceTexture的圖形消費者,即通過調用opengl接口將圖形生產者的圖像數據送到Texture,JNISurfaceTextureContext是個簡單的代理對象,持有java層的SurfaceTexture對象,完成幀可用事件回調。

主要類的關係如下所示,綠色的爲java層的SurfaceTexture對象,黃色的都是native層的對象,可見SurfaceTexture功能基本都在native層實現,java層的SurfaceTexture對象的mSurfaceTexture成員指向的是native層的GLConsumer對象,mProducer成員指向的是native層的BufferQueueProducer對象,當將SurfaceTexture對象傳給圖形生產者對象比如Camera時,就可以從該成員獲取到native層的BufferQueueProducer,用於生產者對象輸出。如下所示:

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到java的跳板。

該類圖與Android BufferQueue簡析圖三的類圖很像,那張類圖說的是顯示流程中的主要類之間的關係,可見SurfaceTexture和SurfaceView原理上基本相似,BufferQueue都是其核心,當然也有一些不同的地方,比如SurfaceTexture的BufferQueue是在應用程序進程這邊創建的,而SurfaceView對應的BufferQueue是在SurfaceFlinger進程創建的。

圖二

step14到step16

這幾個流程就是圖形生產者生產一幀數據後,通過BufferQueueCore層層調用,最後回調OnFrameAvailableListener的onFrameAvailable,通知Listener有新的圖像數據可以使用,一般應用程序會實現該Listener以接收通知。

step17到step35

這幾個流程就是從BufferQueueCore取出圖形生產者生產的幀數據GraphicBuffer,然後調用opengl接口將GraphicBuffer更新到Texture上,等熟悉了opengl再來分析。

step36到step36

應用程序一般還會根據需要調用getTransformMatrix、getTimestamp獲取矩陣和時間戳信息,這些信息是在調用updateTexImage時更新的。

通過以上分析,可見要理解SurfaceTexture的關鍵是要理解BufferQueue和opengl,BufferQueue已經分析過了,opengl等後續熟悉了再抽空分析吧。