使用 Android NDK 通过 openGLES2 渲染视频帧
Posted
技术标签:
【中文标题】使用 Android NDK 通过 openGLES2 渲染视频帧【英文标题】:Render video frame via openGLES2 with Android NDK 【发布时间】:2013-08-17 04:45:39 【问题描述】:我用 NDK 做了一个 bin 代码,通过 ffmpeg 解码获取视频帧,并渲染到 opengles,但屏幕没有任何变化,它仍然显示启动器。
*但是当我做一个apk来启动时,它总是显示黑色。*
我的opengles2.0 ini代码如下:
static int window_init_display(void)
EGLint attribs [] =
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 0,
EGL_SAMPLE_BUFFERS, 0,
EGL_SAMPLES, 0,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
;
EGLint w, h, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, 0, 0);
eglChooseConfig(display, attribs, &config, 1, &numConfigs);
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(g_application->window, 0, 0, format);
surface = eglCreateWindowSurface(display, config, g_application->window, NULL);
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
LOGI("EGL_WIDTH=%d, EGL_HEIGHT=%d",w,h);
eglBindAPI(EGL_OPENGL_ES_API);
EGLint contextAttrs[] =
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
;
context = eglCreateContext(display, config, NULL, contextAttrs);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE)
LOGW("Unable to eglMakeCurrent");
return -1;
LOGI("OK init EGL !!!!");
我的渲染代码如下:
int m_rgbBufferSize = pPicture->iDisplayWidth*pPicture->iDisplayHeight*4;
m_rgbBuffer = new unsigned char[m_rgbBufferSize];
struct SwsContext *m_sw_context=NULL;
m_sw_context = m_dllSwScale.sws_getCachedContext(m_sw_context,
pPicture->iWidth, pPicture->iHeight, PIX_FMT_YUV420P,
pPicture->iWidth, pPicture->iHeight, PIX_FMT_RGBA,
SWS_FAST_BILINEAR, NULL, NULL, NULL);
uint8_t *psrc[] = pPicture->data[0], pPicture->data[1], pPicture->data[2], 0 ;
int srcStride[] = pPicture->iLineSize[0], pPicture->iLineSize[1], pPicture->iLineSize[2], 0 ;
uint8_t *dst[] = m_rgbBuffer, 0, 0, 0 ;
int dstStride[] = pPicture->iDisplayWidth*4, 0, 0, 0 ;
m_dllSwScale.sws_scale(m_sw_context, psrc, srcStride, 0, pPicture->iDisplayHeight, dst, dstStride);
//LOGV("swscale OK");
glEnable(GL_TEXTURE_2D);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
if(textureid == 0)
glGenTextures(1, &textureid);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, textureid);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
pPicture->iDisplayWidth, pPicture->iDisplayHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_rgbBuffer);
为什么什么都没有显示?我应该使用 abk 而不是 bin 文件来运行吗?
【问题讨论】:
如果它仍在显示启动器,那么您的应用程序不在前台,并且窗口管理器不会让您的窗口可见。 那么如何让它到前台呢? 将您的程序编写为 android 应用程序,然后启动它。 我做了一个apk来启动,但它仍然没有显示。启动时它总是黑的。所以我弄错了吗? 【参考方案1】:Surface 默认对其他一些视图隐藏。检查您是否在表面上放置了一些视图。或在顶部设置surfaceZOrder。
【讨论】:
以上是关于使用 Android NDK 通过 openGLES2 渲染视频帧的主要内容,如果未能解决你的问题,请参考以下文章
Android NDK SDL2 OpenGL ES 2 阴影映射(定向)- 可能吗?
我的Android进阶之旅如何在NDK开发的时候定位Native层的内存泄漏?
我的Android进阶之旅如何在NDK开发的时候定位Native层的内存泄漏?