目录
SDL最基本的功能,说的简单点,它为不同平台的窗口创建,surface创建和渲染(render)提供了接口。其中,surface是用EGL创建的,render由OpenGLES来完成。
OpenGL ES
什么是openGL ES
OpenGL ES(OpenGL for Embedded Systems)是 OpenGL 三维图形API的子集,针对手机、PDA和游戏主机等嵌入式设备而设计,各显卡制造商和系统制造商来实现这组 API
EGL
什么是EGL
EGL 是 OpenGL ES 渲染 API 和本地窗口系统(native platform window system)之间的一个中间接口层,它主要由系统制造商实现。EGL提供如下机制:
- 与设备的原生窗口系统通信
- 查询绘图表面的可用类型和配置
- 创建绘图表面
- 在OpenGL ES 和其他图形渲染API之间同步渲染
- 管理纹理贴图等渲染资源
- 为了让OpenGL ES能够绘制在当前设备上,我们需要EGL作为OpenGL ES与设备的桥梁。
OpenGL ES和EGL的关系

使用EGL绘图的一般步骤
- 获取 EGL Display 对象:eglGetDisplay()
- 初始化与 EGLDisplay 之间的连接:eglInitialize()
- 获取 EGLConfig 对象:eglChooseConfig()
- 创建 EGLContext 实例:eglCreateContext()
- 创建 EGLSurface 实例:eglCreateWindowSurface()
- 连接 EGLContext 和 EGLSurface:eglMakeCurrent()
- 使用 OpenGL ES API 绘制图形:gl_*()
- 切换 front buffer 和 back buffer 送显:eglSwapBuffer()
- 断开并释放与 EGLSurface 关联的 EGLContext 对象:eglRelease()
- 删除 EGLSurface 对象
- 删除 EGLContext 对象
- 终止与 EGLDisplay 之间的连接
Ijkplayer通过EGL的绘图过程基本上就是使用上面的流程。
源码分析
现在把音视频输出的源码从头梳理一遍。以安卓平台为例。
图像渲染相关结构体
struct SDL_Vout { SDL_mutex *mutex; SDL_Class *opaque_class; SDL_Vout_Opaque *opaque; SDL_VoutOverlay *(*create_overlay)(int width, int height, int frame_format, SDL_Vout *vout); void (*free_l)(SDL_Vout *vout); int (*display_overlay)(SDL_Vout *vout, SDL_VoutOverlay *overlay); Uint32 overlay_format; }; typedef struct SDL_Vout_Opaque { ANativeWindow *native_window;//视频图像窗口 SDL_AMediaCodec *acodec; int null_native_window_warned; // reduce log for null window int next_buffer_id; ISDL_Array overlay_manager; ISDL_Array overlay_pool; IJK_EGL *egl;// } SDL_Vout_Opaque; typedef struct IJK_EGL { SDL_Class *opaque_class; IJK_EGL_Opaque *opaque; EGLNativeWindowType window; EGLDisplay display; EGLSurface surface; EGLContext context; EGLint width; EGLint height; } IJK_EGL;初始化播放器的渲染对象
通过调用SDL_VoutAndroid_CreateForAndroidSurface来生成渲染对象:
IjkMediaPlayer *ijkmp_android_create(int(*msg_loop)(void*)) { ... mp->ffplayer->vout = SDL_VoutAndroid_CreateForAndroidSurface(); if (!mp->ffplayer->vout) goto fail; ... }最后通过调用 SDL_VoutAndroid_CreateForAndroidSurface来生成播放器渲染对象,看一下播放器渲染对象的几个成员:
- func_create_overlay用于创建视频帧渲染对象。
- func_display_overlay为图像显示接口函数。
- func_free_l用于释放资源。
视频解码后将相关数据存入每个视频帧的渲染对象中,然后通过调用func_display_overlay函数将图像渲染显示。
SDL_Vout *SDL_VoutAndroid_CreateForANativeWindow() { SDL_Vout *vout = SDL_Vout_CreateInternal(sizeof(SDL_Vout_Opaque)); if (!vout) return NULL; SDL_Vout_Opaque *opaque = vout->opaque; opaque->native_window = NULL; if (ISDL_Array__init(&opaque->overlay_manager, 32)) goto fail; if (ISDL_Array__init(&opaque->overlay_pool, 32)) goto fail; opaque->egl = IJK_EGL_create(); if (!opaque->egl) goto fail; vout->opaque_class = &g_nativewindow_class; vout->create_overlay = func_create_overlay; vout->free_l = func_free_l; vout->display_overlay = func_display_overlay; return vout; fail: func_free_l(vout); return NULL; }视频帧渲染对象的创建
创建渲染对象函数:
关键字:
