MediaCodec と Muxer を使用して GLSurfaceView に GL レンダリングを記録するアプリの記録コンポーネントを開発しています。fadden ( bigflakeや Grafika など... fadden に感謝)による素敵な例のセットを見つけて、それらを試してみました。私たちのアプリは GLSurfaceView を使用してレンダリングを行ったため、Android Breakout のゲーム記録モデルに基づいてレコーダーを作成しました。
私のNexus 7(2013年4.4.2および5.0.2)ではうまく機能しているように見えました。レンダリングされた画面を記録することができ、それらのエンコードされた MP4 は他のデバイスでうまく再生されました。ただし、もう少し複雑なレンダリングが必要になると、フレームがドロップし始めました。フレームのレンダリングには約 4 ミリ秒しかかからないため、それほど複雑ではありません。だから、私は問題の原因を特定しようとしてきました。
私の疑似コードは、Android Breakout Recorder と非常によく似ています。OnDrawFrame() は次のようになります。
GLES20.glViewport(mViewportXoff, mViewportYoff, mViewportWidth, mViewportHeight);
drawFrame();
GameRecorder recorder = GameRecorder.getInstance();
if (recorder.isRecording() && recordThisFrame()) {
saveRenderState();
// switch to recorder state
recorder.makeCurrent();
recorder.getProjectionMatrix(mProjectionMatrix);
recorder.setViewport();
// render everything again
drawFrame();
recorder.swapBuffers();
restoreRenderState();
}
行ごとの呼び出しのパフォーマンスを測定しようとしたところ、Nexus 7 でrecorder.swapBuffers() に約 10 ミリ秒かかることがわかりました。バッファーの移動にはそれだけの時間がかかる可能性がありますが、これは妥当だと思います。もう 1 つは、recorder.makeCurrent() で、予想よりも時間がかかりました。これにはさらに 10 ミリ秒かかります。
また、onDrawFrame() の呼び出し間隔を測定しようとしていました。記録がオフのとき (recordThisFrame() 設定を false に設定)、一貫して 16.7 ~ 17 ミリ秒でした。これは予想どおりです。recordThisFrame() が true と false を交互に切り替えて 1 フレームおきに記録するように設定されている場合、約 22 ~ 25 ミリ秒 (記録時) と 4 ~ 10 ミリ秒になります。drawFrame() 呼び出しを単純な glclear() に変更した後でも、同じ結果が得られました。これを Android Breakout Recorder (fadden のオリジナル コード) で試したところ、同じ結果が得られました。
Grafika で「FBO を使用して GL アプリを記録する」アクティビティを試していたところ、記録でも 16 ~ 17 ミリ秒の間隔がより一貫していることがわかりました。Grafika の Record GL アプリのように、GLSurfaceView を SurfaceView に置き換えたいと思いましたが、その変更は今のところ実行可能なオプションではないようです。
makeCurrent() 呼び出しはそれほどコストがかかるのですか? 同様の間隔の問題が発生している人はいますか? 任意の考えをいただければ幸いです。