2013-05-06 8 views
7

Androidでは、カメラフレームでOpenGL処理を実行し、そのフレームをカメラプレビューで表示し、フレームをビデオファイルでエンコードしようとしています。私はGLSurfaceViewとGLSurfaceView.RendererとビデオエンコーディングのためにFFMPEGを使ってOpenGLでこれをしようとしています。Androidでピクセルバッファオブジェクト(PBO)を使用する

シェイダーを使用してイメージフレームを正常に処理しました。今私は、処理されたフレームをビデオにエンコードする必要があります。 GLSurfaceView.Rendererは、onDrawFrame(GL10 ..)メソッドを提供します。このメソッドでは、glReadPixels()だけを使用してイメージフレームを読み込み、ビデオにエンコードするためにフレームをキューに配置しようとしています。それ自身では、glReadPixels()は非常に遅すぎます - 私のフレームレートは1桁です。私はこれをピクセルバッファオブジェクトを使って高速化しようとしています。これは動作していません。 pboを差し込んだ後、フレームレートは変更されません。 OpenGLを使ったのはこれが初めてのことで、どこから問題を探すのか分かりません。私はこの権利をしていますか?誰か私にある方向を与えることができますか?前もって感謝します。

public class MainRenderer implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { 

. 
. 

    public void onDrawFrame (GL10 gl10) { 

     //Create a buffer to hold the image frame  
     ByteBuffer byte_buffer = ByteBuffer.allocateDirect(this.width * this.height * 4); 
     byte_buffer.order(ByteOrder.nativeOrder()); 

     //Generate a pointer to the frame buffers 
     IntBuffer image_buffers = IntBuffer.allocate(1); 
     GLES20.glGenBuffers(1, image_buffers); 

     //Create the buffer 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, image_buffers.get(0)); 
     GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, byte_buffer.limit(), byte_buffer, GLES20.GL_STATIC_DRAW); 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, image_buffers.get(0)); 

     //Read the pixel data into the buffer 
     gl10.glReadPixels(0, 0, this.width, this.height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, byte_buffer); 

     //encode the frame to video 
     enQueueForEncoding(byte_buffer); 

     //unbind the buffer 
     GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); 
    } 

. 
. 

} 
+0

Google Grafikaの例を確認しましたか?これらのOpenGLの実装があなたがAndroid上で手に入れることのできる最適なものに非常に近いと驚くことはありません。つまり、https://github.com/google/grafika/blob/master/src/com/android/grafika/RecordFBOActivity.java – harism

+0

glReadPixelsの呼び出しでは、glReadPixels(0、0、width、height、format、GL_UNSIGNED_BYTE、 0)。最後にゼロが渡されますが、javaはnullを許可しないため、JNI経由でこれを行う必要があります。通常はマップバッファを使用します。 –

答えて

0

私はこれまでに(opengl + video enconding)のようなことを試みたことはありませんが、デバイスメモリからの読み込みが遅いことを教えてください。ダブルバッファリングを試してみてください。これは、GPUが2番目のバッファにレンダリングを続けることができるため、DMAコントローラが読み込みを読み戻すために役立ちます。

プロファイラをロードして(デバイスのGPUベンダーを確認してください)、これはいくつか考えられます。もう1つのことは、内部のpbufferフォーマットを何かに設定し、数字を小さくしてチャンネル(アルファ)を​​落とすことです。

EDIT:あなたがそう感じるなら、GPUでビデオをエンコードすることができます。それはあなたのアプリケーションをブースト、メモリ、処理するのに賢明です。

+0

TraxNet、返信いただきありがとうございます。私はアルファチャンネルを失うことを試みます。私はそれが助けになると確信していますが、それは十分大きな違いを作りません。 GPUでのエンコーディングはベンダー固有のものでしょうか?私は別のデバイスを介して実行する必要があります。 –

+0

おそらく彼はGPUの副作用のためにRenderScriptを使うことを意味します。それはベンダーに依存しないでしょう。 – akauppi

1

glBufferData()が内部バッファをGPUメモリにマップしていないことを覚えているように、メモリからバッファにデータをコピー(初期化)するだけです。

glBufferData()によって割り当てられたメモリにアクセスするには、glMapBufferRange()を使用する必要があります。この関数は、読めるJavaバッファオブジェクトを返します。

関連する問題