从零实现简易播放器-2.opengl渲染yuv图像

opengl渲染yuv图像

作者:史正
邮箱:shizheng163@126.com
如有错误还请及时指正
如果有错误的描述给您带来不便还请见谅
如需交流请发送邮件,欢迎联系

简述

直接渲染Jpeg等编码后的图像(这里使用的是Jpeg图片)是特别慢的(当张图片>40ms), 常用的做法是直接渲染yuv或者rgb的图像。

这里使用的是使用opengl渲染yuv的图像, 当然也可以通过Qt的绘图库来渲染。不过opengl默认的渲染步骤是在gpu上执行的, 而Qt的绘图库是利于cpu进行计算,gpu进行渲染, 占用cpu的资源比较多。

使用opengl渲染yuv图像的时间单帧图像为(0-2]ms
渲染完成后使主线程等待40-渲染时间, 就会呈现出视频的效果。

这一节的完整代码:

这里给出几个ffmpeg将视频分解为jpeg然后再转换为yuv的命令(由于没有找到视频直接分解为yuv图片帧的办法)

  • ffmpeg -i Suger.mp4 -b 3000k -ss 00:00:10 -t 10 SugerFrames/Frame_%04d.jpeg
  • ffmpeg -y -s 1920x1080 -i SugerFrames/yuv_0001.jpeg SugerYuvs/yuv_0001.yuv

由于没有找到直接将多张jpeg图片直接转换为多张yuv图像的方法, 这里写了一个shell脚本来处理

for((i=1;i<=480;i++))
do
    index=`printf "%04d" $i`
    ffmpeg -y -s 1920x1080 -i SugerFrames/yuv_$index.jpeg SugerYuvs/yuv_$index.yuv
done

ffmpeg 查看yuv图像或视频的方法

  • ffplay.exe -video_size 1920x1080 yuv_0001.yuv

使用QOpenGLWidget进行yuv图片渲染

除了可以选择使用QPainter和标准的OpenGL渲染图形,QOpenGLWidget类提供了在Qt应用程序中显示OpenGL图形的功能。

关于QOpenGLWidget的介绍可以参考以下文章:

笔者对opengl基本上没什么了解, 渲染部分选自以下博客,感谢博主

另外glviewport是opengl渲染的图片显示的位置, 坐标原点为左下角。

使用了opengl渲染之后,再使用QPainter渲染(当时只是想使用这个渲染默认的Jpeg图标)就会导致opengl和QPainter渲染的效果无法使用。

解决方法还没有找到, 所以干脆就把默认图片也转成了yuv图像。

.h文件

#ifndef VIDEOGLWIDGET_H
#define VIDEOGLWIDGET_H
#include <QWidget>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <memory>
#include <mutex>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
#include "fileutil.h"
class VideoGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
   
    QOBJECT_H
public:
    VideoGLWidget(QWidget * pParent = 0);
    virtual                 ~VideoGLWidget();
    void                    PictureShow(fileutil::PictureFilePtr pPicture);
    void                    DefaultPictureShow();

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

private:
    //绘图是异步动作, 防止绘图过程中,图片被置为NULL,所以需要加锁
    std::mutex                  m_mutexForShowYuvData;
    bool                        m_bIsShowVideoIcon; //是否要显示视频默认图标
    fileutil::PictureFilePtr    m_pDefaultPict;//默认图片
    fileutil::PictureFilePtr    m_pYuvPictPtr;//当前需要显示的Yuv数据

    //显示Opengl渲染后图像位置
    QRect                       m_drawRect;

    //渲染yuv图像变量
    GLuint                      textureUniformY; //y纹理数据位置
    GLuint                      textureUniformU; //u纹理数据位置
    GLuint                      textureUniformV; //v纹理数据位置
    GLuint                      id_y; //y纹理对象ID
    GLuint                      id_u; //u纹理对象ID
    GLuint                      id_v; //v纹理对象ID
    QOpenGLTexture*             m_pTextureY;  //y纹理对象
    QOpenGLTexture*             m_pTextureU;  //u纹理对象
    QOpenGLTexture*             m_pTextureV;  //v纹理对象
    QOpenGLShader *             m_pVSHader;  //顶点着色器程序对象
    QOpenGLShader *             m_pFSHader;  //片段着色器对象
    QOpenGLShaderProgram        *m_pShaderProgram; //着色器程序容器
};

#endif // VIDEOGLWIDGET_H

PicturePtr结构如下

#include <string>
#include <stdint.h>
#include <memory>
struct FileRawData
{
   
    FileRawData(){
   
        m_pData = NULL;
    }
    FileRawData(FileRawData && filedata)
    {
   
        m_pData = filedata.m_pData;
        m_uLen = filedata.m_uLen;
        m_filename = filedata.m_filename;
        filedata.m_pData = NULL;
        filedata.m_uLen = 0;
        filedata.m_filename.clear(
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值