我需要将YUV420P图像转换为RGB颜色空间,并使用Freescale iMX53处理器上的AMD GPU进行显示(OpenGL ES 2.0,EGL)。操作系统为Linux,无X11。为了实现这一目标,我应该能够创建一个包含YUV420P数据的适当图像:这可以是YUV420P / YV12图像类型或3个简单的8位图像,每个分量一个(Y,U,V)。
glTexImage2D被排除在外,因为它很慢,YUV420P帧是实时视频解码的结果,每秒25帧,使用glTexImage2D我们无法保持所需的帧速率。
有一个替代方案:eglCreateImageKHR / glEGLImageTargetTexture2DOES,唯一的问题是它们不能处理任何适用于YUV420 / YV12数据的图像格式。
glTexImage2D被排除在外,因为它很慢,YUV420P帧是实时视频解码的结果,每秒25帧,使用glTexImage2D我们无法保持所需的帧速率。
有一个替代方案:eglCreateImageKHR / glEGLImageTargetTexture2DOES,唯一的问题是它们不能处理任何适用于YUV420 / YV12数据的图像格式。
EGLint attribs[] = {
EGL_WIDTH, 800,
EGL_HEIGHT, 480,
EGL_IMAGE_FORMAT_FSL, EGL_FORMAT_YUV_YV12_FSL,
EGL_NONE
};
EGLint const req_attribs[] = {
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
EGL_ALPHA_SIZE, 0,
EGL_SAMPLES, 0,
EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
...
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, NULL, NULL);
eglBindAPI(EGL_OPENGL_ES_API);
eglChooseConfig(display, req_attribs, config, ARRAY_SIZE(config), &num_configs);
ctx = eglCreateContext(display, curr_config, NULL, NULL);
surface = eglCreateWindowSurface(display, curr_config, fb_handle, NULL);
...
EGLImageKHR yuv_img = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_NEW_IMAGE_FSL, NULL, attribs);
eglQueryImageFSL(display, yuv_img, EGL_CLIENTBUFFER_TYPE_FSL, (EGLint *)&ptr);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, yuv_img);
glEGLImageTargetTexture2DOES(...)失败。如果我将“attribs”中的适当行更改为以下内容:
EGL_IMAGE_FORMAT_FSL,EGL_FORMAT_RGB_565_FSL,
那么该图像可以分配给OpenGL ES纹理,但是它不适合保存8位数据(Y / U / V)或YUV420 / YV12数据。在搜索网络(包括Freescale社区论坛)时,我没有找到任何解决方案。
如何创建一个图像:
- 快速创建;
- 最终可以分配给已经存在的缓冲区(给出物理地址或虚拟地址);
- 可以在片段/顶点着色器程序中使用以执行YUV --> RGB转换;
限制是为了避免由于性能原因而进行不必要的memcpy (...)。