Video rendering in OpenGL on Qt5
<p>I'm trying to render my decoded frame from FFMPEG to an QOpenGLWindow.
FFMPEG give me NV12 AVFrame or YUV420p or RGB. 
I choose the simplest RGB.</p>

<p>I created an c_gl_video_yuv class inherit from QOpenGLWindow and QOpenGLFunctions_3_3.</p>

<p>I want to use shader to draw my rectangle and texture it with the video frame. (for YUV I want the sader to convert it in RGB and apply texture)</p>

<p>my c_gl_video_yuv class is define as below :</p>

<pre><code>class c_gl_video_yuv : public QOpenGLWindow,protected QOpenGLFunctions_3_3_Core
{
public:
   c_gl_video_yuv();
   ~c_gl_video_yuv();
---
   void update_texture(AVFrame *frame, int w, int h);

protected:
   void initializeGL();
   void paintGL();
   void resizeGL(int width, int height);

   void paintEvent(QPaintEvent *);

private:

   ---
   GLuint textures[2];
   --- 
   // Shader program
   QOpenGLShaderProgram *m_program;

   GLint locVertices;
   GLint locTexcoord;

};
</code></pre>

<p>I initialise the OpenGL :</p>

<pre><code>   void c_gl_video_yuv::initializeGL()
    {
      // Init shader program
        initializeOpenGLFunctions();
        glGenTextures(2, textures);
        /* Apply some filter on the texture */
        glBindTexture(GL_TEXTURE_2D, textures[0]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);

        glBindTexture(GL_TEXTURE_2D, textures[1]);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_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);

        qDebug() &lt;&lt; "c_gl_video_yuv::initializeGL() initialise shader"&lt;&lt; endl;
        m_program = new QOpenGLShaderProgram(this);
        m_program-&gt;addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader/Ressources/vertex_yuv.glsl");
        m_program-&gt;addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shader/Ressources/rgb_to_rgb_shader .glsl");
        m_program-&gt;link();

    //    /* Grab location of shader attributes. */
        locVertices = m_program-&gt;attributeLocation("position");
        locTexcoord = m_program-&gt;attributeLocation("texpos");

        /* Enable vertex arrays to push the data. */
        glEnableVertexAttribArray(locVertices);
        glEnableVertexAttribArray(locTexcoord);

        /* set data in the arrays. */
            glVertexAttribPointer(locVertices, 2, GL_FLOAT, GL_FALSE, 0,
                          &amp;vertices[0][0]);
            glVertexAttribPointer(locTexcoord, 2, GL_FLOAT, GL_FALSE, 0,
                          &amp;texcoords[0][0]);

        // GL options
        glEnable(GL_DEPTH_TEST);    
    }
</code></pre>

<p>And I render </p>

<pre><code>void c_gl_video_yuv::paintGL()
    {

        qDebug() &lt;&lt;  "paintGL()   set viewport "&lt;&lt;endl;
        glViewport(0, 0, width(), height());
        /* Clear background. */
        glClearColor(0.5f,0.5f,0.5f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        if(first_frame)
        {
            qDebug() &lt;&lt;  "paintGL() Bind shader" &lt;&lt;  endl;
            m_program-&gt;bind();

            /* Get Ytex attribute to associate to TEXTURE0 */
                m_program-&gt;bindAttributeLocation("Ytex",0);
                m_program-&gt;bindAttributeLocation("UVtex",1);

                qDebug() &lt;&lt;  "paintGL() Bind texture" &lt;&lt;  endl;
            if(!is_init)
            {
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, textures[0]);
                glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, frame_width, frame_height, 0, GL_RGB, GL_UNSIGNED_BYTE, frame_yuv-&gt;data[0] );

                glActiveTexture(GL_TEXTURE1);
                glBindTexture(GL_TEXTURE_2D, textures[1]);
                glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, frame_width, frame_height, 0, GL_RGB, GL_UNSIGNED_BYTE, frame_yuv-&gt;data[0] );
                is_init = true;
            }
            else
            {
                glActiveTexture(GL_TEXTURE0);
                glBindTexture(GL_TEXTURE_2D, textures[0]);
               glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_BYTE, frame_yuv-&gt;data[0]);

               glActiveTexture(GL_TEXTURE1);
               glBindTexture(GL_TEXTURE_2D, textures[1]);
               glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, frame_width, frame_height, GL_RGB, GL_UNSIGNED_BYTE, frame_yuv-&gt;data[0]);
            }



            glVertexAttribPointer(locVertices, 2, GL_FLOAT, GL_FALSE, 0, vertices);
            glVertexAttribPointer(locTexcoord, 2, GL_FLOAT, GL_FALSE, 0, texcoords);

            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);

            glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

            glDisableVertexAttribArray(1);
            glDisableVertexAttribArray(0);
            m_program-&gt;release();
        }
    }
</code></pre>

<p>the vertex shader is :</p>

<pre><code> #version 330 core
    attribute vec3 position;
    attribute vec2 texpos;
    varying vec2 opos;
    void main(void)
    {
        opos = texpos;
        gl_Position = vec4(position, 1.0);
    }
</code></pre>

<p>and the Fragment shader is : </p>

<pre><code>version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D YImage;
uniform sampler2D UVImage;
const vec3 r_c = vec3(1.164383,  0.000000,  1.596027);
const vec3 g_c = vec3(1.164383, -0.391762, -0.812968);
const vec3 b_c = vec3(1.164383,  2.017232,  0.000000);
const vec3 offset = vec3(-0.0625, -0.5, -0.5);
void main()
{
   float y_val = texture(YImage, TexCoords).r;
   float u_val = texture(UVImage, TexCoords).r;
   float v_val = texture(UVImage, TexCoords).g;
   vec3 yuv = vec3(y_val, u_val, v_val);
   yuv += offset;
   color.r = dot(yuv, r_c);
   color.g = dot(yuv, g_c);
   color.b = dot(yuv, b_c);
   color.a = 1.0;
};
</code></pre>

<p>(for RGB frame a replace thevec3(1.164383,  0.000000,  1.596027); by vec3(1.0,  1.000000,  1.0);</p>

<p>So before i receive a frame it render nothing, just a grey window - noarmal
After I receive a frame, the textures are uploaded and the shaders normaly create the player. But nothing appear not even a black rectangle nothing, just plain grey.</p>

<p>What is wrong ?
It is not the right way to upload texture, or my vertex are not created ?
of course i declarde my vetrtices eand texture coordonate</p>

<pre><code>const GLfloat vertices[][2] = {
    {-1.f, -1.f},
    {1.f, -1.f},
    {-1.f, 1.f},
    {1.f, 1.f}
};
const GLfloat texcoords[][2] = {
    {0.0f, 1.0f},
    {1.0f, 1.0f},
    {0.0f, 0.0f},
    {1.0f, 0.0f}
};
</code></pre>

<p>I am very new to OpenGL so it is quite fuzzy in my head, but I thought it is not really hard to draw a rectangle with a streaming texture.
Maybe i should use vbo or fbo but I still don't really understand this.</p>

<p>If someone can help me, I will appreciate !
Thanks</p>