void exposeEvent(QExposeEvent *)
    {
        if (!isExposed())
            return;

        if (!gl) {
            gl = new QOpenGLContext();
            gl->setFormat(requestedFormat());
            gl->create();
        }

        gl->makeCurrent(this);

        QOpenGLShaderProgram prog;
        prog.addShaderFromSourceCode(QOpenGLShader::Vertex,
                                     "attribute highp vec4 a_Pos;"
                                     "attribute lowp vec4 a_Color;"
                                     "varying lowp vec4 v_Color;"
                                     "void main() {"
                                     "    gl_Position = a_Pos;"
                                     "    v_Color = a_Color;"
                                     "}");
        prog.addShaderFromSourceCode(QOpenGLShader::Fragment,
                                     "varying lowp vec4 v_Color;"
                                     "void main() {"
                                     "    gl_FragColor = v_Color;"
                                     "}");
        prog.bind();

        glClearColor(0, 0, 0, 1);
        glClear(GL_COLOR_BUFFER_BIT);
        glViewport(0, 0, width(), height());

        prog.enableAttributeArray("a_Pos");
        prog.enableAttributeArray("a_Color");

        float coords[] = { -0.7f,  0.7f,
                           0.8f,  0.8f,
                           -0.8f, -0.8f,
                           0.7f, -0.7f
                         };
        float colors[] = { 1, 0, 0, 1,
                           0, 1, 0, 1,
                           0, 0, 1, 1,
                           0, 0, 0, 0
                         };

        prog.setAttributeArray("a_Pos", GL_FLOAT, coords, 2, 0);
        prog.setAttributeArray("a_Color", GL_FLOAT, colors, 4, 0);

        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

        prog.disableAttributeArray("a_Pos");
        prog.disableAttributeArray("a_Color");

        gl->swapBuffers(this);
    }
Example #2
0
void VideoSurface::paintGL()
{
    mutex.lock();
    VideoFrame currFrame = frame;
    frame.invalidate();
    mutex.unlock();

    if (currFrame.isValid() && res != currFrame.resolution)
    {
        res = currFrame.resolution;

        // delete old texture
        if (textureId != 0)
            glDeleteTextures(1, &textureId);

        // a texture used to render the pbo (has the match the pixelformat of the source)
        glGenTextures(1,&textureId);
        glBindTexture(GL_TEXTURE_2D, textureId);
        glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, res.width(), res.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    }

    if (currFrame.isValid())
    {
        pboIndex = (pboIndex + 1) % 2;
        int nextPboIndex = (pboIndex + 1) % 2;

        if (pboAllocSize != currFrame.frameData.size())
        {
            qDebug() << "VideoSurface: Resize pbo " << currFrame.frameData.size() << "(" << currFrame.resolution << ")" << "bytes (before" << pboAllocSize << ")";

            pbo[0]->bind();
            pbo[0]->allocate(currFrame.frameData.size());
            pbo[0]->release();

            pbo[1]->bind();
            pbo[1]->allocate(currFrame.frameData.size());
            pbo[1]->release();

            pboAllocSize = currFrame.frameData.size();
        }


        pbo[pboIndex]->bind();
        glBindTexture(GL_TEXTURE_2D, textureId);
        glTexSubImage2D(GL_TEXTURE_2D,0,0,0, res.width(), res.height(), GL_RGB, GL_UNSIGNED_BYTE, 0);
        pbo[pboIndex]->unmap();
        pbo[pboIndex]->release();

        // transfer data
        pbo[nextPboIndex]->bind();
        void* ptr = pbo[nextPboIndex]->map(QOpenGLBuffer::WriteOnly);
        if (ptr)
            memcpy(ptr, currFrame.frameData.data(), currFrame.frameData.size());
        pbo[nextPboIndex]->unmap();
        pbo[nextPboIndex]->release();
    }

    // background
    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT);

    // keep aspect ratio
    float aspectRatio = float(res.width()) / float(res.height());
    if (width() < float(height()) * aspectRatio)
    {
        float h = float(width()) / aspectRatio;
        glViewport(0, (height() - h)*0.5f, width(), h);
    }
    else
    {
        float w = float(height()) * float(aspectRatio);
        glViewport((width() - w)*0.5f, 0, w, height());
    }

    QOpenGLShaderProgram* programm = nullptr;
    switch (frame.format)
    {
    case VideoFrame::YUV:
        programm = yuvProgramm;
        break;
    case VideoFrame::BGR:
        programm = bgrProgramm;
        break;
    default:
        break;
    }

    if (programm)
    {
        // render pbo
        static float values[] = {
            -1, -1,
            1, -1,
            -1, 1,
            1, 1
        };

        programm->bind();
        programm->setAttributeArray(0, GL_FLOAT, values, 2);
        programm->enableAttributeArray(0);
    }

    glBindTexture(GL_TEXTURE_2D, textureId);

    //draw fullscreen quad
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glBindTexture(GL_TEXTURE_2D, 0);

    if (programm)
    {
        programm->disableAttributeArray(0);
        programm->release();
    }
}