YUV到RGB的转换和显示使用opengl es 2.0从android ndk使用着色器

YUV到RGB的转换和显示使用opengl es 2.0从android ndk使用着色器,android,c,opengl-es,android-ndk,Android,C,Opengl Es,Android Ndk,我目前正在android上开发一个rtsp播放器,使用ffmpeg连接和解码视频流。我想使用OpenGL es 2.0将YUV帧转换为RGB帧并显示它,但我被阻止(这是我第一次使用OpenGL) 我会尽量解释清楚我的问题是什么 从NDK android,我使用以下方法初始化opengl上下文(从我要用于显示图像的线程): // EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_RENDER

我目前正在android上开发一个rtsp播放器,使用ffmpeg连接和解码视频流。我想使用OpenGL es 2.0将YUV帧转换为RGB帧并显示它,但我被阻止(这是我第一次使用OpenGL)

我会尽量解释清楚我的问题是什么

从NDK android,我使用以下方法初始化opengl上下文(从我要用于显示图像的线程):

    //
EGLint attribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE
};
EGLint contextAttrs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
};

LOGI("Initializing context");

if((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY)
{
    closeContext();
    return;
}

if(!eglInitialize(display, 0, 0))
{
    closeContext();
    return;
}

if(!eglChooseConfig(display, attribs, &config, 1, &numConfigs))
{
    closeContext();
    return;
}

if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format))
{
    closeContext();
    return;
}

ANativeWindow_setBuffersGeometry(window, 0, 0, format);

if(!(surface = eglCreateWindowSurface(display, config, window, 0)))
{
    closeContext();
    return;
}

if(!(context = eglCreateContext(display, config, 0, contextAttrs)))
{
    closeContext();
    return;
}

if(!eglMakeCurrent(display, surface, surface, context))
{
    closeContext();
    return;
}

if(!eglQuerySurface(display, surface, EGL_WIDTH, &width) || !eglQuerySurface(display, surface, EGL_HEIGHT, &height))
{
    closeContext();
    return;
}

LOGI("EGLWIDTH : %d EGLHEIGHT : %d ", (int)width, (int)height);

isInitEGLContext = 1;
    //
//Load Vertex and Fragment Shader, attach shader and link program
 programId = createProgram(kVertexShader, kFragmentShader);
 LOGI("Program id : %d error :  %d",(int) programId, glGetError());


if(!programId)
{
    LOGI("Could not create program");
    return;
}
// get index of the generic vertex attribute bound to vPosition
positionObject = (int) glGetAttribLocation(programId, "vPosition");

 // get index of the generic vertex attribute bound to vTexCoord
texturePosition = (int) glGetAttribLocation(programId, "vTexCoord");

// get the location of yTexture within the program (corresponding to   program id)
yuv_texture_object[0] = glGetUniformLocation(programId, "yTexture");

// get the location of uTexture within the program
yuv_texture_object[1] = glGetUniformLocation(programId, "uTexture");

// get the location of vTexture within the program
yuv_texture_object[2] = glGetUniformLocation(programId, "vTexture");

// Setup width of each planes (display size)
stream_yuv_width[0] = 800;
stream_yuv_width[1] = 400;
stream_yuv_width[2] = 400;

// Setup height of each planes (display size)
stream_yuv_height[0] = 600;
stream_yuv_height[1] = 300;
stream_yuv_height[2] = 300;

//set the view port
glViewport(0,0,stream_yuv_width[0],stream_yuv_height[0]);
LOGI("glViewPort() %d ", glGetError());
void drawFrame()
{
LOGI("DrawFrame");
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);
printGLError("glBindFramebuffer");
glUseProgram(programId);
printGLError("glUseProgram");
int i = 0;
for(i = 0 ; i < 3 ; ++i)
{
    glActiveTexture(GL_TEXTURE0 + i);
    printGLError("glActiveTexture");

    glBindTexture(GL_TEXTURE_2D, yuv_texture_object[i]);
    printGLError("glBindTexture");

    glUniform1i(yuv_texture_object[i], i);
    printGLError("glUniform1i");            
    LOGI("Plan : %d Largeur : %d Hauteur : %d ", i, yuv_width[i], yuv_height[i]);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,yuv_width[i], yuv_height[i], GL_LUMINANCE, GL_UNSIGNED_BYTE, yuv_planes[i]);
            printGLError("glTexSubImage2D");

    }

    glVertexAttribPointer(positionObject, 2, GL_FLOAT, GL_FALSE, kStride, kVertexInformation);
    printGLError("glVertexAttribPointer");

    glVertexAttribPointer(texturePosition, 2, GL_SHORT, GL_FALSE, kStride, kTextureCoordinateInformation);
    printGLError("glVertexAttribPointer");

    glEnableVertexAttribArray(positionObject);      
    printGLError("glVertexAttribArray");

    glEnableVertexAttribArray(texturePosition);
    printGLError("glVertexAttribArray");

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    printGLError("glBindFramebuffer");

    glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_SHORT, kIndicesInformation);
    printGLError("glDrawElements");

    eglSwapBuffers(display, surface);
    printGLError("eglSwapBuffers");

}
然后,我使用以下方法设置图形:

    //
EGLint attribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE
};
EGLint contextAttrs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
};

LOGI("Initializing context");

if((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY)
{
    closeContext();
    return;
}

if(!eglInitialize(display, 0, 0))
{
    closeContext();
    return;
}

if(!eglChooseConfig(display, attribs, &config, 1, &numConfigs))
{
    closeContext();
    return;
}

if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format))
{
    closeContext();
    return;
}

ANativeWindow_setBuffersGeometry(window, 0, 0, format);

if(!(surface = eglCreateWindowSurface(display, config, window, 0)))
{
    closeContext();
    return;
}

if(!(context = eglCreateContext(display, config, 0, contextAttrs)))
{
    closeContext();
    return;
}

if(!eglMakeCurrent(display, surface, surface, context))
{
    closeContext();
    return;
}

if(!eglQuerySurface(display, surface, EGL_WIDTH, &width) || !eglQuerySurface(display, surface, EGL_HEIGHT, &height))
{
    closeContext();
    return;
}

LOGI("EGLWIDTH : %d EGLHEIGHT : %d ", (int)width, (int)height);

isInitEGLContext = 1;
    //
//Load Vertex and Fragment Shader, attach shader and link program
 programId = createProgram(kVertexShader, kFragmentShader);
 LOGI("Program id : %d error :  %d",(int) programId, glGetError());


if(!programId)
{
    LOGI("Could not create program");
    return;
}
// get index of the generic vertex attribute bound to vPosition
positionObject = (int) glGetAttribLocation(programId, "vPosition");

 // get index of the generic vertex attribute bound to vTexCoord
texturePosition = (int) glGetAttribLocation(programId, "vTexCoord");

// get the location of yTexture within the program (corresponding to   program id)
yuv_texture_object[0] = glGetUniformLocation(programId, "yTexture");

// get the location of uTexture within the program
yuv_texture_object[1] = glGetUniformLocation(programId, "uTexture");

// get the location of vTexture within the program
yuv_texture_object[2] = glGetUniformLocation(programId, "vTexture");

// Setup width of each planes (display size)
stream_yuv_width[0] = 800;
stream_yuv_width[1] = 400;
stream_yuv_width[2] = 400;

// Setup height of each planes (display size)
stream_yuv_height[0] = 600;
stream_yuv_height[1] = 300;
stream_yuv_height[2] = 300;

//set the view port
glViewport(0,0,stream_yuv_width[0],stream_yuv_height[0]);
LOGI("glViewPort() %d ", glGetError());
void drawFrame()
{
LOGI("DrawFrame");
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);
printGLError("glBindFramebuffer");
glUseProgram(programId);
printGLError("glUseProgram");
int i = 0;
for(i = 0 ; i < 3 ; ++i)
{
    glActiveTexture(GL_TEXTURE0 + i);
    printGLError("glActiveTexture");

    glBindTexture(GL_TEXTURE_2D, yuv_texture_object[i]);
    printGLError("glBindTexture");

    glUniform1i(yuv_texture_object[i], i);
    printGLError("glUniform1i");            
    LOGI("Plan : %d Largeur : %d Hauteur : %d ", i, yuv_width[i], yuv_height[i]);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,yuv_width[i], yuv_height[i], GL_LUMINANCE, GL_UNSIGNED_BYTE, yuv_planes[i]);
            printGLError("glTexSubImage2D");

    }

    glVertexAttribPointer(positionObject, 2, GL_FLOAT, GL_FALSE, kStride, kVertexInformation);
    printGLError("glVertexAttribPointer");

    glVertexAttribPointer(texturePosition, 2, GL_SHORT, GL_FALSE, kStride, kTextureCoordinateInformation);
    printGLError("glVertexAttribPointer");

    glEnableVertexAttribArray(positionObject);      
    printGLError("glVertexAttribArray");

    glEnableVertexAttribArray(texturePosition);
    printGLError("glVertexAttribArray");

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    printGLError("glBindFramebuffer");

    glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_SHORT, kIndicesInformation);
    printGLError("glDrawElements");

    eglSwapBuffers(display, surface);
    printGLError("eglSwapBuffers");

}
我已经硬编码了显示器的大小(现在),直到我得到了一些工作

使用createProgram方法,加载着色器,创建程序,成功编译和链接着色器

以下是我的着色器:

const char kVertexShader[] =
"attribute vec4 vPosition;\n"
"attribute vec2 vTexCoord;\n"
"varying vec2 v_vTexCoord;\n"
"void main() {\n"
"gl_Position = vPosition;\n"
"v_vTexCoord = vTexCoord;\n"
"}\n";

const char kFragmentShader[] =
"precision mediump float; \n"
"varying vec2 v_vTexCoord;\n"
"uniform sampler2D yTexture;\n"
"uniform sampler2D uTexture;\n"
"uniform sampler2D vTexture;\n"
"void main() {\n"
"float nx, ny; \n"
"nx = v_vTexCoord.x; \n"
"ny = v_vTexCoord.y; \n"
"float y=texture2D(yTexture, v_vTexCoord).r;\n"
"float u=texture2D(uTexture, vec2(nx / 2.0, ny / 2.0)).r;\n"
"float v=texture2D(vTexture, vec2(nx / 2.0, ny / 2.0)).r;\n"
"y = 1.1643 * (y - 0.0625);\n"
"u = u - 0.5; \n"
"v = v - 0.5; \n"
"float r=y + 1.5958 * v;\n"
"float g=y - 0.39173 * u - 0.81290 * v;\n"
"float b=y + 2.017 * u;\n"
"gl_FragColor = vec4(r, g, b, 1.0);\n"
"}\n";

const GLfloat kVertexInformation[] = {
    -1.0f, 1.0f,           // TexCoord 0 top left
    -1.0f,-1.0f,           // TexCoord 1 bottom left
    1.0f,-1.0f,           // TexCoord 2 bottom right
    1.0f, 1.0f            // TexCoord 3 top right
};
const GLshort kTextureCoordinateInformation[] = {
    0, 0,         // TexCoord 0 top left
    0, 1,         // TexCoord 1 bottom left
    1, 1,         // TexCoord 2 bottom right
    1, 0          // TexCoord 3 top right  
};
const GLuint kStride = 0;//COORDS_PER_VERTEX * 4;
const GLshort kIndicesInformation[] = {
    0, 1, 2,
    0, 2, 3
};
然后我设置yuv纹理和渲染到纹理,此时yuv_宽度[i]和yuv_高度[i]设置为正确值:

void setupYUVTexture()
{
//Setup the pixel alignement
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
LOGI("glPixelStorei() : %d ", glGetError());
int i = 0;

for(i = 0 ; i < 3 ; ++i)
{
    //Check if the texture already setup
    if(yuv_texture_id[i] != 0)
    {
        glDeleteTextures(1, &yuv_texture_id[i]);
        yuv_texture_id[i] = 0;
    }
    // Active the i texture
    glActiveTexture(GL_TEXTURE0 + i);

    //Generate the texture name
    glGenTextures(1, &yuv_texture_id[i]);

    // Bind the texture
    glBindTexture(GL_TEXTURE_2D, yuv_texture_id[i]);

   // Setup the texture parameters
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);   
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);


    //Define the texture image
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, yuv_width[i], yuv_height[i], 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
    LOGI("glTexImage2D() %d ", glGetError());
}
}

void renderToTexture()
{
 // Generate framebuffer object name
    glGenFramebuffers(1, &frameBufferObject);
    //Bind the framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);


    //Generate render buffer object name
    glGenRenderbuffers(1, &renderBufferObject);

    //Bind render buffer
    glBindRenderbuffer(GL_RENDERBUFFER, renderBufferObject);

   //Create and initialize render buffer for display RGBA with the same size of the viewport
    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 800, 600);

    //Attach render buffer to frame buffer object
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBufferObject);

    //Attach y plane to frame buffer object
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yuv_texture_id[0], 0);

   //Attach u plane to frame buffer object
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yuv_texture_id[1], 0);

     //Attach v plane to frame buffer object
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, yuv_texture_id[2], 0);

    // Bind the framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    //Check if the framebuffer is correctly setup
    GLint status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    if(status != GL_FRAMEBUFFER_COMPLETE)
    {
        LOGI(" FBO setting fault : %d ", status);
        return;
    }
}
void setupYUVTexture()
{
//设置像素对齐
glPixelStorei(GLU解包对齐,1);
LOGI(“glPixelStorei():%d”,glGetError());
int i=0;
对于(i=0;i<3;++i)
{
//检查纹理是否已设置
if(yuv_纹理_id[i]!=0)
{
glDeleteTextures(1,&yuv_texture_id[i]);
yuv_纹理_id[i]=0;
}
//激活i纹理
玻璃结构(GL_纹理0+i);
//生成纹理名称
glGenTextures(1,&yuv_-texture_-id[i]);
//绑定纹理
glBindTexture(GL_TEXTURE_2D,yuv_TEXTURE_id[i]);
//设置纹理参数
glTexParameteri(GL\u纹理\u 2D,GL\u纹理\u最小\u过滤器,GL\u最近);
glTexParameteri(GL_纹理2D,GL_纹理MAG_过滤器,GL_最近);
glTexParameterf(GL_纹理2D、GL_纹理包裹、GL_夹紧到边);
glTexParameterf(GL_纹理2D、GL_纹理包裹、GL_夹紧到边);
//定义纹理图像
GLTEXAGE2D(GL_纹理_2D,0,GL_亮度,yuv_宽度[i],yuv_高度[i],0,GL_亮度,GL_无符号字节,NULL);
LOGI(“glTexImage2D()%d”,glGetError());
}
}
void renderToTexture()
{
//生成帧缓冲区对象名
glGenFramebuffers(1和frameBufferObject);
//绑定帧缓冲区
glBindFramebuffer(GL_FRAMEBUFFER,frameBufferObject);
//生成渲染缓冲区对象名称
glGenRenderbuffers(1,&renderBufferObject);
//绑定渲染缓冲区
glBindRenderbuffer(GL_RENDERBUFFER,renderBufferObject);
//为具有相同视口大小的显示RGBA创建并初始化渲染缓冲区
GLRENDERBUFFER存储(GLRENDERBUFFER,GLRENDERBUFFER RGBA4,800600);
//将渲染缓冲区附加到帧缓冲区对象
glFramebufferRenderbuffer(GL_帧缓冲区、GL_颜色附件0、GL_RENDERBUFFER、renderBufferObject);
//将y平面附着到帧缓冲区对象
glFramebufferTexture2D(GL_帧缓冲区、GL_颜色_附件0、GL_纹理_2D、yuv_纹理_id[0],0);
//将u平面附着到帧缓冲区对象
glFramebufferTexture2D(GL_帧缓冲区、GL_颜色_附件0、GL_纹理_2D、yuv_纹理_id[1],0);
//将v平面附着到帧缓冲区对象
glFramebufferTexture2D(GL_帧缓冲区、GL_颜色_附件0、GL_纹理_2D、yuv_纹理_id[2],0);
//绑定帧缓冲区
glBindFramebuffer(GL_帧缓冲区,0);
//检查帧缓冲区的设置是否正确
闪烁状态=glCheckFramebufferStatus(GLU帧缓冲区);
如果(状态!=GL\U帧缓冲区\U完成)
{
LOGI(“FBO设置故障:%d”,状态);
返回;
}
}
要完成此操作,请使用我的画框方法:

    //
EGLint attribs[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE
};
EGLint contextAttrs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 2,
        EGL_NONE
};

LOGI("Initializing context");

if((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY)
{
    closeContext();
    return;
}

if(!eglInitialize(display, 0, 0))
{
    closeContext();
    return;
}

if(!eglChooseConfig(display, attribs, &config, 1, &numConfigs))
{
    closeContext();
    return;
}

if(!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format))
{
    closeContext();
    return;
}

ANativeWindow_setBuffersGeometry(window, 0, 0, format);

if(!(surface = eglCreateWindowSurface(display, config, window, 0)))
{
    closeContext();
    return;
}

if(!(context = eglCreateContext(display, config, 0, contextAttrs)))
{
    closeContext();
    return;
}

if(!eglMakeCurrent(display, surface, surface, context))
{
    closeContext();
    return;
}

if(!eglQuerySurface(display, surface, EGL_WIDTH, &width) || !eglQuerySurface(display, surface, EGL_HEIGHT, &height))
{
    closeContext();
    return;
}

LOGI("EGLWIDTH : %d EGLHEIGHT : %d ", (int)width, (int)height);

isInitEGLContext = 1;
    //
//Load Vertex and Fragment Shader, attach shader and link program
 programId = createProgram(kVertexShader, kFragmentShader);
 LOGI("Program id : %d error :  %d",(int) programId, glGetError());


if(!programId)
{
    LOGI("Could not create program");
    return;
}
// get index of the generic vertex attribute bound to vPosition
positionObject = (int) glGetAttribLocation(programId, "vPosition");

 // get index of the generic vertex attribute bound to vTexCoord
texturePosition = (int) glGetAttribLocation(programId, "vTexCoord");

// get the location of yTexture within the program (corresponding to   program id)
yuv_texture_object[0] = glGetUniformLocation(programId, "yTexture");

// get the location of uTexture within the program
yuv_texture_object[1] = glGetUniformLocation(programId, "uTexture");

// get the location of vTexture within the program
yuv_texture_object[2] = glGetUniformLocation(programId, "vTexture");

// Setup width of each planes (display size)
stream_yuv_width[0] = 800;
stream_yuv_width[1] = 400;
stream_yuv_width[2] = 400;

// Setup height of each planes (display size)
stream_yuv_height[0] = 600;
stream_yuv_height[1] = 300;
stream_yuv_height[2] = 300;

//set the view port
glViewport(0,0,stream_yuv_width[0],stream_yuv_height[0]);
LOGI("glViewPort() %d ", glGetError());
void drawFrame()
{
LOGI("DrawFrame");
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferObject);
printGLError("glBindFramebuffer");
glUseProgram(programId);
printGLError("glUseProgram");
int i = 0;
for(i = 0 ; i < 3 ; ++i)
{
    glActiveTexture(GL_TEXTURE0 + i);
    printGLError("glActiveTexture");

    glBindTexture(GL_TEXTURE_2D, yuv_texture_object[i]);
    printGLError("glBindTexture");

    glUniform1i(yuv_texture_object[i], i);
    printGLError("glUniform1i");            
    LOGI("Plan : %d Largeur : %d Hauteur : %d ", i, yuv_width[i], yuv_height[i]);
    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,yuv_width[i], yuv_height[i], GL_LUMINANCE, GL_UNSIGNED_BYTE, yuv_planes[i]);
            printGLError("glTexSubImage2D");

    }

    glVertexAttribPointer(positionObject, 2, GL_FLOAT, GL_FALSE, kStride, kVertexInformation);
    printGLError("glVertexAttribPointer");

    glVertexAttribPointer(texturePosition, 2, GL_SHORT, GL_FALSE, kStride, kTextureCoordinateInformation);
    printGLError("glVertexAttribPointer");

    glEnableVertexAttribArray(positionObject);      
    printGLError("glVertexAttribArray");

    glEnableVertexAttribArray(texturePosition);
    printGLError("glVertexAttribArray");

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    printGLError("glBindFramebuffer");

    glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_SHORT, kIndicesInformation);
    printGLError("glDrawElements");

    eglSwapBuffers(display, surface);
    printGLError("eglSwapBuffers");

}
void drawFrame()
{
罗吉(“拉丝架”);
glBindFramebuffer(GL_FRAMEBUFFER,frameBufferObject);
PrintgError(“glBindFramebuffer”);
glUseProgram(programmaid);
打印错误(“glUseProgram”);
int i=0;
对于(i=0;i<3;++i)
{
玻璃结构(GL_纹理0+i);
PrintgleError(“glActiveTexture”);
glBindTexture(GL_纹理_2D,yuv_纹理_对象[i]);
打印错误(“glBindTexture”);
glUniform1i(yuv_纹理_对象[i],i);
打印错误(“glUniform1i”);
逻辑(“平面:%d大:%d高:%d”,i,宽度[i],高度[i]);
glTexSubImage2D(GL_纹理_2D,0,0,yuv_宽度[i],yuv_高度[i],GL_亮度,GL_无符号字节,yuv_平面[i]);
打印错误(“glTexSubImage2D”);
}
GLVertexAttribute指针(positionObject,2,GL_FLOAT,GL_FALSE,kStride,kVertexInformation);
PrintgError(“GLVertexAttribute指针”);
glvertexattributepointer(texturePosition,2,GL_SHORT,GL_FALSE,kStride,kTextureCoordinateInformation);
PrintgError(“GLVertexAttribute指针”);
GlenableVertexAttribute数组(positionObject);
PrintgError(“GLVertexAttributeArray”);
GlenableVertexAttributeArray(纹理定位);
PrintgError(“GLVertexAttributeArray”);
glBindFramebuffer(GL_帧缓冲区,0);
PrintgError(“glBindFramebuffer”);
GLD元件(GLU三角形带,6,GLU无符号短,种类信息);
打印错误(“打印元素”);
eglSwapBuffers(显示器,表面);
打印错误(“eglSwapBuffers”);
}
我初始化一次opengl纹理和其他必要的属性,然后在解码帧时,我将y缓冲区重新复制到
yuv\u平面[0]
、u缓冲区在
yuv\u平面[1]
和v缓冲区在
yuv\u平面[2]

使用ffmpeg正确解码帧后,我将按以下顺序调用:
-
initContext()

-
setupGraphics()

-
setupYUVTexture()

-
renderToTexture()

然后我调用
drawFrame
。当然,当一切都初始化时,我在每个解码帧之后直接调用drawFrame

这就是我现在的输出

图像的大小是正确的,但现在我在这里块。我不明白为什么图像显示是绿色的!
任何想法

都有很多代码需要处理,也有很多事情可能出错;)。要调试此类问题,我将一步一步地进行

  • 只需将红色(
    gl_FragColor=vec4(1.0,0.5,0.5,1.0)
    )输出到ma即可