[转载]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
这个extension定义了一个新的texture target - TEXTURE_EXTERNAL_OES;相应地在shader中增加了一个新的sampler类型 - samplerExternalOES,是a handle for accessing an external texture。
注意:这个extension已经过时,应该使用GL_OES_EGL_image_external_essl3
 
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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值