1,java層
在界面中創建GL2JNIView(基類為GLSurfaceView)。
創建對象AndroidVideoWindowImpl,將GL2JNIView作為參數傳入構造函數。在該對象中監聽GL2JNIView的surface事件(mVideoRenderingView.getHolder().addCallback)。
當surface變化時(如顯示窗口大小變化、activity被其他程序遮住),此時觸發回調函數:
public
void surfaceChanged(SurfaceHolderholder,
intformat,
int width,
int height)
在該函數中調用LinphoneManager.getLc().setVideoWindow(vw); 將AndroidVideoWindowImpl對象傳到c代碼層
C代碼中對應的函數在mediastreamer2\src\android\android-opengl-display.c中android_display_set_window,
此函數中調用步驟如下:
(1) (*jenv)->CallVoidMethod(jenv,window,ad->set_opengles_display_id,ptr);
其中window為java傳過來的AndroidVideoWindowImpl對象;ad->set_opengles_display_id為java 類AndroidVideoWindowImpl成員函數setOpenGLESDisplay;ptr為結構體變量opengles_display,該結構體存儲yuv數據,在後面每幀顯示時會用到。
(2) 將AndroidVideoWindowImpl賦值給ad->android_video_window
該函數主要完成java和c互換對象指針。這主要是由於opengl刷新每幀視頻必須由java層的onDrawFrame來完成,而linphone的視頻流在c層接收解碼,需要由c函數來觸發刷新。
2,c代碼層
在android-opengl-display.c的每幀處理函數android_display_process中,
調用(*jenv)->CallVoidMethod(jenv,ad->android_video_window,ad->request_render_id);其中ad->android_video_window為setVideoWindow傳過來的AndroidVideoWindowImpl對象;ad->request_render_id為java類AndroidVideoWindowImpl成員函數requestRender
該函數觸發opengl刷新一幀,在java層會調用onDrawFrame。
在onDrawFrame函數中調用c代碼層的render,參數為第(1)中傳到java層的opengles_display結構體。
C代碼層對應代碼在mediastreamer2\src\utils\opengles_display.c中ogl_display_render函數,在此函數中將opengles_display中yuv數據繪制到opengl surface中。