• 一 、YUV420P数据格式
  • 二 、GLFW渲染YUV420P
    • 2.1 定义顶点数据
    • 2.2 创建YUV三张纹理
    • 2.3上行YUV420数据
    • 2.4 渲染纹理
    • 2.5 着色器
  • 三、代码地址以及存在的问题
  • 四 、解决存在的问题

一 、YUV420P数据格式

图片来源于谷歌
结合上图可以看出YUV420P的特点如下:
①无论在横向还是纵向上都是两个亮度(Y)共享一组色度(UV),所以UV的宽度和高度都是Y的1/2
②在内存中有三片数据,也就是三个数据指针分别指向Y、U、V

  ffmpeg中avframe保存yuv420p的数据时是直接申请一整个的 image_size, 亮度数据y的地址是起始地址,u 在 y 的基础上偏移, v 在 u 的基础上偏移//以HD的yuv420p 8 bit数据为例uint8_t* yuv420_data = new [1920*1080*1.5]();uint8_t* data_y =  yuv420_data;uint8_t* data_u =  yuv420_data + 1920*1080;uint8_t* data_v =  data_u + 1920*1080/4;delete[] yuv420_data;

二 、GLFW渲染YUV420P

2.1 定义顶点数据

float vertex_coord_data[] = {-1.f, -1.f, 0.f,   0.f, 1.f,-1.f,  1.f, 0.f,   0.f, 0.f,1.f,  1.f, 0.f,   1.f, 0.f,1.f, -1.f, 0.f,   1.f, 1.f,};uint32_t vertx_index_data[] = {0, 1, 2,2, 3, 0};uint32_t m_vertex_buffer, m_index_buffer;glGenBuffers(1, &m_vertex_buffer);glGenBuffers(1, &m_index_buffer);glGenVertexArrays(1, &m_vertex_array);glBindVertexArray(m_vertex_array);glBindBuffer(GL_ARRAY_BUFFER, m_vertex_buffer);glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_coord_data), vertex_coord_data, GL_STATIC_DRAW);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_buffer);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(vertx_index_data), vertx_index_data, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3*sizeof(float)));glEnableVertexAttribArray(1);

2.2 创建YUV三张纹理

   // 纹理 yglGenTextures(1, &m_tex_y);glBindTexture(GL_TEXTURE_2D, m_tex_y);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_tex_width, m_wnd_height, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);glGenerateMipmap(GL_TEXTURE_2D);// 纹理 uglGenTextures(1, &m_tex_u);glBindTexture(GL_TEXTURE_2D, m_tex_u);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_tex_width/2, m_wnd_height/2, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);glGenerateMipmap(GL_TEXTURE_2D);// 纹理 vglGenTextures(1, &m_tex_v);glBindTexture(GL_TEXTURE_2D, m_tex_v);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_tex_width/2, m_wnd_height/2, 0, GL_RED, GL_UNSIGNED_BYTE, nullptr);glGenerateMipmap(GL_TEXTURE_2D);

2.3上行YUV420数据

 glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_tex_y);glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_width, m_tex_height, GL_RED, GL_UNSIGNED_BYTE, y);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, m_tex_u);glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_width/2, m_tex_height/2, GL_RED, GL_UNSIGNED_BYTE, u);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, m_tex_v);glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_width/2, m_tex_height/2, GL_RED, GL_UNSIGNED_BYTE, v);

2.4 渲染纹理

 glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_tex_y);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, m_tex_u);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, m_tex_v);glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

2.5 着色器

/顶点着色器///
#version 330 core
layout (location = 0) in vec3 vertex_pos;
layout (location = 1) in vec2 tex_pos;out vec2 tex_uv;void main()
{gl_Position = vec4(vertex_pos, 1.f);tex_uv = vec2(tex_pos);
}/像素着色器///
#version 330 coreout vec4 frage_color;in vec2 tex_uv;
uniform sampler2D tex_y;
uniform sampler2D tex_u;
uniform sampler2D tex_v;void main()
{vec3 yuv = vec3(0.f);//按照BT709的协议来转换YUV至RGByuv.x = texture2D(tex_y, tex_uv).r - 16.f/235.f;yuv.y = texture2D(tex_u, tex_uv).r - 128.f/240.f;yuv.z = texture2D(tex_v, tex_uv).r - 128.f/240.f;yuv = clamp(yuv, 0.f, 1.f);mat3 yuv_to_rgb = mat3(1.164f,  0.f,     1.793f,1.164f, -0.213f, -0.533f,1.164f,  2.112f,  0.f);vec3 rgb = yuv_to_rgb *yuv;frage_color = vec4(rgb.r, rgb.g, rgb.b, 1.f);
}

三、代码地址以及存在的问题

demo中使用封装好的 ffmpeg 来获取YUV420P数据,相关代码地址:https://github.com/pengguoqing/samples_code.git
使用demo中的代码渲染后的效果画面会变紫,我尝试了用其他YUV_RGB的转换矩阵,也是一样的会变紫,各位老师看过后能不能纠正一下哪里不正确

本demo的渲染效果如下:

正确渲染效果如下:

四 、解决存在的问题

  经过这两天的思考和排查,以及请教行业前辈终于知道原因了,具体如下:
①y、u、v 三张纹理被声明成了 uniform 类型, 所以每次更新纹理数后都需要更新一下

   glActiveTexture(GL_TEXTURE0);glBindTexture(GL_TEXTURE_2D, m_tex_y);glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_width, m_tex_height, GL_RED, GL_UNSIGNED_BYTE, y);m_shader_parse.setInt("tex_y", 0);glActiveTexture(GL_TEXTURE1);glBindTexture(GL_TEXTURE_2D, m_tex_u);glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_width/2, m_tex_height/2, GL_RED, GL_UNSIGNED_BYTE, u);m_shader_parse.setInt("tex_u", 1);glActiveTexture(GL_TEXTURE2);glBindTexture(GL_TEXTURE_2D, m_tex_v);glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_tex_width/2, m_tex_height/2, GL_RED, GL_UNSIGNED_BYTE, v);m_shader_parse.setInt("tex_v", 2);//或一次性通知更新//m_shader_parse.setInt("tex_y", 0);//m_shader_parse.setInt("tex_u", 1);//m_shader_parse.setInt("tex_v", 2);

② shader里面需要对左乘矩阵进行转置
  因为shader里面的向量是列向量,所以 yuv_rgb 的矩阵需要左乘 采样的 yuv纹理数据

    /*mat3 yuv_to_rgb = mat3(1.164f,  0.f,     1.793f,1.164f, -0.213f, -0.533f,1.164f,  2.112f,  0.f);*///709_YUV_to_RGBmat3 yuv_to_rgb = mat3(1.164f, 1.164f,  1.164f,0.f,    -0.213f, 2.112f,1.793f, -0.533f, 0.f);

 修改后的渲染效果正确了

OpenGL渲染YUV420P相关推荐

  1. Android native 层使用opengl渲染YUV420p和NV12

    <Ndk中使用Mediacode解码> <android mediacodec 编码demo(java)> <NDK中使用mediacodec编码h264> < ...

  2. android 渲染yuv数据,Android opengl渲染yuv420例子

    [实例简介] Android下使用OpenGL渲染yuv420p图像并显示.例子中提供了两种类型,一种使用GLSurfaceView在onDrawframe中调用native方法绘制,另外一种使用EG ...

  3. 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)

    ===================================================== 最简单的视音频播放示例系列文章列表: 最简单的视音频播放示例1:总述 最简单的视音频播放示例 ...

  4. Android平台上基于OpenGl渲染yuv视频

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 更多音视频开发文章,请看:音视频开发专栏 介绍一个自己刚出炉的音视频播放录制开源项目 前言 这是我音视频专栏的第一篇实例解析,也算是 ...

  5. windows下使用OpenGL实现yuv420p转rgb播放视频(三重纹理实现)

    一.简述 在博主之前的博文<windows下使用FFmpeg生成YUV视频文件并播放(通过命令的方式)>中,讲述了使用ffplay播放YUV视频文件的方法.本文讲述使用OpenGL播放YU ...

  6. 视频实时OpenGL渲染并保存渲染结果合成MP4

    这是一个能实时播放多个视频.图片在一个GL容器里的控件,通过这个控件,可以在一个view中绘制固定坐标.自由随机滚动的视频和图片,然后从该view中截取数据帧,实时保存成YUV格式的文件,最后合成MP ...

  7. 教你实现GPUImage【OpenGL渲染原理】

    原文出处: 袁峥Seemygo(@袁峥Seemygo)    一.前言 本篇主要讲解GPUImage底层是如何渲染的,GPUImage底层使用的是OPENGL,操控GPU来实现屏幕展示 由于网上Ope ...

  8. 【OpenGL】八、初始化 OpenGL 渲染环境 ( 导入 OpenGL 头文件 | 链接 OpenGL 库 | 将窗口设置为 OpenGL 窗口 | 设置像素格式描述符 | 渲染绘制 ) ★

    文章目录 一.导入 OpenGL 的两个头文件 二.链接 OpenGL 库 三.将 Windows 桌面窗口改成 OpenGL 窗口 四.获取窗口设备 五.设置像素格式描述符 六.设置像素格式 七.创 ...

  9. OpenGL渲染纹理和平面反射

    OpenGL渲染纹理和平面反射 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <stdio.h> #include "GL ...

  10. OpenGL渲染水water

    OpenGL渲染水water 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <stdio.h> #include <stdli ...

最新文章

  1. 基于OHCI的USB主机 —— OHCI(设计思路)
  2. 进程间的通信方式:简介
  3. php和派森,安装多版本Python,一个神器足矣
  4. HTML5 Web app开发工具Kendo UI Web中Grid网格控件的使用
  5. BJUI验证Input非空和是否为数字
  6. IIS-ShortName-Scanner使用
  7. 清华2018顶级数据团队建设全景报告发布:Python最受欢迎,C语言含金量最高
  8. PDF转换技巧之如何把文件转换为WPS?
  9. 自学JAVA-11:IO流
  10. 非递归中序遍历---算法导论12.1-3
  11. c语言 鼠标宏,鼠标宏设置软件下载 Mini Mouse Macro(鼠标宏设置工具) v7.2.0.0 免费安装版 下载-脚本之家...
  12. ccf csp 201912-1报数(python)
  13. 推荐系统-推荐冷启动问题
  14. 神策数据盛永根:微信生态——全数据采集和打通
  15. Python中json.loads()无法解析单引号字符串问题的两种解决方法
  16. Spring学习笔记 之 Spring<全>
  17. 全国CSM敏捷教练认证将于2023年3月25-26开班,报名从速!
  18. 工作半年后的一点感悟
  19. Python+Django+Mysql实现在线电影推荐系统 基于用户、项目的协同过滤推荐在线电影系统 代码实现 源代码下载
  20. daocloud mysql_使用 DaoCloud 部署 NODE

热门文章

  1. 重磅 | 完备的人工智能AI 学习——基础知识学习路线,所有资料免关注免套路直接网盘下载
  2. UEFI除标准应用程序工程模块外的其他工程模块--随记
  3. WinXP下搭建适合Nokia开发的J2ME环境
  4. 从零开始的数模学习(7):插值方法(预测类模型)
  5. 在OpenLava中探索Fairshare调度
  6. [乱七八糟]《进化论——人类科学史上最大的谎言》
  7. 记录Java学习书籍
  8. 终于来了!Win11 预览版镜像提前出世(附 ISO 下载)
  9. 朱军清华大学计算机系是哪里人,朱军(清华大学计算机系教授)_百度百科
  10. sharp s2 android 9,夏普s2第三方ROM AOSP(Android P)v105