FFmpeg(14)-使用NDK、C++完成EGL,display, surface, context的配置和初始化


 EGL

用它開發需要做哪些事情。

 

DIsplay 與原生窗口建立鏈接。EGL在Android中可以用java調,也可以用C++調。

       EGLDisplay eglGetDisplay                                // 獲取原生窗口的鏈接

       EGLBoolean eglInitlize                                     // 再進行窗口的初始化。

 

Surface配置和創建Surface。創建一個渲染區域,它是最終我們用來顯示的對象。

EGLBoolean eglChooseConfig                                // 對渲染區域進行參數的配置。比方說顏色的深度、紅色、綠色對應的深度、顏色的存儲格式等

EGLSurface eglCreateWindowSurface                      // 創建surface

經過上面兩步操作后,會創建一個surface,我們將來的畫面就會渲染到這塊surface當中去。

 

Context 創建渲染環境。該渲染環境主要用於描述OpenGL ES的所有項目運行需要的數據結構(如用到的頂點數據怎么繪制)。包括頂點、片斷着色器、頂點數據矩陣。

eglCreateConrtext

eglMakeCurrent

 

GLSL

具體的顯示YUV數據。又稱之為shade,着色器語言。它主要包含下列兩個模塊:頂點着色器片元着色器。

頂點着色器是針對每個頂點執行一次。比方說要畫一個三維的模型,這個時候就需要把每個頂點給計算出來,然后跟着光照的改變而改變(因為雖然三個三點的坐標是固定的,但是視角不同,這三個值就會不一樣,這個時候就需要確定一個頂點着色器,把頂點的值給算出來,繪制視頻則無此問題,只要繪制一個矩形就可以了)。

片元着色器是針對每個顯示的片元(像素點)執行一次,執行的時候會調用相應的代碼,這個時候就可以把每個像素相應的顏色給改變掉(比方說傳遞的是YUV的數據,但是YUV的數據是不能直接用來顯示的,這個時候就可以在片元着色器里面把它的值進行轉換,轉換成RGB的值用於顯示)。

GLSL的基本語法與C相同。

它支持向量和矩陣的操作。

GLSL提供了大量的內置函數來提供豐富的擴展功能。

同時GLSL還通過一些限定符操作來管理輸入輸出的。

 

顯示YUV代碼演示

  1. 准備YUV數據。通過FFmpeg工具生成一個YUV文件

ffmpeg –i 720.mp4 –pix_fmt yuv420p –s 424*240 out.yuv

把生成的YUV數據上傳到模擬器

PS:需要下載FFmpeg.exe工具。

yuv420p,

p是平面格式(平面格式就是針對一幅圖像,,Y存在第一位,再存U,再存V,它們是非交錯的格式,就是Y全部存完了,再存U,再存V)。

如果是交錯格式的話可能就是一個Y,一個U,一個V,這種存放方式。

示例代碼:

需要包含庫文件

target_link_libraries( # Specifies the target library.
                       native-lib
                       GLESv2
                       EGL
                       android

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

C++代碼

extern "C"
JNIEXPORT void JNICALL
Java_com_yuneec_testopengles_Xplay_open(JNIEnv *env, jobject instance, jstring url_,
                                        jobject surface) {
    const char *url = env->GetStringUTFChars(url_, 0);

    // 獲取原始窗口
    ANativeWindow *nwin = ANativeWindow_fromSurface(env, surface);
    // EGL
    // 1. EGL display 的創建和初始化
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (display == EGL_NO_DISPLAY) {
        LOGE("eglGetDisplay() failed");
        return;
    }
    if (EGL_TRUE != eglInitialize(display, 0, 0)) {
        LOGE("eglInitialize() failed");
        return;
    }
    // 2. Surface
    // surface 窗口配置
    // 輸出配置
    EGLConfig config;
    EGLint configNum;
    EGLint configSpec[] = {
            EGL_RED_SIZE, 8,
            EGL_GREEN_SIZE, 8,
            EGL_BLUE_SIZE, 8,
            EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE
    };
    if (EGL_TRUE != eglChooseConfig(display, configSpec, &config, 1, &configNum)) {
        LOGE("eglChooseConfig() failed");
        return;
    }
    // 創建Surface
    EGLSurface winSurface = eglCreateWindowSurface(display, config, nwin, 0);
    if (winSurface == EGL_NO_SURFACE) {
        LOGE("eglCreateWindowSurface() failed");
        return;
    }

    //3. context 創建關聯的上下文
    const EGLint ctxAttr[] = {
            EGL_CONTEXT_CLIENT_VERSION,2,EGL_NONE
    };
    EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, ctxAttr);
    if (context == EGL_NO_CONTEXT) {
        LOGE("eglCreateContext failed");
        return;
    }
    if (EGL_TRUE != eglMakeCurrent(display, winSurface, winSurface, context)) {
        LOGE("eglMakeCurrent failed");
        return;
    }

    LOGI("EGL init success");

    env->ReleaseStringUTFChars(url_, url);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM