https://www.jianshu.com/p/b19a0f49d4ac
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接口做些具體的業務了。
下面說說具體的流程吧。
這幾個流程就是初始化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進程創建的。
圖二
這幾個流程就是圖形生產者生產一幀數據後,通過BufferQueueCore層層調用,最後回調OnFrameAvailableListener的onFrameAvailable,通知Listener有新的圖像數據可以使用,一般應用程序會實現該Listener以接收通知。
這幾個流程就是從BufferQueueCore取出圖形生產者生產的幀數據GraphicBuffer,然後調用opengl接口將GraphicBuffer更新到Texture上,等熟悉了opengl再來分析。
應用程序一般還會根據需要調用getTransformMatrix、getTimestamp獲取矩陣和時間戳信息,這些信息是在調用updateTexImage時更新的。
通過以上分析,可見要理解SurfaceTexture的關鍵是要理解BufferQueue和opengl,BufferQueue已經分析過了,opengl等後續熟悉了再抽空分析吧。