【开源项目】QT OPENGL 与 shader 绘制展示视频代码实例 OPenGL直接显示YUV数据

本文使用QT中的QOpenGLFunctions(此类封装了OPenGL的方法,相当于QT版OPenGL)

其次重载 void paintGL();   void initializeGL();  void resizeGL(int width, int height);是基本操作


 * 三种GLSL变量说明
 * varying 顶点与片元共享
 * attribute 顶点使用,由bindAttributeLocation传入
 * uniform 程序传入,uniformLocation获取地址

XvideoWidget.h

#pragma once#include <QOpenGLWidget>
#include<QOpenGLFunctions>
#include<QGLShaderProgram>class XvideoWidget : public QOpenGLWidget,protected QOpenGLFunctions
{Q_OBJECTpublic:XvideoWidget(QWidget *parent);~XvideoWidget();protected://重载//刷新显示void paintGL();//初始化GLvoid initializeGL();//窗口尺寸变化void resizeGL(int width, int height);private://shader程序QGLShaderProgram program;//shader中yuv变量地址GLuint unis[3] = { 0 };//openg的 texture地址GLuint texs[3] = { 0 };//材质内存空间unsigned char *datas[3] = { 0 };int width = 352;int height = 288;};

XvideoWidget.cpp

#include "XvideoWidget.h"
#include <QDebug>
#include <QTimer>
//自动加双引号
#define GET_STR(x) #x
#define A_VER 3
#define T_VER 4FILE *fp = NULL;//顶点shader
const char *vString = GET_STR(
attribute vec4 vertexIn;   //顶点坐标
attribute vec2 textureIn;  //材质坐标
varying vec2 textureOut;   //顶点shader片元shader共享
void main(void)
{gl_Position = vertexIn;textureOut = textureIn;
}
);//片元shader
const char *tString = GET_STR(
varying vec2 textureOut;
uniform sampler2D tex_y;
uniform sampler2D tex_u;
uniform sampler2D tex_v;
void main(void)
{vec3 rgb;vec3 yuv;yuv.x = texture2D(tex_y, textureOut).r;yuv.y = texture2D(tex_u, textureOut).r - 0.5;yuv.z = texture2D(tex_v, textureOut).r - 0.5;//YUV转RGB固定公式,利用矩阵转换rgb = mat3(1.0, 1.0, 1.0,0.0, -0.39465, 2.03211,1.13983, -0.58060, 0.0) * yuv;gl_FragColor = vec4(rgb, 1.0);
});//准备yuv数据
// ffmpeg -i v1080.mp4 -t 10 -s 240x128 -pix_fmt yuv420p  out240x128.yuv
XvideoWidget::XvideoWidget(QWidget *parent): QOpenGLWidget(parent)
{
}XvideoWidget::~XvideoWidget()
{
}//初始化opengl
void XvideoWidget::initializeGL()
{qDebug() << "initializeGL";//初始化opengl (QOpenGLFunctions继承)函数 initializeOpenGLFunctions();//program加载shader(顶点和片元)脚本//片元(像素)qDebug() << program.addShaderFromSourceCode(QGLShader::Fragment, tString);//顶点shaderqDebug() << program.addShaderFromSourceCode(QGLShader::Vertex, vString);//设置顶点坐标的变量program.bindAttributeLocation("vertexIn", A_VER);//设置材质坐标program.bindAttributeLocation("textureIn", T_VER);//编译shaderqDebug() << "program.link() = " << program.link();qDebug() << "program.bind() = " << program.bind();//传递顶点和材质坐标//顶点static const GLfloat ver[] = {-1.0f,-1.0f,1.0f,-1.0f,-1.0f, 1.0f,1.0f,1.0f};//材质static const GLfloat tex[] = {0.0f, 1.0f,1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f};//顶点glVertexAttribPointer(A_VER, 2, GL_FLOAT, 0, 0, ver);glEnableVertexAttribArray(A_VER);//材质glVertexAttribPointer(T_VER, 2, GL_FLOAT, 0, 0, tex);glEnableVertexAttribArray(T_VER);//从shader获取材质unis[0] = program.uniformLocation("tex_y");unis[1] = program.uniformLocation("tex_u");unis[2] = program.uniformLocation("tex_v");//创建材质,创建三个对象glGenTextures(3, texs);//Y 绑定材质glBindTexture(GL_TEXTURE_2D, texs[0]);//放大过滤,线性插值   GL_NEAREST(效率高,但马赛克严重)glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//创建材质显卡空间glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE, 0);//UglBindTexture(GL_TEXTURE_2D, texs[1]);//放大过滤,线性插值glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//创建材质显卡空间glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);//VglBindTexture(GL_TEXTURE_2D, texs[2]);//放大过滤,线性插值glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//创建材质显卡空间glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width / 2, height / 2, 0, GL_RED, GL_UNSIGNED_BYTE, 0);///分配材质内存空间datas[0] = new unsigned char[width*height];		//Ydatas[1] = new unsigned char[width*height / 4];	//Udatas[2] = new unsigned char[width*height / 4];	//Vfp = fopen("VIDEO2.yuv", "rb");if (!fp){qDebug() << "VIDEO2.yuv file open failed!";}//启动定时器QTimer *ti = new QTimer(this);connect(ti, SIGNAL(timeout()), this, SLOT(update()));ti->start(40);
}//刷新显示
void XvideoWidget::paintGL()
{if (feof(fp)){fseek(fp, 0, SEEK_SET);}fread(datas[0], 1, width*height, fp);fread(datas[1], 1, width*height / 4, fp);fread(datas[2], 1, width*height / 4, fp);glActiveTexture(GL_TEXTURE0);//激活第0层glBindTexture(GL_TEXTURE_2D, texs[0]); //0层绑定到Y材质//修改材质内容(复制内存内容)glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, datas[0]);//与shader uni遍历关联glUniform1i(unis[0], 0);//0表示对应0层glActiveTexture(GL_TEXTURE0 + 1);glBindTexture(GL_TEXTURE_2D, texs[1]); //1层绑定到U材质//修改材质内容(复制内存内容)glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[1]);//与shader uni遍历关联glUniform1i(unis[1], 1);glActiveTexture(GL_TEXTURE0 + 2);glBindTexture(GL_TEXTURE_2D, texs[2]); //2层绑定到V材质//修改材质内容(复制内存内容)glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, datas[2]);//与shader uni遍历关联glUniform1i(unis[2], 2);glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);qDebug() << "paintGL";
}// 窗口尺寸变化
void XvideoWidget::resizeGL(int width, int height)
{qDebug() << "resizeGL " << width << ":" << height;
}

本文配套开源项目

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/336415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java开发课程表_展示Java开发人员课程包

java开发课程表60个小时以上的课程&#xff0c;5门所有级别的课程&#xff1a;成为Java编程专家 嘿&#xff0c;怪胎&#xff0c; 本周&#xff0c;在我们的JCG Deals商店中 &#xff0c;我们提供了一个极端的报价 。 我们提供的Java Developer Course Bundle 仅售39美元&am…

二阶自回归过程matlab,时间序列分析:二阶自回归过程

时间序列分析&#xff1a;二阶自回归过程Author: nex3z2019-07-131. 定义对于二阶自回归过程 $AR(2)$\begin{equation}X_t \phi_1 X_{t-1} \phi_2 X_{t-2} e_t \tag{1}\end{equation}假设 $e_t$ 独立于 $Y_{t-1}, Y_{t-2}, \cdots$。式 $(1)$ 也可以表示为\begin{equation}X…

m4s格式转换mp3_mp4怎么转换成mp3格式?mp4转mp3的傻瓜式方法

原标题&#xff1a;mp4怎么转换成mp3格式&#xff1f;mp4转mp3的傻瓜式方法或许对于很多小伙伴来说&#xff0c;要将视频改变一下格式就已经很难了&#xff0c;又何况是要将原本的视频改变成音频格式呢&#xff1f;一个是视频&#xff0c;一个是音频&#xff0c;压根就是风马牛…

Git安装及基本操作

1.安装Git 配置用户 git config --global user.name "用户名" git config --global user.email "邮箱"配置完成后查看配置 git config -l生成SSH秘钥 ssh-keygen -t rsa -C “邮箱” 输入完成后需要按3次Enter键 $ ssh-keygen -t rsa -C "邮箱&quo…

ZigBee网络数据传递流程_蓝牙、Wifi与ZigBee三种,这三种无线传输技术,谁能一统天下...

智能产品种类越来越多&#xff0c;运用在智能家居上的技术也越来越成熟。然而在无线通信协议上却一直无法做到统一&#xff0c;从目前的情况来看&#xff0c;短期内是无法实现这一愿望的了。既然如此&#xff0c;我们何不另辟蹊径&#xff0c;在这些标准中&#xff0c;选择优势…

千元平板电脑排行榜_最值得买的平板电脑推荐-最佳平板电脑品牌排行榜【2020年10月】...

平板电脑相较笔记本电脑而言&#xff0c;以其便携与功能强大的特点成为大家日常生活和工作的必备搭档&#xff0c;无论在性能配置上还是在内置软件应用方面&#xff0c;不同的使用场景有不同的需求。今天给大家推荐最佳平板电脑品牌排行&#xff0c;希望对大家选购平板电脑有帮…

java 枚举 菜鸟_2个菜鸟Java常量和枚举陷阱

java 枚举 菜鸟在对Java和Groovy代码进行的各种代码审查中&#xff0c;我经常看到魔术数字和其他随机字符串散落在整个代码库中。 例如&#xff0c;下面的&#xff08;Groovy&#xff09;代码段中的4.2是一个神奇的数字&#xff1a; if (swashbuckle > 4.2) {... }4.2是什…

python正则_python的正则表达式

上次小编写了正则表达式的用法&#xff0c;今天就小编就讲讲正则表达式再python中的应用&#xff0c;在python中想使用正则表达式就需要导入re模块。接下来小编将先介绍re模块中几个常见的函数findall:re.findall(‘正则表达式’&#xff0c;‘待匹配的内容’)例1&#xff1a;输…

公里与英里的换算c语言函数_60迈=60码=60公里?这三者天壤之别,可别搞错了

说到行车速度&#xff0c;大家经常用的是这三个单位&#xff1a;码、迈、公里/时&#xff0c;很多人以为这三者是同一个意思&#xff0c;都是每小时多少公里。实际上这三者并不等同&#xff0c;下面小编科普一下这几个词的差异。码1码不等于1公里&#xff0c;而是等于0.9144米&…

php3.2.3分组查询,ThinkPHP3.2.3版本如何设置应用分组

鑫强已经解决了我的解决方法是创建两个入口文件实际上我的目的就是想要达到两个模块共用一个配置文件和公共函数文件我的解决方法是在项目根目录下建立两个入口文件一个是Index.php与Root.php两个入口文件其中是这样写的Index.php{<?php #前台入口文件 header(Conte…

C++ 11 深度学习(一)auto、头文件防卫、引用、常量

1.数组初始化 int a[]{ 1,2,3,4,5 }; 2.C11 auto auto可以在声明变量的时候根据变量的初始值的类型自动为此变量先择合适的类型&#xff0c;声明时要赋予初值。 auto自动推导发生在编译期间 auto A 10;//A会被自动推导为int类型 3.头文件防卫式声明 作用:防止头文件重…

android 在什么情况下会主动gc_Python 什么情况下会生成 pyc 文件?

作者&#xff1a;折木奉太郎(经授权转载)来源&#xff1a;https://www.zhihu.com/question/30296617/answer/112564303作为 Python 爱好者&#xff0c;需要了解 .py 脚本的基本运行机制及特性&#xff1a;在很多工作上&#xff0c;Python 的运行流程基本上取决于用户&#xff0…

【IP协议头分析】

Version 版本号 IHL IP头长度 Type of Service Total Length 总长度 Identification 拆包的唯一标识 Flags 1位保留 &#xff0c; 2位 允许拆包 3位 不允许拆包 Fragment offset 在原包偏移量 Time to Live 时间或路由跳数 Protocol IP中是什么协议类型 Header Check…

乡村野生草药_官方野生蝇群流口水分数

乡村野生草药官方是什么&#xff1f; 标题太小&#xff0c;但有用的贡献。 Wildfly Swarm允许我们创建相当小的自包含应用程序&#xff0c;包括我们从Wildfly Application Server中需要的应用程序。 在这篇文章中&#xff0c;我们将研究与Wildfly Swarm合作使用的Drools分数 。…

obs多推流地址_(无人直播)教程利用OBS推流抖音直播电脑屏幕或PC游戏

目前的火爆程度相信大家都有目共睹&#xff0c;也為部分活躍用戶提供直播功能&#xff0c;開通直播的方法有&#xff1a;①粉絲達到10000粉絲&#xff0c;官方會自動邀請妳開通直播權限。②加入和官方合作的工會&#xff0c;無需粉絲&#xff0c;也可以開通直播權限。開通直播功…

倒数日电脑版_应用日报|iOS 或更名为 iPhoneOS,倒数日 Mac 版上线限时免费

今日推荐倒数日 Days Matter for Desktop免费&#xff0c;macOS 86 MB倒数日 Days Matter 是 iOS 端非常经典的应用&#xff0c;今天它的 Mac 版本上线&#xff0c;限时免费 7 天。它延续了 iOS 端的风格语言&#xff0c;同样能帮你记录生活中重要的日子&#xff1a;例如恋人…

【TPC协议头解析】

Source Port 源端口 Destination Port 目的端口 Sequence Number 数据报编号 (seq)&#xff08;按字节序&#xff09;保证有序 Acknowledgment Number (ACK) 报文应答, 保证可靠性 Data offset 跳到data数据部分 Reserved 保留部分 URG 紧急数据标识 ACK 确认消息…

iphone新旧手机数据传输已取消_如何取消iPhone手机App自动扣费?三种方法让你不再被“偷”...

一直以来苹果手机App这个自动续费真是让大家不胜其烦&#xff0c;钱虽然不多可总是平白无故这里十块&#xff0c;那里二十块的被扣也是不小的浪费&#xff0c;日常生活中为了追追剧、听听音乐、玩玩游戏难免会开通一些App会员而选择自动续费的话每月会费是有不错优惠的&#xf…

【TCP三次握手与四次挥手最强解析】

TCP连接拥塞控制四种方法总结&#xff08;详细简单&#xff0c;稳的一批&#xff09; TCP三次握手 作用&#xff1a;确认seqnumber&#xff1b;确定窗口大小以及最大报文大小 TCP四次挥手 WAIT_TIME状态到CLOSED需要2MSL时间&#xff08;最长单位MSL为2min,一般30s&#xff0…