zoukankan      html  css  js  c++  java
  • (原)android-as_video_player中的OpenGLES视频显示

    android-as_video_player中的OpenGLES视频显示

    1,SurfaceView和OpenGLES

    先从java的上层代码入手:

    surfaceView = (SurfaceView) findViewById(R.id.gl_surface_view);
    surfaceView.getLayoutParams().height =screenWidth;
    SurfaceHolder mSurfaceHolder = surfaceView.getHolder();
    mSurfaceHolder.addCallback(previewCallback);
    private Callback previewCallback = new Callback() {
       public void surfaceCreated(SurfaceHolder holder) {
           //这里先创建一个播放器对象,然后调用播放器的初始化函数
           playerController.init(path, surfaceHolder.getSurface(), width, height,new OnInitializedCallback())
       }
     }

    而在播放器对象中,我们是先从surface对象拿到ANativeWindow对象,然后在后文中就会用这个ANativeWindow对象跟opengles相关内容结合。

    //这里会先根据上层的surface对象拿到ndk层的窗口对象ANativeWindow
    window = ANativeWindow_fromSurface(env, surface);
    //往下传递,将这个窗口对象
    videoPlayerController->onSurfaceCreated(window, width, height);

    接着我们跳过中间无关的内容,我们看看是如何利用这个window对象的.

    bool VideoOutput::createEGLContext(ANativeWindow* window) {
       //创建一个EGL对象
       eglCore = new EGLCore();
      //这里是创建一个egl共享上下文,并初始化相关东西,我们等会分析
       bool ret = eglCore->initWithSharedContext();
       //在底层会根据相关参数,创建一个eglsurface
       this->createWindowSurface(window);
       //连接 EGLContext 和 EGLSurface
       eglCore->doneCurrent();    
    }

    接下来的内容,更多的涉及到egl相关的内容了。

    2,什么是 EGL?

    EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现。EGL提供如下机制:

    • 与设备的原生窗口系统通信

    • 查询绘图表面的可用类型和配置

    • 创建绘图表面

    • 在OpenGL ES 和其他图形渲染API之间同步渲染

    • 管理纹理贴图等渲染资源

    为了让OpenGL ES能够绘制在当前设备上,我们需要EGL作为OpenGL ES与设备的桥梁

    2.1,使用EGL绘图的基本步骤
    • Display(EGLDisplay) 是对实际显示设备的抽象。

    • Surface(EGLSurface)是对用来存储图像的内存区域

    • FrameBuffer 的抽象,包括 Color Buffer, Stencil Buffer ,Depth Buffer。

    • Context (EGLContext) 存储 OpenGL ES绘图的一些状态信息。

    使用EGL的绘图的一般步骤:

    1. 获取 EGL Display 对象:eglGetDisplay()

    2. 初始化与 EGLDisplay 之间的连接:eglInitialize()

    3. 获取 EGLConfig 对象:eglChooseConfig()

    4. 创建 EGLContext 实例:eglCreateContext()

    5. 创建 EGLSurface 实例:eglCreateWindowSurface()

    6. 连接 EGLContext 和 EGLSurface:eglMakeCurrent()

    7. 使用 OpenGL ES API 绘制图形:gl_*()

    8. 切换 front buffer 和 back buffer 送显:eglSwapBuffer()

    9. 断开并释放与 EGLSurface 关联的 EGLContext 对象:eglRelease()

    10. 删除 EGLSurface 对象

    11. 删除 EGLContext 对象

    12. 终止与 EGLDisplay 之间的连接

     

    3,接着上面的代码,继续分析我们的egl和opengles的相关代码

    bool EGLCore::initWithSharedContext(){
       //这里初始化一个共享的context,所谓的共享,其实就是底层使用的单例模式,创建了一个EglShareContext
       //然后在这个单例对象中存储了一个EGLContext sharedContext;对象,这里就是返回这个对象,实际上
       EGLContext context = EglShareContext::getSharedContext();
       //也是对上面的context在初始化一次,感觉两次初始化的内容其实都是一样,所以这个地方就不再贴了
       return init(context);
    }

    而在EglShareContext的初始化中,也是初始化egl相关内容:

    void EglShareContext::init() {
        sharedContext = EGL_NO_CONTEXT;
        EGLint numConfigs;
        sharedDisplay = EGL_NO_DISPLAY;
        EGLConfig config;
        const EGLint attribs[] = { EGL_BUFFER_SIZE, 32, EGL_ALPHA_SIZE, 8,
              EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8,
              EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE,
              EGL_WINDOW_BIT, EGL_NONE };
        //获取egl的默认显示对象
        if ((sharedDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY))
              == EGL_NO_DISPLAY) {
        }
        //初始化和display对象之间连接的相关egl实现版本信息
        if (!eglInitialize(sharedDisplay, 0, 0)) {
        }
        //选择config
        if (!eglChooseConfig(sharedDisplay, attribs, &config, 1, &numConfigs)) {
        }
        //创建一个共享contex上下文对象
        EGLint eglContextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
        if (!(sharedContext = eglCreateContext(sharedDisplay, config,
              NULL == sharedContext ? EGL_NO_CONTEXT : sharedContext,
              eglContextAttributes))) {
        }
    }

    接着我们走到VideoOutput::createWindowSurface(ANativeWindow* window)函数,我们看下源码:

    void VideoOutput::createWindowSurface(ANativeWindow* window) {
       this->surfaceWindow = window;
       if(NULL!=eglCore){
          //根据窗口对象window,display,以及display的config等信息来创建一个eglsurface的渲染表面对象
          renderTexSurface = eglCore->createWindowSurface(window);
          if (renderTexSurface != NULL){
             //这里是对当前的display和context所连接surface对象,即渲染表面
             //eglMakeCurrent(display, eglSurface, eglSurface, context);
             eglCore->makeCurrent(renderTexSurface);
             //然后这里就是创建一个opengl es相关内容的对象了,在这个对象内部,实现opengles相关的渲染操作
             //例如shader的加载,编译,连接,以及纹理加载,渲染等等都在这个对象里面操作
             renderer = new VideoGLSurfaceRender();
             if(NULL!=renderer){
                bool isGLViewInitialized = renderer->init(screenWidth, screenHeight);
                if (!isGLViewInitialized) {            
                } else {
                   surfaceExists = true;
                   forceGetFrame = true;
                }
             }
          }
       }
    }

     转载请注明出处:https://www.cnblogs.com/lihaiping/p/opengles.html

  • 相关阅读:
    MinDoc v0.6 发布,轻量级文档在线管理系统
    PostMessage和SendMessage有什么区别?(有EnumChildWindowsProc的例子)
    将QuickReport报表保存为图片(使用TMetaFile和TMetafileCanvas)
    如何将JPEG缩略图放到LISTVIEW中(delphi listview自绘图形)
    栈和队列
    SQL调优日志--内存问题
    Nancy之实现API
    JAVA和.NET互调用
    NET Core环境并创建运行ASP.NET网站
    React Native
  • 原文地址:https://www.cnblogs.com/lihaiping/p/opengles.html
Copyright © 2011-2022 走看看