Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Qt5.8.0 QOpenGLWidget display video on ubuntu 16.04
Forum Updated to NodeBB v4.3 + New Features

Qt5.8.0 QOpenGLWidget display video on ubuntu 16.04

Scheduled Pinned Locked Moved Unsolved Mobile and Embedded
6 Posts 2 Posters 3.4k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alex_wang
    wrote on last edited by Alex_wang
    #1

    Hi,
    My question is :
    when I use QOpenGLWidget to display a yuv video file on ubuntu 16.04, the screen has only one frame image and the image has many black holes.
    The image is similar :

    ***************************
    **O**O**O**O**O**O**O**O***
    **O**O**O**O**O**O**O**O***
    **O**O**O**O**O**O**O**O***
    **O**O**O**O**O**O**O**O***
    **O**O**O**O**O**O**O**O***
    ***************************
    

    Environment:
    Qt version : 5.8.0
    Ubuntu : 16.04
    OpenGl :
    OpenGL vendor string: NVIDIA Corporation
    OpenGL renderer string: NVIDIA Tegra X1 (nvgpu)/integrated
    OpenGL core profile version string: 4.5.0 NVIDIA 24.2.1
    OpenGL core profile shading language version string: 4.50 NVIDIA
    OpenGL core profile context flags: (none)
    OpenGL core profile profile mask: core profile
    OpenGL core profile extensions:
    OpenGL version string: 4.5.0 NVIDIA 24.2.1
    OpenGL shading language version string: 4.50 NVIDIA
    OpenGL context flags: (none)
    OpenGL profile mask: (none)
    OpenGL extensions:
    OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 24.2.1
    OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20

    1 Reply Last reply
    0
    • A Offline
      A Offline
      Alex_wang
      wrote on last edited by
      #2

      My code :

      void CQOpenGLDisplay::initializeGL()
      {
          initializeOpenGLFunctions();
      
          glEnable(GL_DEPTH_TEST);
      
          //现代opengl渲染管线依赖着色器来处理传入的数据
          //着色器:就是使用openGL着色语言(OpenGL Shading Language, GLSL)编写的一个小函数,
          //       GLSL是构成所有OpenGL着色器的语言,具体的GLSL语言的语法需要读者查找相关资料
          //初始化顶点着色器 对象
          m_pVSHader = new QOpenGLShader(QOpenGLShader::Vertex, this);
          //顶点着色器源码
          const char *vsrc = "attribute vec4 vertexIn; \
          attribute vec2 textureIn; \
          varying vec2 textureOut;  \
          void main(void)           \
          {                         \
              gl_Position = vertexIn; \
              textureOut = textureIn; \
          }";
          //编译顶点着色器程序
          bool bCompile = m_pVSHader->compileSourceCode(vsrc);
          if(!bCompile)
          {
          }
      
          //初始化片段着色器 功能gpu中yuv转换成rgb
          m_pFSHader = new QOpenGLShader(QOpenGLShader::Fragment, this);
          //片段着色器源码
          const char *fsrc = "varying vec2 textureOut; \
          uniform sampler2D tex_y; \
          uniform sampler2D tex_u; \
          uniform sampler2D tex_v; \
          void main(void) \
          { \
              vec3 yuv; \
              vec3 rgb; \
              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; \
              rgb = mat3( 1,       1,         1, \
                          0,       -0.39465,  2.03211, \
                          1.13983, -0.58060,  0) * yuv; \
              gl_FragColor = vec4(rgb, 1); \
          }";
          //将glsl源码送入编译器编译着色器程序
          bCompile = m_pFSHader->compileSourceCode(fsrc);
          if(!bCompile)
          {
          }
      #define PROGRAM_VERTEX_ATTRIBUTE 0
      #define PROGRAM_TEXCOORD_ATTRIBUTE 1
          //创建着色器程序容器
          m_pShaderProgram = new QOpenGLShaderProgram;
          //将片段着色器添加到程序容器
          m_pShaderProgram->addShader(m_pFSHader);
          //将顶点着色器添加到程序容器
          m_pShaderProgram->addShader(m_pVSHader);
          //绑定属性vertexIn到指定位置ATTRIB_VERTEX,该属性在顶点着色源码其中有声明
          m_pShaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX);
          //绑定属性textureIn到指定位置ATTRIB_TEXTURE,该属性在顶点着色源码其中有声明
          m_pShaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE);
          //链接所有所有添入到的着色器程序
          m_pShaderProgram->link();
          //激活所有链接
          m_pShaderProgram->bind();
          //读取着色器中的数据变量tex_y, tex_u, tex_v的位置,这些变量的声明可以在
          //片段着色器源码中可以看到
          textureUniformY = m_pShaderProgram->uniformLocation("tex_y");
          textureUniformU =  m_pShaderProgram->uniformLocation("tex_u");
          textureUniformV =  m_pShaderProgram->uniformLocation("tex_v");
          // 顶点矩阵
          static const GLfloat vertexVertices[] = {
              -1.0f, -1.0f,
               1.0f, -1.0f,
               -1.0f, 1.0f,
               1.0f, 1.0f,
          };
          //纹理矩阵
          static const GLfloat textureVertices[] = {
              0.0f,  1.0f,
              1.0f,  1.0f,
              0.0f,  0.0f,
              1.0f,  0.0f,
          };
          //设置属性ATTRIB_VERTEX的顶点矩阵值以及格式
          glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices);
          //设置属性ATTRIB_TEXTURE的纹理矩阵值以及格式
          glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
          //启用ATTRIB_VERTEX属性的数据,默认是关闭的
          glEnableVertexAttribArray(ATTRIB_VERTEX);
          //启用ATTRIB_TEXTURE属性的数据,默认是关闭的
          glEnableVertexAttribArray(ATTRIB_TEXTURE);
          //分别创建y,u,v纹理对象
          m_pTextureY = new QOpenGLTexture(QOpenGLTexture::Target2D);
          m_pTextureU = new QOpenGLTexture(QOpenGLTexture::Target2D);
          m_pTextureV = new QOpenGLTexture(QOpenGLTexture::Target2D);
          m_pTextureY->create();
          m_pTextureU->create();
          m_pTextureV->create();
          //获取返回y分量的纹理索引值
          id_y = m_pTextureY->textureId();
          //获取返回u分量的纹理索引值
          id_u = m_pTextureU->textureId();
          //获取返回v分量的纹理索引值
          id_v = m_pTextureV->textureId();
          glClearColor(0.3,0.3,0.3,0.0);//设置背景色
          //qDebug("addr=%x id_y = %d id_u=%d id_v=%d\n", this, id_y, id_u, id_v);
      }
      void CQOpenGLDisplay::resizeGL(int w, int h)
      {
          if(h == 0)// 防止被零除
          {
              h = 1;// 将高设为1
          }
          //设置视口
          glViewport(0,0, w,h);
      }
      void CQOpenGLDisplay::paintGL()
      {
          //加载y数据纹理
          //激活纹理单元GL_TEXTURE0
          glActiveTexture(GL_TEXTURE0);
          //使用来自y数据生成纹理
          glBindTexture(GL_TEXTURE_2D, id_y);
          //使用内存中m_pBufYuv数据创建真正的y数据纹理
          glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW, m_nVideoH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, m_pBufYuv);
          glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
          //加载u数据纹理
          glActiveTexture(GL_TEXTURE1);//激活纹理单元GL_TEXTURE1
          glBindTexture(GL_TEXTURE_2D, id_u);
          glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (char*)m_pBufYuv+m_nVideoW*m_nVideoH);
          glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
          //加载v数据纹理
          glActiveTexture(GL_TEXTURE2);//激活纹理单元GL_TEXTURE2
          glBindTexture(GL_TEXTURE_2D, id_v);
          glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (char*)m_pBufYuv+m_nVideoW*m_nVideoH*5/4);
          glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
          //指定y纹理要使用新值 只能用0,1,2等表示纹理单元的索引,这是opengl不人性化的地方
          //0对应纹理单元GL_TEXTURE0 1对应纹理单元GL_TEXTURE1 2对应纹理的单元GL_TEXTURE2
          glUniform1i(textureUniformY, 0);
          //指定u纹理要使用新值
          glUniform1i(textureUniformU, 1);
          //指定v纹理要使用新值
          glUniform1i(textureUniformV, 2);
          //使用顶点数组方式绘制图形
          glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
          //return;
       }
      int CQOpenGLDisplay::DisplayOneFrame()
      {
          //函数功能读取一张yuv图像数据进行显示,每单击一次,就显示一张图片
          if(NULL == m_pYuvFile)
          {
              //打开yuv视频文件 注意修改文件路径
              m_pYuvFile = fopen(YUV_FILE_PATH, "rb");
      
              //根据yuv视频数据的分辨率设置宽高,demo当中是1080p,这个地方要注意跟实际数据分辨率对应上
              m_nVideoW = 1920;
              m_nVideoH = 1080;
              //resizeGL(m_nVideoW,m_nVideoH);
          }
      
          //申请内存存一帧yuv图像数据,其大小为分辨率的1.5倍
          int nLen = m_nVideoW*m_nVideoH*3/2;
          if(NULL == m_pBufYuv)
          {
              m_pBufYuv = new unsigned char[nLen];
              qDebug("CPlayWidget::PlayOneFrame new data memory. BufferLen=%d width=%d height=%d\n",
                     nLen, m_nVideoW, m_nVideoW);
          }
          //将一帧yuv图像读到内存中
          if(NULL == m_pYuvFile)
          {
              qFatal("read yuv file err.may be path is wrong!\n");
              return -1;
          }
      
          int readSize = 0;
          readSize  = fread(m_pBufYuv, 1, nLen, m_pYuvFile);
      
          if (readSize < nLen && ferror(m_pYuvFile))
          {
              qDebug()<<"YUV文件读取出错readSize: "<<readSize;
              return -1;
          }
          //刷新界面,触发paintGL接口
          update();
      
          return 0;
      }
      
      1 Reply Last reply
      0
      • A Offline
        A Offline
        Alex_wang
        wrote on last edited by
        #3

        the same code is ok when running on windows

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi,

          IIRC, Qt 5.8 has support for uyvy and yuyv image format.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          1
          • A Offline
            A Offline
            Alex_wang
            wrote on last edited by
            #5

            Hi.
            How to do?

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              IIRC, it's only available thought QML. Can you use that for that part ?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved