Рендеринг YUV-видео на Android, текстуры не загружаются в текстурные блоки - PullRequest
1 голос
/ 01 ноября 2019

Я портировал рабочий код с C ++ на Java. В C ++ я использовал те же шейдеры, что и здесь, и тот же код, и я смог использовать 3 текстурных блока графического процессора для загрузки компонентов Y, U и V, а затем использовать texture() для соединения с ними. текстуры в буфер RGBA для визуализации.

Проблема в том, что в Android я вижу зеленый экран, который представляет собой цвет RGBA, который генерируется шейдером при пустых Y, U и V даны текстурные единицы. Таким образом, текстуры не загружаются. Я отключил все объекты в пиксельном буфере и попытался просто glTexImage2D с простым буфером, а также не увидел никаких изменений.

 public boolean renderYUV(DecodedFrame decodedFrame) throws Exception {
        GLES20.glEnableVertexAttribArray(vertexInLocation);
        GLES20.glEnableVertexAttribArray(textureInLocation);

        if (!initiatedTextures)
        {
            glGenTextures(TEXTURE_NUMBER, textureId);

            for (int i = 0; i < TEXTURE_NUMBER; i++)
            {
                glBindTexture(GL_TEXTURE_2D, textureId.get(i));
                glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBufferObjects.get(i));
                glBufferData(GL_PIXEL_UNPACK_BUFFER, decodedFrame.textureSize[i], null, GL_STREAM_DRAW);
                glTexImage2D(GL_TEXTURE_2D,
                            0,
                            GL_RED,
                            decodedFrame.width[i],
                            decodedFrame.height[i],
                            0,
                            GL_RED,
                            GL_UNSIGNED_BYTE,
                            null); //decodedFrame->buffer[i]);
                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);
            }
            initiatedTextures = true;
        }
        for (int j = 0; j < TEXTURE_NUMBER; j++)
        {
            glActiveTexture(GL_TEXTURE0 + j);
            glBindTexture(GL_TEXTURE_2D, textureId.get(j));
            glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBufferObjects.get(j));

            if (true)//todo: change to verify if buffer has contents
            {
                for (int i = 0; i <= decodedFrame.height[j] - 1; i++)
                {
                    int offset = i * decodedFrame.linesize[j];
                    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, offset, decodedFrame.width[j], decodedFrame.buffer[j]);
                }
                glTexSubImage2D(GL_TEXTURE_2D,
                        0,
                        0,
                        0,
                        decodedFrame.width[j],
                        decodedFrame.height[j],
                        GL_RED,
                        GL_UNSIGNED_BYTE,
                        null);
            }
            glUniform1i(textureLocation[j], j);
        }
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        return true;
    }

Вот шейдеры:

Vertex:

#version 320 es
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

Фрагмент:

#version 320 es

#ifdef GL_ES
precision mediump int;
precision mediump float;
#endif

uniform sampler2D tex_y;
uniform sampler2D tex_u;
uniform sampler2D tex_v;

in vec2 TexCoord;
out vec4 FragColor;

void main()
{
    vec3 yuv;
    vec4 rgba;
    yuv.r = texture(tex_y, TexCoord).r - 0.0625;
    yuv.g = texture(tex_u, TexCoord).r - 0.5;
    yuv.b = texture(tex_v, TexCoord).r - 0.5;

    rgba.r = yuv.r + 1.402 * yuv.b;
    rgba.g = yuv.r - 0.34413 * yuv.g - 0.71414 * yuv.b;
    rgba.b = yuv.r + 1.772 * yuv.g;
    FragColor = rgba;
}

Я проверил, что tex_y, tex_u и tex_v загружаются (работает glGetUniformLocation) и шейдеры компилируются без каких-либо проблем. Я также обмениваю FragColor = rgba на FragColor = vec4(1.0f, 0, 0, 1.0f) и говорю красное изображение, подтверждающее, что шейдер работает, единственная проблема - пустые текстуры. Так что я уверен, что проблема связана с заполнением текстур. Как вы можете видеть, glUniform1i(textureLocation[j], j); активирует Sampler2D для каждой унифицированной переменной, так что это тоже не проблема.

Может кто-то заметить что-то простое, что мне не хватает в Java, отличное от C ++?

Просто, чтобы добавить немного информации, вот мои вершины и координаты текстуры:

static float vertex[] = {
        -1.0f,  -1.0f, 0.0f, // top left
        1.0f, -1.0f, 0.0f,   // bottom left
        -1.0f, 1.0f, 0.0f,   // bottom right
        1.0f,  1.0f, 0.0f    // top right
}; 
static float fragment[] = {
        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f
};

//create vertexBuffer and fragmentBuffer from the arrays here

GLES20.glVertexAttribPointer(vertexInLocation, 3, GLES20.GL_FLOAT, false, 3*4, vertexBuffer);
GLES20.glEnableVertexAttribArray(vertexInLocation);
GLES20.glVertexAttribPointer(textureInLocation, 2, GLES20.GL_FLOAT, false, 2*4, fragmentBuffer);
GLES20.glEnableVertexAttribArray(textureInLocation);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...