OpenGLを使用してフレームバッファオブジェクトに描画し、その結果のテクスチャをディスプレイに描画してから、アプリケーションがエンコードしている場合はMediaCodec入力サーフェイスを描画するビデオエフェクトアプリケーションがあります。Android MediaCodec eglSwapBuffer非同期モードのGPUをブロックする
私は最初、API 18のエンコーダを同期モードで書いていました(大きなフレークの例に基づいています)。私は最近、API 21と非同期モードに切り替えました。
これはビデオをうまく記録しており、すべてが正しく設定されていると思います。しかし、eglSwapBuffersを呼び出すと、フレームレートが大幅に低下するようです。
他のすべてのOpenGL呼び出しを削除すると、よりうまく動作しますが、レンダリングするのは高価ではありません(フレームごとに複数回細かくレンダリングできます)。エンコーダの設定を変更すると(つまり、640x360 @ 2Mbpsから1920x1080 @ 16Mbpsに)、実質的に違いはありません。
実行を高速化する唯一の方法は、eglSwapBuffers(バッファデータをエンコーダに送信する)への呼び出しを削除することです。
私の理解では、出力バッファは以前と同じように非同期モードで呼び出しをブロックしません。私はこれについて間違っていますか?レンダラーを呼び出す方法、または別のスレッドで非同期にレンダリングする方法がありますか?
ご協力いただきありがとうございます!
ありがとうございました!それは間違いなく私の質問の一つに答えます。その場合、ビデオを非同期でエンコードすることはこれまで理にかなっていますか?私がすぐにコールバックでバッファを解放し、データで何もしない場合でも、レンダリングスレッドはまだeglSwapBuffersによってブロックされています。同期モードに戻り、出力バッファを解放してエンコーダを「ドレイン」にすると、同じ減速が発生します。 – Sam598
一般に、はい、非同期モードは絶対に意味があります。一例として、面入力モードを使用しないエンコーダを考えてみましょう。任意の時点で、新しい空き入力バッファーを使用するか、出力バッファーを満たすのを待つ必要があります。両方のタイムアウト値をチェックすると、最高のスループットが得られますが、基本的にはビジーループになります。ゼロ以外のタイムアウトを待つと、ビジーループは発生しません。すべての入力バッファを満たしていれば、出力バッファを待ってそれを返すまで、新しい入力バッファは取得されません。 – mstorsjo
つまり、同期モードでは、入力と出力を待つ時間の長さと、スループットとbusyloopingのバランスをとるというトレードオフがあります。非同期モードでは、できるだけ入力を続けるだけで、出力があれば排水してください。恐らく、eglSwapBuffersはエンコーダが描画するための自由な入力バッファを提供するのを待っている、つまり、GLパイプラインとビデオエンコーダがエンコードできる速度でブロックされているということです。スワップ自体はそれほど時間がかかりませんが、空き入力バッファがなくなると、それを待たなければなりません。 – mstorsjo