0

我正在尝试在 C++ 中将相机 nv12 缓冲区渲染到 OpenGL ES 表面,这是输出。 在此处输入图像描述

让我们看看我的着色器:

const char gVertexShader[] =
    "#version 320 es\n"
    "layout (location = 0) in vec4 vertex;\n"
    "out vec2 TexCoords;\n"
    "uniform mat4 projection;\n"
    "void main() {\n"
    "  gl_Position = projection * vec4(vertex.xy, 1.0, 1.0);\n"
    "  TexCoords = vertex.zw;\n"
    "}\n";

const char gFragmentNV12ToRGB[] =
    "#version 320 es\n"
    "precision highp float;\n"
    "in vec2 TexCoords;\n"
    "out vec4 color;\n"
    "uniform sampler2D text;\n"
    "uniform sampler2D textUV;\n"
    "void main (void) {\n"
    "float r, g, b, y, u, v;\n"
    "y = texture(text, TexCoords).r;\n"
    "u = texture(textUV, TexCoords).r - 0.5;\n"
    "v = texture(textUV, TexCoords).a - 0.5;\n"
    "r = y + 1.13983*v;\n"
    "g = y - 0.39465*u - 0.58060*v;\n"
    "b = y + 2.03211*u;\n"
    "color = vec4(r, g, b, 1.0);\n"
    "}\n";

这是代码,首先我创建一个带有 NULL 数据的 cameraTexture 然后每 10 毫秒刷新一次显示

void Camera::createCameraTexture(const int width, const int height)
{
    if (cameraTexId == 0)
    {
        GLuint idTex;
        glGenTextures(1, &idTex);
        glBindTexture(GL_TEXTURE_2D, idTex);

        glPixelStorei(GL_UNPACK_ALIGNMENT, 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);
        glTexImage2D(GL_TEXTURE_2D, GL_ZERO, GL_BGRA_EXT, width, height, GL_ZERO, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
        glBindTexture(GL_TEXTURE_2D, GL_ZERO);

        cameraTexId = idTex;
    }
}

void Camera::refreshCamera()
{
    GLfloat xpos = 0;
    GLfloat ypos = 0;

    GLfloat w = mSurfaceWidth;
    GLfloat h = mSurfaceHeight;

    GLfloat vertices[6][4] = {
        {xpos, ypos + h, 0.0, 0.0},
        {xpos, ypos, 0.0, 1.0},
        {xpos + w, ypos, 1.0, 1.0},

        {xpos, ypos + h, 0.0, 0.0},
        {xpos + w, ypos, 1.0, 1.0},
        {xpos + w, ypos + h, 1.0, 0.0}};

    glBindTexture(GL_TEXTURE_2D, cameraTexId);
    glUniform1i(mTextShaderHandle, GL_ZERO);
    glBindVertexArray(VAO);

    glActiveTexture(GL_TEXTURE0);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glTexSubImage2D(GL_TEXTURE_2D, GL_ZERO, GL_ZERO, GL_ZERO, mVideoCapture.getWidth(),
                    mVideoCapture.getHeight(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, mVideoCapture.getRawBufferCamera());
    glBufferSubData(GL_ARRAY_BUFFER, GL_ZERO, sizeof(vertices), vertices);

    glDrawArrays(GL_TRIANGLES, GL_ZERO, 6);

    //end
    glBindTexture(GL_TEXTURE_2D, GL_ZERO);
    glBindBuffer(GL_ARRAY_BUFFER, GL_ZERO);
}

我认为我必须通过另一个带有 UV 缓冲区的缓冲区,但我知道缓冲区 Y 和 UV 是相同的。

请有人告诉我实现这一目标的正确方法是什么?

谢谢你的帮助。

4

1 回答 1

0

您需要将 yuv 颜色缓冲区重新打包为 rgb 结构:

看这里:

将 YV12 转换为 NV21 (YUV YCrCb 4:2:0)

于 2020-12-16T16:36:23.183 回答