我一直在开发我们应用程序的记录组件,它使用 MediaCodec 和 Muxer 在 GLSurfaceView 上记录 GL 渲染。我找到了 fadden 的一组很好的例子(比如bigflake和 Grafika ......非常感谢 fadden),并尝试了这些东西。我基于 Android Breakout 的游戏录制模型构建了一个录制器,因为我们的应用程序使用 GLSurfaceView 来进行渲染。
它似乎在我的 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 毫秒。移动缓冲区可能需要很长时间,我认为这是合理的。另一个比预期花费更长的时间是 recorder.makeCurrent(),大约需要 10 毫秒。
我还试图测量 onDrawFrame() 的调用间隔。当录制关闭时(recordThisFrame() 设置为假),我一直在得到 16.7 ~ 17 毫秒,这是预期的。当 recordThisFrame() 设置为在 true 和 false 之间交替记录每隔一帧时,我一直在 22 ~ 25 ms(录制时)和 4~10 ms 左右。即使将 drawFrame() 调用更改为简单的 glclear(),我也得到了相同的结果。我在 Android Breakout Recorder(fadden 的原始代码)上尝试了这个,也得到了相同的结果。
我在 Grafika 中尝试了“使用 FBO 记录 GL 应用程序”活动,我发现即使在录制的情况下,它的 16-17 毫秒间隔也更加一致。我很想用 SurfaceView 替换 GLSurfaceView,就像在 Grafika 的 Record GL 应用程序中一样,但是这种更改目前似乎不是一个可行的选择。
makeCurrent() 调用成本高吗?有没有人遇到类似的间隔问题?任何想法将不胜感激。