9

私のネイティブスレッドでは、FFMpegがフレームを取得してデコードし、それらをキューに入れています。

Java側ではGLSurfaceViewRenderer.onDrawFrameビットマップを渡すネイティブコードを呼び出しています(そのビットマップは1回だけ作成し、毎回渡します)。

ネイティブコードでは、キューの先頭を取得し、関数を使用してデータをJavaビットマップにコピーしてから、AndroidBitmap_xxxそのビットマップをJava側でテクスチャとしてレンダリングします。

ビデオをレンダリングするより速い方法があるのだろうか?完全にネイティブコードで実行しますか?はいの場合、なぜ高速になるのですか?

編集: RGBフレームピクセルをロックされたビットマップピクセルにコピーせず、YUVフレームをロックされたビットマップピクセルに直接デコードします。これにより、レンダリングが大幅に高速化されます(不要なmemcpyがなくなったため)。それでも問題は残ります。

4

1 に答える 1

2

テクスチャのピクセルを変更する最も効果的な手法は、Render-to-Textureと呼ばれ、OpenGL / OpenGLESでFBOを介して実行できます。デスクトップOpenGLでは、ピクセルバッファーオブジェクト(PBO)を使用して、GPU上でピクセルデータを直接操作できます(ただし、OpenGL ESはこれをまだサポートしていません)。

拡張されていないOpenGLでは、システムメモリ内のピクセルを変更してから、glTexImage2D / glTexSubImage2Dでテクスチャを更新できますが、これは非効率的な最後の手段であり、可能であれば回避する必要があります。glTexSubImage2Dは、既存のテクスチャ内のピクセルのみを更新するため、通常ははるかに高速ですが、glTexImage2Dは、まったく新しいテクスチャを作成します(利点として、テクスチャのサイズとピクセル形式を変更できます)。一方、glTexSubImage2Dでは、テクスチャの一部のみを更新できます。

OpenGL ESで動作させたいとおっしゃっていたので、次の手順を実行することを提案します。

  • glTexImage2D()をglTexSubImage2D()に置き換えます-十分なパフォーマンスが得られたら、そのままにします。
  • FBOとシェーダーを使用してテクスチャへのレンダリングを実装します。コードを書き直すにははるかに多くの作業が必要になりますが、パフォーマンスはさらに向上します。

FBOの場合、コードは次のようになります。

// setup FBO
glGenFramebuffers( 1, &FFrameBuffer );
glBindFramebuffer( GL_FRAMEBUFFER, FFrameBuffer );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, YourTextureID, 0 );
glBindFramebuffer( GL_FRAMEBUFFER, 0 );

// render to FBO
glBindFramebuffer( GL_FRAMEBUFFER, FFrameBuffer );
glViewport( 0, 0, YourTextureWidth, YourTextureHeight );
your rendering code goes here - it will draw directly into the texture
glBindFramebuffer( GL_FRAMEBUFFER, 0 );

// cleanup
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
glDeleteFramebuffers( 1, &FFrameBuffer );

すべてのピクセル形式をレンダリングできるわけではないことに注意してください。通常、RGB/RGBAで問題ありません。

于 2012-07-25T10:04:00.307 に答える