[转载]YUV格式纹理贴图的例子

frameworks/native/opengl/tests/gl2_yuvtex/gl2_yuvtex.cpp 是Android提供的yuv格式纹理贴图的例子。
 
前面先申请存放纹理数据的buffer
yuvTexBuffer = new GraphicBuffer(yuvTexWidth, yuvTexHeight, yuvTexFormat, yuvTexUsage);
其中 yuvTexFormat = HAL_PIXEL_FORMAT_YV12
 
class GraphicBuffer在 frameworks/native/include/ui/GraphicBuffer.h 中定义,其初始化函数通过initSize调用allocator.alloc申请空间。allocator是GraphicBufferAllocator的引用,这个class包含了alloc_device_t变量,是grallocHAL模块中alloc设备使用的结构体,完成对图形缓冲区的管理,实现从硬件内存到应用地址的映射。
 
后续会通过vendor driver提供的eglCreateImageKHR调用dpy->winsys->get_native_buffer,到winsysp_native_buffer_validate,get_buffer_egl_format,再到hal_format_to_egl_format,完成从HAL format到egl format的映射,例如 HAL_PIXEL_FORMAT_YV12 <-> EGL_COLOR_BUFFER_FORMAT_YV12_BT601_NARROW
配置在 arm/xxx/android/config/mali_config_interface_reference.cpp
 
在eglCreateImageKHR通过get_native_buffer到egl_color_buffer_wrap_external_planar生成EGLImageKHR后,调用glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image),从EGLImageKHR产生纹理。
 
这个过程利用了OpenGL的extension - GL_OES_EGL_image_external
https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external.txt
这个extension定义了一个新的texture target - TEXTURE_EXTERNAL_OES;相应地在shader中增加了一个新的sampler类型 - samplerExternalOES,是a handle for accessing an external texture。
注意:这个extension已经过时,应该使用GL_OES_EGL_image_external_essl3
https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external_essl3.txt
 
Vulkan则用VkSamplerYcbcrModelConversion定义了从source color model到shader color model的转换。
typedef enum VkSamplerYcbcrModelConversion {
 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY=0,    // input values unmodified
  VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY=1,  // no conversion but range expanded
  VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709=2,       // YCbCr to RGB as defined in BT.709
  VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601=3,      // YCbCr to RGB as defined in BT.601
  VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020=4,     // YCbCr to RGB as defined in BT.2020
} VkSamplerYcbcrModelConversion;
 
 
原程序的YUV值共有2^3=8种组合,所以输出色块共有8种颜色。为了调试方便可以改动赋值以输出纯色,以红色(255, 0, 0)为例,
Y =  0.257 * R + 0.504 * G + 0.098 * B + 16  =  0.257 * 255 + 16  = 81
U = -0.148 * R - 0.291 * G + 0.439 * B + 128 = -0.148 * 255 + 128 = 90
V =  0.439 * R - 0.368 * G - 0.071 * B + 128 =  0.439 * 255 + 128 = 240
 
在修改yuvTexWidth = yuvTexHeight = 128的情况下,
yuvTexStrideY = 128
yuvTexOffsetV = 16384  yuvTexStrideV = 64
yuvTexOffsetU = 20480  yuvTexStrideU = 64
 
为了检查输出,可以在renderFrame和eglSwapBuffers之间插入glReadPixels如下:
GLubyte *pixels = (GLubyte *) calloc(4, sizeof(GLubyte));
glReadPixels(w/2, h/2, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
printf("RGBA values: %d %d %d %d\n", pixels[0], pixels[1], pixels[2], pixels[3]);
free(pixels);
 
另外ISP信号通常使用YUV420SP也就是NV21格式。
HAL_PIXEL_FORMAT_YCrCb_420_SP <-> EGL_COLOR_BUFFER_FORMAT_NV21_BT601_NARROW

 

 

 

 

 

 

http://blog.sina.com.cn/s/blog_5423c45a0102xk7h.html

你可能感兴趣的:([转载]YUV格式纹理贴图的例子)