qt+opengl 播放yuv视频

一、实现效果

二、pro文件

Qt += widgets opengl

三、主要代码

复制代码
#include "glwidget.h"


GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    connect(&m_timer, &QTimer::timeout, this,
            [&]()
    {
        this->update();
    });

    m_timer.start(1000/33);
}

void GLWidget::initializeGL()
{
    qDebug() << "初始化";
    initializeOpenGLFunctions();    // 初始化opengl

    qDebug() << "加载片元脚本:" <<program.addShaderFromSourceFile(QGLShader::Vertex, ":/res/shader.vert");  // 片元
    qDebug() << "加载顶点脚本:" <<program.addShaderFromSourceFile(QGLShader::Fragment, ":/res/shader.frag");    // 顶点

    qDebug() << "编译shader:" << program.link();
    qDebug() << "绑定shader:" << program.bind();

    int A_VER = -1;
    int T_VER = -1;
    // 设置顶点坐标的变量
    A_VER = program.attributeLocation("vertexIn");//, A_VER
    // 设置材质坐标
    T_VER = program.attributeLocation("textureIn");//, T_VER

    static const GLfloat ver[] = {
        -1.0f, -1.0f,   0.0f, 1.0f,//0.0f, 0.0f,
        1.0f, -1.0f,    1.0f, 1.0f,//1.0f, 0.0f,
        -1.0f, 1.0f,    0.0f, 0.0f,//0.0f, 1.0f,
        1.0f, 1.0f,     1.0f, 0.0f//1.0f, 1.0f
    };

    glGenVertexArrays(1, &m_vao);
    glBindVertexArray(m_vao);

    glGenBuffers(1, &m_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);

    glBufferData(GL_ARRAY_BUFFER, sizeof(ver), ver, GL_STATIC_DRAW);

    glVertexAttribPointer(A_VER, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(A_VER);

    glVertexAttribPointer(T_VER, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2* sizeof(float)));
    glEnableVertexAttribArray(T_VER);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    // 从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]);   // 绑定材质
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  // 设置纹理参数,放大过滤,线性插值 GL_NEAREST(效率高,效果差)
    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);   // 创建材质显卡空间

    //  U
    glBindTexture(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);   // 创建材质显卡空间

    // 创建材质 V
    glBindTexture(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);   // 创建材质显卡空间

    m_file.setFileName(":/res/1.yuv");
    if(!m_file.open(QIODevice::ReadOnly))
    {
        qDebug() << "打开失败!";
        return;
    }

}

void GLWidget::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT); // 清除颜色缓冲区

    program.bind();

    //qDebug() << "绘制";
    if(m_file.atEnd())
    {
        m_file.seek(0);
    }

    QByteArray buf;
    buf = m_file.read(width * height);

    glBindVertexArray(m_vao);

    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, buf.data());
    glUniform1i(unis[0], 0);   // 与shader的uni变量关联

    buf = m_file.read(width * height / 4);
    glActiveTexture(GL_TEXTURE0 + 1);   // 激活第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, buf.data());
    glUniform1i(unis[1], 1);   // 与shader的uni变量关联

    buf = m_file.read(width * height / 4);
    glActiveTexture(GL_TEXTURE0 + 2);   // 激活第2层  V
    glBindTexture(GL_TEXTURE_2D, texs[2]);  // 2层绑定到v材质中
    // 修改材质内容(复制内存内容)
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width / 2, height / 2, GL_RED, GL_UNSIGNED_BYTE, buf.data());
    glUniform1i(unis[2], 2);   // 与shader的uni变量关联

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  // 开始绘制

    glBindVertexArray(0);
}

void GLWidget::resizeGL(int w, int h)
{
    //qDebug() << w <<" " << h;
    glViewport(0, 0, w, h);
}

完整demo下载:点击跳转

觉得有帮助的话,打赏一下呗。。

需要商务合作(定制程序)的欢迎私信!!

相关推荐
小短腿的代码世界1 天前
Qt Bluetooth源码深度解析:从HCI协议到跨平台API的完整架构
开发语言·qt·架构
小短腿的代码世界1 天前
Qt WebEngine多进程架构与IPC通信:从Chromium多进程到Qt信号槽融合
qt·架构·系统架构
尘中远1 天前
【Qwt 7.0 系列】快速入门与核心新特性概览 —— 更现代的 Qt 数据可视化库
qt·数据可视化·绘图·qwt·科学绘图
cxr8281 天前
第14章 创意音乐与视频的多模态智能体创作
人工智能·音视频·智能体·hermes
初阳7851 天前
【Qt】系统相关(3)——多线程
qt
梦帮科技1 天前
基于EVM架构的Web3音频确权与RNS Token智能合约设计深度解析
人工智能·python·架构·web3·区块链·音视频·智能合约
初阳7851 天前
【Qt】系统相关(2)——文件
开发语言·qt
最爱老式锅包肉1 天前
《HarmonyOS技术精讲-Core Speech Kit(基础语音服务)》第1篇:音频管理基础与语音服务入门
华为·音视频·harmonyos
“码”力全开2 天前
AI视频分析飞书告警常见问题和排查清单
人工智能·音视频·飞书
西安老张(AIGC&ComfyUI)2 天前
第021章:ComfyUI文生音频Qwen3-TTS模型数字人音色设计(二)
aigc·音视频·comfyui