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下载:点击跳转

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

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

相关推荐
AI视频工具指南3 小时前
用 AI 能做哪些视频?按想交付的作品选做法
人工智能·aigc·音视频
希和20279 小时前
免费AI视频生成工具汇总(国内优先,适合做漫剧、短视频,Obsidian笔记版)
人工智能·笔记·音视频
謓泽12 小时前
【插件】用写网页的方式做视频?HyperFrames 让我重新理解了“做视频“这件事!
gpt·ai·大模型·音视频·媒体·claude·视频
无忧_wy13 小时前
MoneyPrinterTurbo 自动化视频生成实战指南
运维·人工智能·自动化·音视频
联犀2 天前
联犀 Go SIMD 实战:视频转码从 16.5ms 到 5.46ms
开发语言·golang·音视频
9527华安2 天前
FPGA纯verilog实现DP视频接口,支持2K60帧分辨率,提供3套工程源码和技术支持
fpga开发·音视频·dp
MetaEnchanter2 天前
视频章节怎么整理:填好时间点,导出前检查这几处
音视频
奇树谦2 天前
Qt Quick 图片加载与 GPU 纹理机制详解:QImage、QQuickTextureFactory、QSGTexture 与异步加载
开发语言·qt·系统架构
小豆庄2 天前
测试视频里的人脸车牌敏感信息自动化脱敏方案
计算机视觉·目标跟踪·ffmpeg·音视频·边缘计算·视频·敏捷流程
光泽雨3 天前
WPF 音视频四大核心方案对比
wpf·音视频