Qt中使用OpenGL渲染视频

2023-11-16

Qt5.4之后,OpenGL在Qt中可以通过QOpenGLWidget和QOpenGLFunctions来实现,以下Demo(只展示OpenGL相关部分)解码出AVFrame后对其进行渲染。

//顶点Shader
static const char vertexShaderSource[] =
"attribute vec4 position;           \n"
"attribute vec2 texcoord;           \n"
"varying vec2 v_texcoord;           \n"
"void main()                        \n"
"{                                  \n"
"   gl_Position = position;         \n"
"   v_texcoord = texcoord.xy;       \n"
"}                                  \n";

//片元Shader
static const char yuvFragmentShaderSource[] =
"precision mediump float;                              \n"
"varying vec2 v_texcoord;                              \n"
"uniform sampler2D s_texture_y;                        \n"
"uniform sampler2D s_texture_u;                        \n"
"uniform sampler2D s_texture_v;                        \n"
"void main()                                           \n"
"{                                                     \n"
"   vec3 yuv;                                          \n"
"   vec3 rgb;                                          \n"
"   yuv.r = texture2D(s_texture_y, v_texcoord).r;      \n"
"   yuv.g = texture2D(s_texture_u, v_texcoord).r - 0.5;\n"
"   yuv.b = texture2D(s_texture_v, v_texcoord).r - 0.5;\n"
"   rgb = mat3(1.0, 1.0, 1.0,                          \n"
"              0.0, -0.39465, 2.03211,                 \n"
"              1.13983, -0.58060, 0.0)*yuv;            \n"
"   gl_FragColor = vec4(rgb,1.0);                      \n"
"}                                                     \n";

//Vertex coordinates
static const GLfloat verCoords[] = {
	-1.0f, -1.0f,
	 1.0f, -1.0f,
	-1.0f,  1.0f,
	 1.0f,  1.0f
};

//Material coordinates
static const GLfloat texCoords[] = {
	0.0f, 1.0f,
	1.0f, 1.0f,
	0.0f, 0.0f,
	1.0f, 0.0f
};

头文件部分

class VideoWidget : public QOpenGLWidget, protected QOpenGLFunctions {
	Q_OBJECT

public:
	explicit VideoWidget(QWidget *parent = 0);
	~VideoWidget() override;
	GLuint VideoWidget::InitShader(GLenum type, const GLchar *code);

protected:
	void initializeGL() override;
	void paintGL() override;
	void resizeGL(int w, int h) override;

private:
	int viewPortWidth_ = 0;   
	int viewPortHeight_ = 0;
	GLuint program;
	std::array<GLuint, 3> textures;

};

在initializeGL函数中需要添加initializeOpenGLFunctions()完成初始化,然后启动定时器QTimer

void VideoWidget::initializeGL() {
	initializeOpenGLFunctions();

    //初始化等相关加载工作
    // ......
    // ......

	QTimer *time = new QTimer(this);
	connect(time, SIGNAL(timeout()), this, SLOT(update()));
	time->start(15);
}
void VideoWidget::resizeGL(int w, int h) {
	LOG(INFO) << "resizeGL: " << w << "," << h;
	viewPortWidth_ = w;
	viewPortHeight_ = h;
}

Shader的创建、编译

GLuint VideoWidget::InitShader(GLenum type, const GLchar *code) {
	GLuint shader = glCreateShader(type);
	if (shader == 0 || shader == GL_INVALID_ENUM) {
		LOG(ERROR) << "Failed to create shader";
		return 0;
	}

	glShaderSource(shader, 1, &code, NULL);
	glCompileShader(shader);

#ifdef DEBUG
	GLint logLength;
	glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
	if (logLength > 0) {
		GLchar *log = (GLchar *)malloc(logLength);
		glGetShaderInfoLog(shader, logLength, &logLength, log);
		LOG(INFO) << "Shader compile log : " << log;
		free(log);
	}
#endif

	GLint status;
	glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
	if (status == GL_FALSE) {
		glDeleteShader(shader);
		LOG(ERROR) << "Failed to compile shader";
		return 0;
	}

	return shader;
}
void VideoWidget::paintGL() {
	//需要获取frame
	//......
	//......
	auto frame = mediaSamples[0]->GetFrame();
	
	glViewport(0, 0, viewPortWidth_, viewPortHeight_);
	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
	glGenTextures(3, textures.data());
	int width = frame->width;
	int height = frame->height;
	int widths[3] = { width, width >> 1, width >> 1 };
	int heights[3] = { height, height >> 1, height >> 1 };
	//支持的是yuv格式数据
	for (int i = 0; i < 3; ++i) {
		glPixelStorei(GL_UNPACK_ROW_LENGTH, frame->linesize[i]);
		glBindTexture(GL_TEXTURE_2D, textures[i]);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, widths[i], heights[i],
			0, GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[i]);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	}
	glBindTexture(GL_TEXTURE_2D, 0);

	program = glCreateProgram();
	GLuint vShader = InitShader(GL_VERTEX_SHADER, vertexShaderSource);
	if (!vShader) {
		glDeleteShader(vShader);
		CHECK(false) << "CreateShader GL_VERTEX_SHADER failed";
	}
	GLuint fShader = InitShader(GL_FRAGMENT_SHADER, yuvFragmentShaderSource);
	if (!fShader) {
		glDeleteShader(fShader);
		CHECK(false) << "CreateShader GL_VERTEX_SHADER failed";
	}
	glAttachShader(program, vShader);
	glAttachShader(program, fShader);
	glBindAttribLocation(program, 0, "position");
	glBindAttribLocation(program, 1, "texcoord");
	glLinkProgram(program);
	GLint status;
	glGetProgramiv(program, GL_LINK_STATUS, &status);
	if (status == GL_FALSE) {
		glDeleteProgram(program);
		CHECK(false) << "failed to link program : " << program;
	}
	glValidateProgram(program);
#ifdef DEBUG
	GLint logLength;
	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
	if (logLength > 0) {
		GLchar *log = (GLchar *)malloc(logLength);
		glGetProgramInfoLog(program, logLength, &logLength, log);
		LOG(INFO) << "program validate log : " << log;
		free(log);
	}
#endif
	glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
	if (status == GL_FALSE) {
		LOG(INFO) << "ValidateProgram failed";
		exit(1);
	}
	glUseProgram(program);
	glUniform1i(glGetUniformLocation(program, "s_texture_y"), 0);
	glUniform1i(glGetUniformLocation(program, "s_texture_u"), 1);
	glUniform1i(glGetUniformLocation(program, "s_texture_v"), 2);

	for (int i = 0; i < 3; ++i) {
		glActiveTexture(GL_TEXTURE0 + i);
		glBindTexture(GL_TEXTURE_2D, textures[i]);
	}
	glVertexAttribPointer((GLuint)ATTRIBUTE_COORD::ATTRIBUTE_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, verCoords);
	glEnableVertexAttribArray((GLuint)ATTRIBUTE_COORD::ATTRIBUTE_VERTEX);
	glVertexAttribPointer((GLuint)ATTRIBUTE_COORD::ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
	glEnableVertexAttribArray((GLuint)ATTRIBUTE_COORD::ATTRIBUTE_TEXCOORD);
	
	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt中使用OpenGL渲染视频 的相关文章

  • 无法将 [未定义] 分配给 QColor

    我正在使用 Qt 5 11 构建 运行代码 代码中有QML风格如下 Button style delegate Component id enabledButtonStyle ButtonStyle padding top 0 paddin
  • Qt 和 MOC 的困境与简单的制作

    我想这更像是一个 GNU Make 问题 而不是 Qt 和 moc 但这里是 我有一个包含多个目录Q OBJECTS 我有一些简单的代码 它收集所有这些 例如 MOCS shell grep l Q OBJECT HEADERS Assum
  • 如何通过信号和槽传递参数?

    我的 GUI 包括LineEdit and a 按钮 当 的时候按钮单击后 插槽clicked 叫做 我想在之间建立信号槽关系clicked 作为信号和doSomething 作为插槽 问题是doSomething 无权访问 UI 并且do
  • 更改 Qt 中的语言环境

    我尝试使用 QLocale 和 setDefault 函数更改区域设置 但似乎不起作用 以下是使用 C 本地化库和 QLocale 更改语言环境的示例 对于 C 本地化库 它似乎可以工作 但对于 QLocale setDefault 函数调
  • 仅当从 Qt 连接时网页返回 HTTP 406 错误

    我有一个测试页面设置http mlecturedownload com test qt php http mlecturedownload com test qt php有以下代码
  • QtWebEngine Quicknano 在嵌入式 Linux 中没有声音

    我已将 QtWebEngine 编译到我的 i MX6 嵌入式设备中 当我尝试使用 Quicknanobrowser 播放 YouTube 视频时 视频会播放 但没有声音 事实上 当我尝试播放音频文件时没有声音hpr dogphilosop
  • 在 Qt 中创建/写入新文件

    我正在尝试写入文件 如果该文件不存在 则创建它 我在互联网上搜索过 但没有任何效果 我的代码目前看起来像这样 QString filename Data txt QFile file filename if file open QIODev
  • QWebView等待加载

    bool MainWindow waitForLoad QWebView view QEventLoop loopLoad QTimer timer QObject connect view SIGNAL loadFinished bool
  • 如何阻止 Qt Creator 将可执行文件放置在“调试”子目录中?

    我正在 Qt Creator 中构建一个项目 虽然我不关心中间 obj 文件去哪里 但重要的是最终的可执行文件应放入 并运行 许多依赖项 DLL 等所在的特定目录中 被发现 因此 在 Qt Creator 中 我选择 Shadow Buil
  • 如何从 ffmpeg 中打开的文件获取流信息?

    我正在尝试使用 ffmpeg 读取视频文件 我有与其旧版本相对应的工作代码 并开始尝试升级到最新的构建版本 将所有这些已弃用的函数替换为其实际的类似函数 但是我遇到了问题 似乎没有检索到任何流 并且视频负载停止在轨道中 这是我正在使用的代码
  • 如何改善 Qt5 程序的启动时间?

    我最近切换到 Qt5 我注意到与 Qt4 相比 初始化 QApplication 花费的时间明显更长 大约几分钟 仔细一看 程序似乎把时间花在了这里 Qt5Guid dll QGlobalStatic
  • QListWidget 拖放项目从 Symbian 列表中消失

    我在实现带有可通过拖放重新排序的自定义项的 QListWidget 时遇到问题 问题是当我在某个项目上快速双击 非常短的拖放 时 该项目有时会从 QListWidget 中消失 这是我的小部件的构造函数 ListPopisiDragDrop
  • PyQt QFileDialog exec_ 很慢

    我正在使用自定义QFileDialog因为我想选择多个目录 但是exec 功能非常慢 我不明白为什么 我正在使用最新版本的 PyQt 代码片段 from PyQt4 import QtGui QtCore QtNetwork uic cla
  • QStandardItemModel::removeRows() 在我的用例中不起作用

    基本上我想删除模型中的所有行 我更喜欢使用removeRows 代替clear 因为我想保留我的标题 我想我错过了一些东西 文档在这里 http doc qt nokia com 4 7 snapshot qstandarditemmode
  • 使用 QSet 作为 Qt 地图容器中的键

    我需要一个映射 其中键是唯一的 并且每个键都是一组或自定义 POD 结构 其中包含 3 个数据项 这些值只是指向对象实例的指针 从阅读Qt 的 QMap 与 QHash 的文档 http qt project org doc qt 4 8
  • 带 Qt 的菜单栏/系统托盘应用程序

    我是 Qt PyQt 的新手 我正在尝试制作一个应用程序 其功能将从菜单栏 系统托盘执行 这里展示了一个完美的例子 我找不到关于如何做到这一点的好资源 有人可以建议吗 Thanks 我认为您正在寻找与QMenu and QMainWindo
  • QPainter 性能高帧率

    我试图在 QPainter 中以 60fps 的速度显示视频 在 OpenGLwidget 中 我遇到一个问题 有时绘图花费的时间太长 并且在使用 QPainter 时发生下一个重绘事件 这会生成警告和随机崩溃 有几个问题 是否有一种 Qt
  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • 在 Qt 5 中嵌入 Python

    我想将 Python 解释器嵌入到 Qt 5 应用程序中 我在 Qt 5 中有一个工作应用程序 但是当我把 include
  • 如何为 qmlRegisterSingletonType 实现单例提供程序?

    我想在 QML 中使用 C 类作为 Singleton 实例 并认为我必须使用 qmlRegisterSingletonType 注册它们 此函数需要一个提供已注册 C 类的实例的函数 我在 Windows 上使用最新的 Qt 5 3 1

随机推荐

  • pyQt5 学习笔记(19)QFrame 边框设置

    文章目录 一 QFrame 简介 二 QFrame 的创建 三 组合效果图 四 QFrame 的功能 API 1 功能 2 QFrame 结构 3 使用总结 1 挑选目标样式 2 根据参数写程序 五 信号 一 QFrame 简介 QFram
  • mysql 数组_MySQL如何实现数组功能

    前段时间想要用数组功能实现某些需求 结果发现mysql不支持数组 这个确实让人很头痛 查阅官方文档 也没有这一方面的资料 结果在网上 看到了某仁兄贴出了变相实现的一种方法 代码如下 DELIMITER DROP DATABASE IF EX
  • 【Ubuntu】使用grub2挂载NFS根文件系统(rootfs)

    经常调试arm开发板的同学应该比较熟悉uboot 它可以使用tftp自动下载内核并通过nfs挂载rootfs 其实 作为x86平台常见的bootloader grub也可以做到通过nfs挂载rootfs 安装grub2 目前新版的ubunt
  • 云vscode搭建--使用容器化部署

    Vscode作为一个轻量级的IDE 其支持丰富的插件 而通过这些插件我们就可以实现在Vscode中写任何语言的代码 Code Server是Vscode的网页版 启动Code Server之后我们就可以在浏览器中打开vscode来愉快的编写
  • java 分页page_java分页PageHelper的使用

    我以前写分页都是些工具类后面偶然的机会发现了这个pagehelper在github上开源框架 maven依赖 com github pagehelper pagehelper 5 1 6 只需要在service层加上然后在controlle
  • 网络安全单兵工具 -- YAKIT

    网络安全单兵工具 YAKIT 一 下载及安装 1 原作者及下载地址 https github com yaklang yakit 2 双击下载好的exe文件 点击核心引擎安装与升级 3 点击意见更新Yak引擎 4 以管理员启动 5 点击连接
  • 《从Paxos到ZooKeeper》读书笔记之第一章(二)

    从Paxos到ZooKeeper 读书笔记之第一章 二 1 2从ACID到CAP BASE 这一节由三小节 从大家数值的数据库事务的四个特性 引出来分布式事务的概念 通过对ACID模型的讨论 提出如何构建一个兼顾可用性和一致性的分布式系统方
  • 前端技术面试大全

    快速搞定前端技术一面 匹配大厂面试要求 迅速建立初中级前端面试 0 2年 JS知识体系 掌握解决面试题的思路与技巧 知识点介绍 CSS 布局 定位 移动端响应式 ES语法 原型 原型链 作用域 闭包 异步 单线程 Web API DOM B
  • SQL复习要点

    1 数据库系统阶段的数据管理特点 1 数据结构化2 数据共享性高 冗余度小 易扩充 3 数据独立性高4 统一的数据管理和控制功能 2 数据库 database DB 是存放数据的仓库 3 数据库管理系统 data base manageme
  • js 截取字符串里的IP和port

    例如 str 192 168 12 254 18081 1 用 ip和port 的正则 let ip reg d gi let ip ip reg exec str ip ip 0 let port reg d 1 5 let port s
  • C++,菱形继承和虚继承

    一 菱形继承的基本概念 菱形继承又称为钻石继承 由公共基类派生出多个中间子类 又由多个中间子类共同派生出汇聚子类 汇聚子类会得到 中间子类从公共基类继承下来的多份成员 菱形继承的格式 A 公共基类 B C 中间子类 D 汇聚子类 示例 in
  • 读《企业中的开放源代码》有感

    文章目录 开源代码的益处 开源的本质 开源是一门学科 开源代码的益处 学习出色编码技能的最佳方法是开发开源项目 注意是开发而不是阅读 因为可以研究该领域内顶尖编码员所采用的实践 以更快的方式启动新项目 从此没有必要再闭门造车 开源的本质 我
  • Linux平台下二进制安装FastDDS

    1 Linux平台下二进制安装 该页面主要介绍在linux环境下 使用二进制release安装 eProsima公司的 Fast DDSThe 安装 内容 运行应用 在一个CMake项目中包含Fast DDS 卸载 1 1 安装 ePros
  • 规则动词的过去式及发音规则

    规则动词的过去式词尾变化有几种 1 一般情况下加ed 如watched planted watered pulled climbed picked 2 以不发音字母e结尾的加d 如liked moved tasted 3 以辅音字母加y结尾
  • 线程池使用之自定义线程池

    目录 一 Java内置线程池原理剖析 二 ThreadPoolExecutor参数详解 三 线程池工作流程总结示意图 四 自定义线程池 参数设计分析 1 核心线程数 corePoolSize 2 任务队列长度 workQueue 3 最大线
  • Java学习心得8——继承

    当我们需要设计几个类似的类的时候 我们可以把它们之间的相同的东西提取出来放到一个父类中 然后这几个类就可以不写这些相同的东西 只要去继承那个父类就可以得到这些东西了 假如我们需要设计三个类Fish Bird Dog 它们的共同点是都有年龄
  • UE4 实现用鼠标旋转场景中的物体

    本文实现的是用在UE4 中用鼠标旋转场景中的物体 点击到物体时开始物体旋转功能 移动鼠标物体跟着旋转相应的角度 松开鼠标左键物体停止旋转 下面介绍实现此功能的蓝图逻辑 由于比较简单就不一一介绍了 直接贴上蓝图代码 如有问题欢迎交流
  • dpkg:警告:无法找到软件包 XXX的文件名列表文件,现假定该软件包目前没有任何文件被安装在系统里。(详细的解决过程)

    1 问题描述 在使用sudo apt get update 和upgrade中会出现 dpkg 警告 无法找到软件包ca certificates 的文件名列表文件 现假定该软件包目前没有任何文件被安装在系统里 dpkg 警告 无法找到软件
  • docker gitlab 数据 迁移 2770

    我的操作步骤 1 把 gitlab目录下 的 data etc log 目录下压缩并拷贝 2 把压缩文件 拷贝到新的gitlab 指定目录下 3 启动 错误 up to date storage directory var opt gitl
  • Qt中使用OpenGL渲染视频

    Qt5 4之后 OpenGL在Qt中可以通过QOpenGLWidget和QOpenGLFunctions来实现 以下Demo 只展示OpenGL相关部分 解码出AVFrame后对其进行渲染 顶点Shader static const cha