java - glTexImage2D 中的 ByteBuffer.wrap() 导致过多的垃圾收集

标签 java android opengl-es garbage-collection android-camera

我目前正在 android GLSurfaceView() 中进行以下 openGL 调用 onDrawFrame():

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, cameraTexture[0]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, camPreviewSize.width, camPreviewSize.height, 0, GLES20.GL_LUMINANCE,     GLES20.GL_UNSIGNED_BYTE, ByteBuffer.wrap(yArray));
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);

我需要在每一帧都执行此操作(或类似操作),因为我正在使用相机内的 android 的 setPreviewCallback() 功能使用自定义回调方法处理来自 android 相机预览的实时提要,但是我的垃圾收集变得非常疯狂(以下内容每秒重复大约 10 次!):

....

GC_FOR_ALLOC freed 1530K, 42% free 3671K/6307K, paused 18ms
GC_FOR_ALLOC freed 1530K, 42% free 3671K/6307K, paused 22ms
GC_FOR_ALLOC freed 1530K, 42% free 3671K/6307K, paused 25ms
GC_FOR_ALLOC freed 1530K, 42% free 3671K/6307K, paused 20ms
GC_FOR_ALLOC freed 1530K, 42% free 3671K/6307K, paused 20ms
GC_FOR_ALLOC freed 1530K, 42% free 3671K/6307K, paused 16ms
GC_FOR_ALLOC freed 1530K, 42% free 3671K/6307K, paused 22ms

....

yArray 是一个字节数组,我将它包装到一个缓冲区中。我已经使用 DDMS 完成了分析,实际上大部分分配都是字节数组,从我对 wrap 函数所做的阅读来看,它似乎可能会在调用 wrap 时创建一个底层字节 [],这将用作纹理后被GC回收。

我怎样才能减少分配的数量?我应该通过 GL 调用以某种方式改变吗?似乎我可以重新使用相同的字节数组,但我不确定如何。

任何帮助将不胜感激!这么多垃圾吓到我了!

最佳答案

有一个well documented android bug与导致过度垃圾收集的 setPreviewCallback() 方法有关。此问题的解决方案是使用较新的方法 setPreviewCallbackWithBuffer,您可以在其中预先分配一个缓冲区,使用 addCallbackBuffer 方法在每个帧上添加和重新添加该缓冲区:

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
...
  mCamera.addCallbackBuffer(callbackBuffer);
  mCamera.setPreviewCallbackWithBuffer(class that implements PreviewCallback);
...
}

并且在 onPreviewFrame 函数中必须再次添加缓冲区:

public void onPreviewFrame(byte[] yuvArray, Camera camera) {
...
  camera.addCallbackBuffer(callbackBuffer);
...
}

解决最初对 ByteBuffer.wrap() 正在 GL 调用中分配内存的怀疑:事实并非如此。它实际上会使用底层数组(提供的代码中的 yArray),并且不会分配新内存以进行垃圾回收。

关于java - glTexImage2D 中的 ByteBuffer.wrap() 导致过多的垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11406481/

相关文章:

java - BigQuery 性能和运行并发作业

安卓 : download content from URL which returns mp3 file

ios - 是否有常见 OpenGL 着色器的常用来源?

opengl-es - OpenGL ES 1.0 或 2.0

java - 使用图形 API 在 Facebook 群组上发布照片

iphone - 纹理图集应该具有的最大尺寸是多少?

java - @DirtiesContext 不适用于 Spring Boot 和 Kotlin

java - 在 websphere 中导致的日期格式问题

java - 使用反射收集类成员的信息

java - Android/Java - 带条件的递归扫描