Example #1
0
static void uploadTextures(QOpenGLContext* context, SharedFrame& frame, GLuint texture[])
{
    int width = frame.get_image_width();
    int height = frame.get_image_height();
    const uint8_t* image = frame.get_image();
    QOpenGLFunctions* f = context->functions();

    // Upload each plane of YUV to a texture.
    if (texture[0] && texture[1] && texture[2])
        f->glDeleteTextures(3, texture);
    check_error(f);
    f->glGenTextures(3, texture);
    check_error(f);
    f->glPixelStorei(GL_UNPACK_ROW_LENGTH, width);

    f->glBindTexture  (GL_TEXTURE_2D, texture[0]);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    check_error(f);
    f->glTexImage2D   (GL_TEXTURE_2D, 0, GL_RED, width, height, 0,
                    GL_RED, GL_UNSIGNED_BYTE, image);
    check_error(f);

    f->glBindTexture  (GL_TEXTURE_2D, texture[1]);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    check_error(f);
    int y = context->isOpenGLES() ? 2 : 4;
    f->glTexImage2D   (GL_TEXTURE_2D, 0, GL_RED, width/2, height/y, 0,
                    GL_RED, GL_UNSIGNED_BYTE, image + width * height);
    check_error(f);

    f->glBindTexture  (GL_TEXTURE_2D, texture[2]);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    check_error(f);
    f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    check_error(f);
    f->glTexImage2D   (GL_TEXTURE_2D, 0, GL_RED, width/2, height/y, 0,
                    GL_RED, GL_UNSIGNED_BYTE, image + width * height + width/2 * height/2);
    check_error(f);
}
Example #2
0
    void bind()
    {
        QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();

        QMutexLocker lock(&m_frameMutex);
        if (m_frame.isValid()) {
            if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
                QSize textureSize = m_frame.size();

                int stride = m_frame.bytesPerLine();
                switch (m_frame.pixelFormat()) {
                case QVideoFrame::Format_RGB565:
                    stride /= 2;
                    break;
                default:
                    stride /= 4;
                }

                m_width = qreal(m_frame.width()) / stride;
                textureSize.setWidth(stride);

                if (m_textureSize != textureSize) {
                    if (!m_textureSize.isEmpty())
                        functions->glDeleteTextures(1, &m_textureId);
                    functions->glGenTextures(1, &m_textureId);
                    m_textureSize = textureSize;
                }

                GLint dataType = GL_UNSIGNED_BYTE;
                GLint dataFormat = GL_RGBA;

                if (m_frame.pixelFormat() == QVideoFrame::Format_RGB565) {
                    dataType = GL_UNSIGNED_SHORT_5_6_5;
                    dataFormat = GL_RGB;
                }

                GLint previousAlignment;
                functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
                functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

                functions->glActiveTexture(GL_TEXTURE0);
                functions->glBindTexture(GL_TEXTURE_2D, m_textureId);
                functions->glTexImage2D(GL_TEXTURE_2D, 0, dataFormat,
                                        m_textureSize.width(), m_textureSize.height(),
                                        0, dataFormat, dataType, m_frame.bits());

                functions->glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment);

                functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
                functions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

                m_frame.unmap();
            }
            m_frame = QVideoFrame();
        } else {
            functions->glActiveTexture(GL_TEXTURE0);
            functions->glBindTexture(GL_TEXTURE_2D, m_textureId);
        }
    }
Example #3
0
void QSGVideoMaterial_YUV::bind()
{
    QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
    QMutexLocker lock(&m_frameMutex);
    if (m_frame.isValid()) {
        if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
            int fw = m_frame.width();
            int fh = m_frame.height();

            // Frame has changed size, recreate textures...
            if (m_textureSize != m_frame.size()) {
                if (!m_textureSize.isEmpty())
                    functions->glDeleteTextures(m_planeCount, m_textureIds);
                functions->glGenTextures(m_planeCount, m_textureIds);
                m_textureSize = m_frame.size();
            }

            GLint previousAlignment;
            functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &previousAlignment);
            functions->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

            if (m_format.pixelFormat() == QVideoFrame::Format_NV12
                    || m_format.pixelFormat() == QVideoFrame::Format_NV21) {
                const int y = 0;
                const int uv = 1;

                m_planeWidth[0] = m_planeWidth[1] = qreal(fw) / m_frame.bytesPerLine(y);

                functions->glActiveTexture(GL_TEXTURE1);
                bindTexture(m_textureIds[1], m_frame.bytesPerLine(uv) / 2, fh / 2, m_frame.bits(uv), GL_LUMINANCE_ALPHA);
                functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
                bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), GL_LUMINANCE);

            } else { // YUV420P || YV12
                const int y = 0;
                const int u = m_frame.pixelFormat() == QVideoFrame::Format_YUV420P ? 1 : 2;
                const int v = m_frame.pixelFormat() == QVideoFrame::Format_YUV420P ? 2 : 1;

                m_planeWidth[0] = qreal(fw) / m_frame.bytesPerLine(y);
                m_planeWidth[1] = m_planeWidth[2] = qreal(fw) / (2 * m_frame.bytesPerLine(u));

                functions->glActiveTexture(GL_TEXTURE1);
                bindTexture(m_textureIds[1], m_frame.bytesPerLine(u), fh / 2, m_frame.bits(u), GL_LUMINANCE);
                functions->glActiveTexture(GL_TEXTURE2);
                bindTexture(m_textureIds[2], m_frame.bytesPerLine(v), fh / 2, m_frame.bits(v), GL_LUMINANCE);
                functions->glActiveTexture(GL_TEXTURE0); // Finish with 0 as default texture unit
                bindTexture(m_textureIds[0], m_frame.bytesPerLine(y), fh, m_frame.bits(y), GL_LUMINANCE);
            }

            functions->glPixelStorei(GL_UNPACK_ALIGNMENT, previousAlignment);
            m_frame.unmap();
        }

        m_frame = QVideoFrame();
    } else {
        // Go backwards to finish with GL_TEXTURE0
        for (int i = m_planeCount - 1; i >= 0; --i) {
            functions->glActiveTexture(GL_TEXTURE0 + i);
            functions->glBindTexture(GL_TEXTURE_2D, m_textureIds[i]);
        }
    }
}