2012-07-10 2 views
1

의 원인이 OpenGL을)은 안드로이드 GLSurfaceView (에 onDrawFrame()를 호출하여 다음는 glTexImage2D에 ByteBuffer.wrap이() 나는 현재하고 있어요 과도한 가비지 컬렉션

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); 

내가이 일을 (또는 같은)가 필요합니다 카메라 안의 안드로이드의 setPreviewCallback() 기능을 사용하는 커스텀 콜백 메소드로 라이브 피드를 처리하고 있기 때문에 매 프레임마다 가비지 수집이 절대적으로 어려워졌습니다 (다음은 약 10x 초마다 반복됩니다) :

.... 

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를 사용하여 프로파일 링 작업을 수행했으며 실제로 할당의 대부분은 바이트 배열이며 랩 함수에서 수행 한 작업에서 랩핑 호출에서 기본 바이트 []를 생성하는 것처럼 보입니다. 그런 다음 텍스처로 사용 된 후에 GC로 수집됩니다.

어떻게 할당 수를 줄일 수 있습니까? GL 호출로 어떻게 변경해야합니까? 대신에 같은 바이트 배열을 재사용 할 수있는 것처럼 보이지만 방법이 확실하지 않습니다.

도움이 될 것입니다! 이 양의 쓰레기는 나를 겁나게합니다!

답변

4

과도한 가비지 수집을 초래하는 setPreviewCallback() 메서드와 관련된 well documented android bug이 있습니다. 버퍼가 다시 추가해야합니다 기능

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

과 onPreviewFrame에서이 문제에 대한 해결책은 당신이 추가되고 addCallbackBuffer 방법으로 모든 FRAM에 부가 다시 버퍼를 미리 할당 곳에 새로운 방법 setPreviewCallbackWithBuffer을 사용하는 것입니다 :

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

ByteBuffer.wrap()는 GL에서 메모리를 호출 할당되는 초기 의심을 해결하기 : 그렇지. 실제로는 기본 배열 (제공된 코드에서 yArray)을 사용하며 가비지 수집 할 새 메모리를 할당하지 않습니다.

+1

당신이 답을 찾았기로 기쁘다. 똑같은 크기/유형 텍스처를 매 프레임마다 새로 고치면 glTexImage2D 대신 glTexSubImage2D를 사용해도 좋을 것입니다. 더 나은 성능을 제공 할 수 있습니다. 여기를 참조하십시오 : http://www.opengl.org/wiki/Common_Mistakes#Updating_A_Texture – Tim

+0

그레이트! glTexSubImage2D를 사용하여 작업했습니다. glTexSubImage2D의 진정한 의도 된 사용법임을 깨닫지 못했습니다. 저를 계몽 해 주셔서 감사합니다. 나는 그것이 더 빠른 것을 만들고 있는지 확신하지 못한다. 그러나 가능한 한 많은 일반적인 오류를 피하고 싶다. :) –

0

모든 전화에 새로운 ByteBuffer 인스턴스가 생성됩니다.이 인스턴스는 즉시 가비지 수집됩니다. 데이터의 크기가 변경되고 텍스처 크기 차원 자체가 변경 될 때만 필요합니다. 나는 이것이 가능하지 않을 것이라고 생각합니다.

미리 할당하려면 ByteBuffer을 벌크 방식으로 업데이트하십시오.

+0

이 시도하고 버퍼 오버플로 오류가 발생했습니다. 배열을 사용하는 .put 메서드를 사용하는 것은 put 메서드에 입력됩니다. 나는 다시 시도하고, 그걸 알아 내려고, 너에게 돌아 가려고 노력할 것이다. 감사! –

+1

@ DanielSmith 배열을 다시 채우기 전에 buffer.position (0)을 설정해야합니다 (그렇지 않으면 끝에 추가됩니다). – Tim

+0

실제로 버퍼에 문제가 있었지만 위의 응답에서 볼 수 있듯이 실제로 관심사가 아닙니다. –

관련 문제