我正在使用OpenGLES来渲染视频。解码的YUV420视频帧作为纹理映射到GLSurfaceView。 YUV420帧被正确解码。每当有可用的帧时,将调用drawFrame()并且应该渲染帧。 Howerver,视频帧根本没有出现,纹理一直是灰色的。我的opengl代码在这里:
static const char VERTEX_SHADER[] =
"varying vec2 interp_tc;\n"
"attribute vec4 in_pos;\n"
"attribute vec2 in_tc;\n"
"void main() {\n"
" gl_Position = in_pos;\n"
" interp_tc = in_tc;\n"
"}\n";
static const char FRAGMENT_SHADER[] =
"precision mediump float;\n"
"varying vec2 interp_tc;\n"
"uniform sampler2D y_tex;\n"
"uniform sampler2D u_tex;\n"
"uniform sampler2D v_tex;\n"
"void main() {\n"
" float y = 1.164 * (texture2D(y_tex, interp_tc).r - 0.0625);\n"
" float u = texture2D(u_tex, interp_tc).r - 0.5;\n"
" float v = texture2D(v_tex, interp_tc).r - 0.5;\n"
" gl_FragColor = vec4(y + 1.596 * v, "
" y - 0.391 * u - 0.813 * v, "
" y + 2.018 * u, "
" 1.0);\n"
"}\n";
const GLfloat TEXTURE_VERTICES[] = {
-1.0f, 1.0f,
-1.0f, -1.0f,
1.0f, 1.0f,
1.0f, -1.0f,};
const char* TEXTURE_UNIFORMS[] = {"y_tex", "u_tex", "v_tex"};
GLuint yuvTextures[3];
void addShader(int type, const char* source, int program) {
int result[1] = {GL_FALSE};
int shader = glCreateShader(type);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
GLint compiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
glAttachShader(program, shader);
glDeleteShader(shader);
}
bool GLRenderer::init()
{
EGLBoolean returnValue;
EGLint majorVersion;
EGLint minorVersion;
EGLConfig myConfig = {0};
EGLint numConfig = 0;
EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
EGLint s_configAttribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE };
const EGLint RGBA8888ConfigAttr[] = {
EGL_BUFFER_SIZE, 24,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
checkEglError("eglGetDisplay");
if (dpy == EGL_NO_DISPLAY) {
LOGI("eglGetDisplay returned EGL_NO_DISPLAY.\n");
return false;
}
returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
checkEglError("eglInitialize", returnValue);
if (returnValue != EGL_TRUE) {
LOGI("eglInitialize failed\n");
return false;
}
returnValue = eglChooseConfig(dpy, RGBA8888ConfigAttr, &myConfig, 1, &numConfig);
checkEglError("eglChooseConfig", returnValue);
if (returnValue != EGL_TRUE || numConfig != 1) {
LOGI("eglInitialize failed\n");
return false;
}
surface = eglCreateWindowSurface(dpy, myConfig, static_cast<EGLNativeWindowType>(_window), NULL);
checkEglError("eglCreateWindowSurface");
if (surface == EGL_NO_SURFACE) {
if(DEBUG) {
memset(tmp,0,sizeof(tmp));
sprintf(tmp,"eglCreateWindowSurface error! \n");
LogGL(tmp);
}
return false;
}
context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
checkEglError("eglCreateContext");
if (context == EGL_NO_CONTEXT) {
if(DEBUG) {
memset(tmp,0,sizeof(tmp));
sprintf(tmp,"eglCreateContext error \n");
LogGL(tmp);
}
return false;
}
returnValue = eglMakeCurrent(dpy, surface, surface, context);
checkEglError("eglMakeCurrent", returnValue);
if (returnValue != EGL_TRUE) {
return false;
}
eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
checkEglError("eglQuerySurface");
eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
checkEglError("eglQuerySurface");
if(!setupGraphics(w, h)) {
fprintf(stderr, "Could not set up graphics.\n");
return false;
}
if(!setupTextures()) {
fprintf(stderr, "Could not set up Textures.\n");
return false;
}
eglSwapInterval(dpy,0);
return true;
}
bool GLRenderer::setupGraphics(int w, int h) {
gProgram = glCreateProgram();
if (!gProgram) {
return false;
}
addShader(GL_VERTEX_SHADER, VERTEX_SHADER, gProgram);
addShader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER, gProgram);
glLinkProgram(gProgram);
GLint linkStatus = GL_FALSE;
glGetProgramiv(gProgram, GL_LINK_STATUS, &linkStatus);
if (linkStatus != GL_TRUE) {
if(DEBUG) {
memset(tmp,0,sizeof(tmp));
sprintf(tmp,"glGetProgramiv error \n");
LogGL(tmp);
}
}
glUseProgram(gProgram);
gvPositionHandle = glGetAttribLocation(gProgram, "in_pos");
glEnableVertexAttribArray(gvPositionHandle);
glVertexAttribPointer(
gvPositionHandle, 2, GL_FLOAT, false, 0, TEXTURE_VERTICES);
gYuvTexSamplerHandle = glGetAttribLocation(gProgram, "in_tc");
glEnableVertexAttribArray(gYuvTexSamplerHandle);
glViewport(0, 0, w, h);
checkGlError("glViewport");
return true;
}
bool GLRenderer::setupTextures() {
glGenTextures(3, yuvTextures);
for (int i = 0; i < 3; i++) {
glActiveTexture(GL_TEXTURE0 + i);
glUniform1i(glGetUniformLocation(gProgram, TEXTURE_UNIFORMS[i]), i);
glBindTexture(GL_TEXTURE_2D, yuvTextures[i]);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D,
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
//checkNoGLES2Error();
return true;
}
void GLRenderer::drawFrame(int YStride, int UVStride, int iWidth, int iHeight, const char* YData, const char* UData, const char* VData) {
glUseProgram(gProgram);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glUseProgram(gProgram);
int yuvStrides[3];
yuvStrides[0] = YStride;
yuvStrides[1] = UVStride;
yuvStrides[2] = UVStride;
float crop = (float) iWidth / yuvStrides[0];
GLfloat textureCoords[] = {
0.0f, 0.0f,
0.0f, 1.0f,
crop, 0.0f,
crop, 1.0f,};
glVertexAttribPointer(
gYuvTexSamplerHandle, 2, GL_FLOAT, false, 0, textureCoords);
glVertexAttribPointer(
gvPositionHandle, 2, GL_FLOAT, false, 0, TEXTURE_VERTICES);
glEnableVertexAttribArray(gvPositionHandle);
glEnableVertexAttribArray(gYuvTexSamplerHandle);
eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
checkEglError("eglQuerySurface");
eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
checkEglError("eglQuerySurface");
glViewport(0, 0, w, h);
char *yuvPlanes[3];
yuvPlanes[0] = (char *)YData;
yuvPlanes[1] = (char *)UData;
yuvPlanes[2] = (char *)VData;
for (int i = 0; i < 3; i++) {
int h = (i == 0) ? iHeight : (iHeight + 1) / 2;
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, yuvTextures[i]);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, yuvStrides[i],
h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yuvPlanes[i]);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
eglSwapBuffers(dpy, surface);
checkEglError("eglSwapBuffers");
}
答案 0 :(得分:0)
如果要渲染SurfaceTexture纹理,则应使用GL_TEXTURE_EXTERNAL_OES纹理目标和samplerExternalOES采样器。
如下所示:SurfaceTexture:
纹理对象使用GL_TEXTURE_EXTERNAL_OES纹理目标, 它由GL_OES_EGL_image_external OpenGL ES扩展定义。 这限制了纹理的使用方式。每次纹理都是 绑定它必须绑定到GL_TEXTURE_EXTERNAL_OES目标 比GL_TEXTURE_2D目标。此外,任何OpenGL ES 2.0着色器 纹理中的样本必须声明其使用此扩展名 例如,使用“#extension GL_OES_EGL_image_external: 要求“指令。这样的着色器也必须使用 samplerExternalOES GLSL采样器类型。
还有一件事 - 您还应该GL_TEXTURE_EXTERNAL_OES
使用glTexParameterf
。