OpenGL ES中YUV420到RGB转换的纹理 [英] texture for YUV420 to RGB conversion in OpenGL ES

查看:490
本文介绍了OpenGL ES中YUV420到RGB转换的纹理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须在Freescale iMX53处理器(OpenGL ES 2.0,EGL)上使用AMD GPU将YUV420P图像转换并显示为RGB色彩空间. Linux操作系统,没有X11.为此,我应该能够创建一个包含YUV420P数据的适当图像:这可以是YUV420P/YV12图像类型,也可以是3个简单的8位图像,每个分量(Y,U,V)一个.

I have to convert and display YUV420P images to RGB colorspace using the AMD GPU on a Freescale iMX53 processor (OpenGL ES 2.0, EGL). Linux OS, no X11. To achieve this I should be able to create an appropriate image holding the YUV420P data: this could be either a YUV420P/YV12 image type or 3 simple 8-bit images, one for each component (Y, U, V).

glTexImage2D被排除在外,因为它很慢,YUV420P帧是@ 25FPS实时视频解码的结果,而使用glTexImage2D我们无法保持所需的帧率.

glTexImage2D is excluded, because it's slow, the YUV420P frames are the results of a real time video decoding @25FPS and with glTexImage2D we can't keep the desired framerate.

还有一种选择:eglCreateImageKHR/glEGLImageTargetTexture2DOES.唯一的问题是它们不能处理任何适合YUV420/YV12数据的图像格式.

There's an alternative: eglCreateImageKHR/glEGLImageTargetTexture2DOES. The only problem is that these can't handle any image format that would be suitable for YUV420/YV12 data.

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"中的相应行更改为此:

glEGLImageTargetTexture2DOES(...) fails. If I change the appropriate line in 'attribs' to this:

EGL_IMAGE_FORMAT_FSL,EGL_FORMAT_RGB_565_FSL

EGL_IMAGE_FORMAT_FSL, EGL_FORMAT_RGB_565_FSL,

然后可以将图像分配给OpenGL ES纹理,但是不适合保存8位数据(Y/U/V)或YUV420/YV12数据.在网上搜索(包括飞思卡尔社区论坛),我尚未找到任何解决方案.

then the image can be assigned to an OpenGL ES texture, but it's not appropriate to hold either 8-bit data (Y/U/V) or a YUV420/YV12 data. Searching the net (including Freescale community forum) I've haven't found any solution to this.

如何创建图像:

  • 创建速度快;
  • 最终可以分配给一个已经存在的缓冲区(给出物理地址或虚拟地址);
  • 可在片段/顶点着色器程序中使用以执行YUV-> RGB转换;

约束是为了避免由于性能原因而不必要的memcpy(...).

Constraint is to avoid unneccessary memcpy(...)s due to performance reasons.

推荐答案

我已经在i.MX53上针对几种YUV格式实现了此功能,并且效果非常好.我对此发表了一篇文章,尽管它被概括为涵盖更多的Android平台:

I have implemented this on the i.MX53 for several YUV formats and it works really well. I have a published article about it, although it was generalized to cover more Android platforms:

http://软件.intel.com/zh-CN/articles/using-opengl-es-accelerate-apps-with-legacy-2d-guis

我怀疑您的问题是您没有绑定到正确的纹理目标.应该是这样的:

I suspect your problem is that you are not binding to the correct texture target. It should be like this:

glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, hEglImage[iTextureIndex]);

glBindTexture(GL_TEXTURE_EXTERNAL_OES, hTexture[iIndex]);   

eglImageAttributes应该是其中之一:

And the eglImageAttributes should be one of these:

EGLint eglImageAttributes[] = {EGL_WIDTH, iTextureWidth, EGL_HEIGHT, iTextureHeight, EGL_IMAGE_FORMAT_FSL, EGL_FORMAT_YUV_YV12_FSL, EGL_NONE};
EGLint eglImageAttributes[] = {EGL_WIDTH, iTextureWidth, EGL_HEIGHT, iTextureHeight, EGL_IMAGE_FORMAT_FSL, EGL_FORMAT_YUV_NV21_FSL, EGL_NONE};
EGLint eglImageAttributes[] = {EGL_WIDTH, iTextureWidth, EGL_HEIGHT, iTextureHeight, EGL_IMAGE_FORMAT_FSL, EGL_FORMAT_YUV_UYVY_FSL, EGL_NONE};

hEglImage[iTextureIndex] = eglCreateImageKHR(eglDisplay, EGL_NO_CONTEXT, EGL_NEW_IMAGE_FSL, NULL, eglImageAttributes);

struct EGLImageInfoFSL EglImageInfo;
eglQueryImageFSL(eglDisplay, hEglImage[iTextureIndex], EGL_CLIENTBUFFER_TYPE_FSL, (EGLint *)&EglImageInfo);

尽管Freescale i.MX53平台的此功能使视频的YUV到RGB颜色空间转换非常快,但确实有两个限制:

Although this feature of the Freescale i.MX53 platform makes YUV to RGB color space conversion for video extremely fast, it does have a couple of limitations:

  1. 它仅支持这3种YUV格式.
  2. eglCreateImageKHR()必须分配缓冲区.没有办法使它使用现有的缓冲区.飞思卡尔确认NULL指针不能是其他任何东西,从技术上讲违反了Khronos规范.

尽管架构确实不同,但飞思卡尔已在i.MX6平台上解决了这些问题.希望这会有所帮助.

Freescale has resolved these problems on the i.MX6 platform, although the architecture is really different. Hope this helps.

这篇关于OpenGL ES中YUV420到RGB转换的纹理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆