android使用GraphicBuffer在eglDestroyImageKHR上崩溃

时间:2014-02-19 20:06:12

标签: android opengl-es-2.0 stagefright

我正在使用以下代码将数据复制到GraphicBuffer:

uint8_t *ptr;
sp<GraphicBuffer> gBuffer = new GraphicBuffer(width,height,format,usage);
gBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&ptr));
//Copy Data
gBuffer->unlock();

EGLClient clientBuffer = (EGLClientBuffer)gBuffer->getNativeBuffer();

EGLImageKHR img = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,clientBuffer, NULL);

glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureHandle);
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)img);

//Finished using img, Crash Here:

eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), img);

问题来自调用eglDestroyImageKHR,它在某些设备中崩溃而其他一些设备没有崩溃。这是回溯:

00 pc 00006488 /system/lib/libui.so
01 pc 00006719 /system/lib/libui.so (android::GraphicBuffer::free_handle()+52)
02 pc 00006813 /system/lib/libui.so (android::GraphicBuffer::~GraphicBuffer()+22)
03 pc 00006841 /system/lib/libui.so (android::GraphicBuffer::~GraphicBuffer()+4)
04 pc 0000f823 /system/lib/libutils.so (android::RefBase::decStrong(void const*) const+40)
05 pc 00003bbb /system/vendor/lib/egl/eglsubAndroid.so
06 pc 0001b5f4 /system/vendor/lib/egl/libEGL_adreno.so (egliDoDestroyEGLImage+80)
07 pc 00006c88 /system/vendor/lib/egl/libEGL_adreno.so (eglDestroyImageKHR+16)
08 pc 0000e749 /system/lib/libEGL.so (eglDestroyImageKHR+44)

以下是一些完整的回溯:

http://pastebin.com/S0Ax6eNp

http://pastebin.com/bGWeWruw

不调用eglDestroyImageKHR会导致泄漏,当再次调用上述例程时,gbuffer-&gt; lock()会因内存不足错误消息而失败。

例如在星系S4,星系s2,xperia z1上坠毁,并且在连接4,连接7,星系王牌2等中不会崩溃

我将不胜感激。

-EDITED -

我找到的唯一解决方法是将引用计数器减少到0,以便调用GraphicBuffer析构函数并释放内存。

if(gBuffer->getStrongCount() > 0){
    gBuffer->decStrong(gBuffer->handle);
}

2 个答案:

答案 0 :(得分:2)

我对EGL曲面有同样的问题。由于4.3三星ROM在销毁任何一个时不会停用活动上下文和表面。代码现在看起来像这样:

// This line had to be added to prevent crashes:
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);

mEgl.eglDestroyContext(mEglDisplay, mEglContext);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);

堆栈跟踪看起来非常相似。你有没有尝试在调用eglDestroyImageKHR之前销毁gBuffer?

答案 1 :(得分:2)

FWIW,在Mozilla AndroidGraphicBuffer.cpp代码中,作者writes

/**
 * XXX: eglDestroyImageKHR crashes sometimes due to refcount badness (I think)
 *
 * If you look at egl.cpp (https://github.com/android/platform_frameworks_base/blob/master/opengl/libagl/egl.cpp#L2002)
 * you can see that eglCreateImageKHR just refs the native buffer, and eglDestroyImageKHR
 * just unrefs it. Somehow the ref count gets messed up and things are already destroyed
 * by the time eglDestroyImageKHR gets called. For now, at least, just not calling      
 * eglDestroyImageKHR should be fine since we do free the GraphicBuffer below.
 *
 * Bug 712716
 */

并且基本上不会调用eglDestroyImageKHR(),这在该上下文中显然是正常的。错误报告here。 James Willcox author of the Mozilla code也是the snorp blog post的作者。