2012-01-19 4 views
0

외부 카메라에서 비디오를 렌더링하는 Android 응용 프로그램에서 작업 중입니다. 비디오 프레임은 NDK 레이어의 opengl을 통해 화면으로 렌더링되며, ndk에서 카메라와 통신하므로 더 빠릅니다. 이 제 3 자 (카메라의 개발자)에서 온 나는 코드를 작성하지 않은 다음과 같이 그들은 MyGLSurfaceView의 방법 surfaceDestroyed을 구현 한 : myRenderer 지금Android NDK OpenGL glDeleteTextures가 오류를 발생시킵니다. 현재 컨텍스트가없는 OpenGL ES API를 호출합니다.

myRenderer = new MyGLRenderer(mContext); 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
     Log.d(TAG, "Inside GL surfaceDestroyed"); 
     // TODO Auto-generated method stub 
     myRenderer.surfaceDestroyed(); //call this to clean up the renderer. 
     super.surfaceDestroyed(holder); 
} 

입니다

경우 렌더러에서 다음 코드가 작성되었습니다.

public class MyGLRenderer implements Renderer { 
    public void surfaceDestroyed() 
    { 
     Log.d(TAG, "Inside surfaceDestroyed"); 
     /* Note: As per doc, GLSurfaceView kills the renderer and deletes any textures associated with it. 
     * However, it does not clean up textures created in NDK. So, we need to do this explicitly. 
     */ 
     mGLAdapter.destroyGlTexturesJni(myRenderer); 
    } 

NDK에서 만든 텍스처는 정리되지 않습니다. 사실입니까? 나는 NDK 코드에서 오류가 발생됩니다 위치를 정확히 파악하는 디버깅 문을 넣어 가지고와 소멸자에 있어야 그것을 발견 한

01-19 12:01:19.715: E/libEGL(27208): call to OpenGL ES API with no current context (logged once per thread) 

: 물어 이유는 내가이 호출에서 다음과 같은 오류를 얻을 수 있다는 것입니다 ImageRender (청소를 호출하는)라는 일부 클래스, 여기가 트리거 라인 : 그들은 m_unTexture을 설정처럼

void ImageRender::Clean() 
{ 
// destruct texture 
if (m_unTexture != -1) 
    glDeleteTextures(1,&m_unTexture); 
    .... 

것 같습니다 (이는 GL 컨텍스트가 맞다?) 여기 :

int ImageRender::InitTexture(const int nWidth, const int nHeight) 
    { 
// Enable texture 2D first. 
glEnable(GL_TEXTURE_2D); 
// create texture 
glGenTextures(1,&m_unTexture); 
// bind texture to target. 
glBindTexture(GL_TEXTURE_2D,m_unTexture); 
    ... 

그리고 glGetError를 검사하면 코드를 통과하고 GL_NO_ERROR를 얻지 못하면 -1로 설정하여 유효하지 않음을 알립니다.

그래, 내 질문에 정말 NDK에서 만든 텍스처를 정리해야합니까, 그렇다면, 내가 본 오류없이 어떻게 할 수 있습니다. 렌더러가 OpenGL 스레드에서 호출되었지만 오류가 발생했는지 확인하기 위해 다음을 사용하여 호출 해 보았습니다.

제안 사항? 그런데 코드가 잘 작동하는 것처럼 보입니다. 간단히 말해서이 메소드를 호출하지 않으면 오랫동안 해왔지만, OpenGL 프레임을 사용하는 액티비티를 시작했을 때 마지막 프레임으로 초기화됩니다. 이전의 OpenGL 활동. 이 전화를 다시 걸면 문제가 해결되는 것 같았지만 시간 만 남았습니다.

답변

3

OpenGL 컨텍스트가 없으므로 UI ​​스레드에서 myRenderer.surfaceDestroyed를 호출 할 수 없습니다. OpenGL 스레드에서 surfaceDestroyed를 실행하려면 queueEvent를 사용해야합니다. Runnable로 구현 한 문제는 다음과 같습니다. - queueEvent는 비 블로킹입니다. 따라서 네이티브 코드가 호출되기 전에 myRenderer.surfaceDestroyed() 및 GL 컨텍스트가 파손되기 전에 super.surfaceDestroyed (holder)가 호출 될 가능성이 큽니다.

이 방법이 효과가 있을지 모르지만 queueEvent 호출 후 UI 스레드를 차단하고 Runnable이 작업을 마칠 때까지 기다리십시오. 이런 식으로 뭔가 : 이것은 당신의 원시 코드가 상황을 정리 할 수 ​​있도록 최대 100 밀리 초 동안 UI 스레드를 차단합니다

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    Log.d(TAG, "Inside GL surfaceDestroyed"); 

    queueEvent(new Runnable() { 
     @Override 
     public void run() { 
      myRenderer.surfaceDestroyed(); 
      synchronized (myRenderer) { 
       myRenderer.notify(); 
      } 
     } 
    }); 

    synchronized (myRenderer) 
    { 
     try { myRenderer.wait(100); } 
     catch (InterruptedException e) { } 
    } 

    super.surfaceDestroyed(holder); 
} 

. 필요한 경우 100 이상 늘리십시오. 최악의 경우

은 - 그냥 무료 GL 자원 자신을.GL 문맥이 당신을 위해 그 (것)들을 해방하게하십시오.

+0

다른 스레드에서 전화를 걸 때 차단하는 방법에 대한 흥미로운 아이디어. 불행히도 현재 컨텍스트없이 OpenGL ES API를 호출하는 것에 대한 오류가 계속 발생하지만 나는 왜 glDeleteTextures (1, & m_unTexture)에 대한 호출이 긍정적이라는 이유로 확신 할 수 없다. super.surfaceDestroyed (holder) 호출 (모든 로그 아웃) 전에 발생합니다. –

+0

실제로 이것에 대한 버그가 정확히 채워졌습니다. - http://code.google.com/p/android/issues/detail?id=19245 surfaceDestroyed가있는 것 같습니다. 표면은 이미 파괴되었습니다. –

+1

[GLSurfaceView.EGLContextFactory] (http://developer.android.com/reference/android/opengl/GLSurfaceView.EGLContextFactory.html) 인터페이스에는 destroyContext 콜백이 있습니다. 그것을 사용해보십시오. 내가 올바르게 이해한다면 GLSurfaceView에서 setEGLContextFactory를 호출하면 destryContext callaback의 문맥을 파괴 할 책임이있다. –

0

다른 질문에 대답하려면 : m_unTexture는 GL 텍스처 이름 (GL 컨텍스트가 아님)입니다. glGenTextures()가 텍스처의 새로운 이름을 할당하지 못하면 -1 값이 터치되지 않는 텍스처 이름의 기본 초기화 값으로 나타납니다.