2012-01-19 12 views
0

外部カメラからビデオをレンダリングするアンドロイドアプリケーションを開発中です。 ndkでカメラとの通信を行うため、ビデオフレームはNDKレイヤーのopenglを介してスクリーンにレンダリングされ、より高速です。次のようにサードパーティ(カメラ​​の開発者)から来たように私は、コードを書いていないと、彼らはMyGLSurfaceViewでsurfaceDestroyed方法を実装している:Android NDK OpenGL glDeleteTexturesが原因でエラーが発生しました:現在のコンテキストなしでOpenGL ES APIを呼び出す

myRendererは

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

をレンダラーに次のコードが書かれていた:NDKで作成されたテクスチャがクリーンアップされないこと

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

お知らせコメント。これは本当ですか?私が尋ねる理由は、私はこの呼び出しから次のエラーを取得することです:

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

私はNDKコードでエラーがスローされますと、それはデストラクタであることが判明している場所を正確に把握するために、いくつかのデバッグ文を入れています(クリーンを呼び出す)ImageRenderと呼ばれるいくつかのクラスのために、ここでそれをトリガー行は次のようになります。

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

彼らは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スレッド上で確実に呼び出されるようにするには、

//from MyGLSurfaceView 
    @Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    Log.d(TAG, "Inside GL surfaceDestroyed"); 
      // TODO Auto-generated method stub 

     queueEvent(new Runnable() { 
     @Override 
     public void run() { 
      // TODO Auto-generated method stub 
      myRenderer.surfaceDestroyed(); //call this to clean up the renderer.  
     } 
     }); 
    super.surfaceDestroyed(holder); 
} 

を呼び出してみましたが、同じエラーが発生していました。

提案がありますか?ところで、このメソッドを単に呼び出さないとコードが正常に動作しているように見えますが、これはかなり前から行われていましたが、OpenGLフレームを使用したアクティビティを開始したときに、以前のOpenGLアクティビティこの呼び戻しを問題に直していたのではなく、時間のほんの一部であるように見えました。

答えて

3

OpenGLコンテキストがないため、UIスレッドでmyRenderer.surfaceDestroyedを呼び出すことはできません。 OpenGLスレッドでsurfaceDestroyedを実行するには、queueEventを使用する必要があります。あなたがRunnableで実装したものの問題は次の通りです。 - queueEventは非ブロックです。したがって、あなたのネイティブコードが呼び出される前に、myRenderer.surfaceDestroyed()およびGLコンテキストが破棄される前に、おそらくsuper.surfaceDestroyed(holder)が呼び出されます。

これが機能するかどうかは不明ですが、queueEvent呼び出しの後にUIスレッドをブロックして、Runnableがそのジョブを終了するまで待ちます。

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

これは、ネイティブコードがコンテキストをクリーンアップできるように、UIスレッドを最大100ミリ秒ブロックします。必要に応じて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コンテキストではありません)。 -1値は、glGenTextures()がテクスチャの新しい名前の割り当てに失敗した場合には触れないテクスチャ名のデフォルト初期値にしか見えません。

関連する問題