Tutorial :How to play YUV video in Qt4?


I want to play YUV video sequence by using Qt. Now I am using QPixmap, by using DrawPixel on QPixmap pixel by pixel. However, it can't play the video in real-time. How can I do to improve the speed?


Did you try using the Phonon classes like VideoPlayer?

Take a look at this:



Pixel by pixel is about the slowest method to create a picture. It would improve performance a lot if you processed the image data before and used QPixmap's loadFromData() method.


Well, DrawPixel is definetily the worst perfomance solution.

QOpenGLWiget nowadays (Qt 5) could be used for rendering video frames to a texture. Actually, depending on the video pixel format, it could be either simple texture rendering or a pixel format conversion via shaders with further texture drawing.

The question is old, so I'll leave a sketchy solution just because it took me some time to get to it myself once. So, the simpliest (not best, because lots of optimizations are possible) solution is:


#pragma once      #include <QOpenGLWidget>  #include <QOpenGLFunctions>  #include <QScopedPointer>  #include <QException>      /*!   * \brief The OpenGLDisplay class   * Simple OpenGL display, that renders RGBA to texture   */  class OpenGLDisplayRGB : public QOpenGLWidget, public QOpenGLFunctions  {      Q_OBJECT      public:      explicit OpenGLDisplayRGB(QWidget* parent = nullptr);      ~OpenGLDisplayRGB() override;      protected:      void initializeGL() override;      void resizeGL(int w, int h) override;      void paintGL() override;        void closeEvent(QCloseEvent* e) override;      public:      void DisplayVideoFrame(unsigned char* data, int frameWidth, int frameHeight);          Q_SIGNAL void closed();        private:      struct OpenGLDisplayRGBImpl;      QScopedPointer<OpenGLDisplayRGBImpl> impl;  };  


#include "OpenGLDisplayRGB.h"    #include <QOpenGLShader>  #include <QOpenGLTexture>  #include <QCoreApplication>  #include <QResizeEvent>  #include <QTimer>  #include <QDebug>      #define ATTRIB_VERTEX 0  #define ATTRIB_TEXTURE 1    namespace  {      //Vertex matrix      static const GLfloat vertexVertices[] = {          -1.0f, -1.0f,           1.0f, -1.0f,           -1.0f, 1.0f,           1.0f, 1.0f,      };        //Texture matrix      static const GLfloat textureVertices[] = {          0.0f,  1.0f,          1.0f,  1.0f,          0.0f,  0.0f,          1.0f,  0.0f,      };  }    struct OpenGLDisplayRGB::OpenGLDisplayRGBImpl  {      OpenGLDisplayRGBImpl(QObject* ownerPtr)          : mBufRGB(nullptr)          //, mRepaintTimer(new QTimer(ownerPtr))          , mEnabled(true)          , mShaderProgram(new QOpenGLShaderProgram(ownerPtr))          , mTexture(new QOpenGLTexture(QOpenGLTexture::Target2D))      { }        unsigned char*                      mBufRGB;      //QTimer*                             mRepaintTimer;      bool                                mEnabled;        QOpenGLShader*                      mVShader;      QOpenGLShader*                      mFShader;      QOpenGLShaderProgram*               mShaderProgram;        QScopedPointer<QOpenGLTexture>      mTexture;        int                                 mTextureUniform;      GLsizei                             mVideoW, mVideoH;    };    /*************************************************************************/    OpenGLDisplayRGB::OpenGLDisplayRGB(QWidget* parent)      : QOpenGLWidget(parent)      , impl(new OpenGLDisplayRGBImpl(this))  {      setAttribute(Qt::WA_OpaquePaintEvent);  //    setAttribute(Qt::WA_PaintOnScreen);      setAttribute(Qt::WA_NoSystemBackground);        /*      impl->mRepaintTimer->setInterval(50);      connect(impl->mRepaintTimer, SIGNAL(timeout()), this, SLOT(update()));      impl->mRepaintTimer->start();*/  }      OpenGLDisplayRGB::~OpenGLDisplayRGB()  {      makeCurrent();  }      void OpenGLDisplayRGB::DisplayVideoFrame(unsigned char *data, int frameWidth, int frameHeight)  {      impl->mVideoW = frameWidth;      impl->mVideoH = frameHeight;      impl->mBufRGB = data;      update();  }      void OpenGLDisplayRGB::initializeGL()  {      initializeOpenGLFunctions();        glEnable(GL_DEPTH_TEST);        /* Modern opengl rendering pipeline relies on shaders to handle incoming data.       *  Shader: is a small function written in OpenGL Shading Language (GLSL).       * GLSL is the language that makes up all OpenGL shaders.       * The syntax of the specific GLSL language requires the reader to find relevant information. */        impl->mEnabled = impl->mShaderProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/OpenGL/simple_vertex_shader.v.glsl");      if(!impl->mEnabled)          qDebug() << QString("[Error] Vertex shader failed: %1").arg(impl->mShaderProgram->log());        impl->mShaderProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/OpenGL/simple_texture_shader.f.glsl");      if(!impl->mEnabled)          qDebug() << QString("[Error] Fragment shader failed: %1").arg(impl->mShaderProgram->log());        // Bind the property vertexIn to the specified location ATTRIB_VERTEX, this property      // has a declaration in the vertex shader source      impl->mShaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX);      // Bind the attribute textureIn to the specified location ATTRIB_TEXTURE, the attribute      // has a declaration in the vertex shader source      impl->mShaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE);      //Link all the shader programs added to      impl->mShaderProgram->link();      //activate all links      impl->mShaderProgram->bind();      // Read the position of the data variable tex_rgb in the shader, the declaration      // of these variables can be seen in      // fragment shader source      impl->mTextureUniform = impl->mShaderProgram->uniformLocation("uSampler");        // Set the value of the vertex matrix of the attribute ATTRIB_VERTEX and format      glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices);      // Set the texture matrix value and format of the attribute ATTRIB_TEXTURE      glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);      // Enable the ATTRIB_VERTEX attribute data, the default is off      glEnableVertexAttribArray(ATTRIB_VERTEX);      // Enable the ATTRIB_TEXTURE attribute data, the default is off      glEnableVertexAttribArray(ATTRIB_TEXTURE);        impl->mTexture->create();        impl->mTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);      impl->mTexture->setWrapMode(QOpenGLTexture::ClampToEdge);        glClearColor (1.0f, 0.0f, 1.0f, 1.0f); // set the background color  }    void OpenGLDisplayRGB::resizeGL(int w, int h)  {      if(h == 0)// prevents being divided by zero          h = 1;// set the height to 1        // Set the viewport      glViewport(0, 0, w, h);  }    void OpenGLDisplayRGB::paintGL()  {      if (!impl->mEnabled || !impl->mBufRGB)          return; //RET        // Load y data texture      // Activate the texture unit GL_TEXTURE0      glActiveTexture(GL_TEXTURE0);      // Use the texture generated from y to generate texture      glBindTexture(GL_TEXTURE_2D, impl->mTexture->textureId());        // Use the memory mBufYuv data to create a real y data texture      glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, impl->mVideoW, impl->mVideoH, 0, GL_RGBA, GL_UNSIGNED_BYTE, impl->mBufRGB);      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);        // Specify y texture to use the new value can only use 0, 1, 2, etc. to represent      // the index of the texture unit, this is the place where opengl is not humanized      //0 corresponds to the texture unit GL_TEXTURE0 1 corresponds to the      // texture unit GL_TEXTURE1 2 corresponds to the texture unit GL_TEXTURE2      glUniform1i(impl->mTextureUniform, 0);      // Use the vertex array way to draw graphics      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  }      void OpenGLDisplayRGB::closeEvent(QCloseEvent *e)  {      emit closed();      e->accept();  }  


varying vec2 vTextureCoord;  uniform sampler2D uSampler;    void main(void)  {      gl_FragColor = texture2D(uSampler, vTextureCoord);  }  


attribute vec4 vertexIn;  attribute vec2 textureIn;  varying vec2 vTextureCoord;    void main(void)  {      gl_Position = vertexIn;      vTextureCoord = textureIn;  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »