Android MediaCodec异步模式下的eglSwapBuffer阻塞GPU

3
我有一个视频特效应用程序,在其中使用OpenGL绘制到帧缓冲对象,然后将生成的纹理绘制到显示器上,以及如果应用程序正在编码,则绘制到MediaCodec输入表面。
我最初在API 18中按照同步模式(基于大flake示例)编写了编码器。我最近将其切换到API 21和异步模式。
它可以正常记录视频,我相信我已经正确设置了所有内容。但是,调用eglSwapBuffers似乎会导致帧速率显着下降。
如果我删除所有其他OpenGL调用,它运行得更好,但是我渲染的内容并不那么昂贵(它可以在每帧内多次良好渲染)。更改编码器设置(即从640x360@2Mbps到1920x1080@16Mbps)几乎没有任何区别。
唯一可以加快运行速度的方法是删除对eglSwapBuffers的调用(这将缓冲区数据发送到编码器)。
我的理解是,在异步模式下输出缓冲区不会像之前那样阻塞调用。我的理解是否正确?还有一种首选的调用渲染器的方式,或者在单独的线程上异步进行渲染的方法吗?
如有任何帮助或想法,请不吝赐教,感谢!

最终的解决方案是什么? - Pablo Martinez
1个回答

6
即使在异步模式下,输出缓冲区仍会阻塞编码器 - 您需要快速处理输出并在异步编码器输出回调被调用后将输出缓冲区返回给编码器,否则您将像以前一样阻塞输入。
同步和异步模式唯一的区别是您不需要轮询这些事件,而是获得回调。

非常感谢!那肯定回答了我一个问题。在这种情况下,异步编码视频是否有意义?即使我立即在回调上释放缓冲区,并且不对数据进行任何其他操作,渲染线程仍然被 eglSwapBuffers 阻塞。如果返回同步模式并通过释放任何输出缓冲区来“排空”编码器,我得到了相同的减速现象。 - Sam598
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - mstorsjo
也就是说,在同步模式下,你总是需要权衡等待输入和输出的时间,以平衡吞吐量和忙碌循环。而在异步模式下,只需尽可能多地提供输入,并在可用时排出输出。你看到的可能是 eglSwapBuffers 等待编码器提供一个空闲的输入缓冲区来绘制,即它被 GL 管道和视频编码器能够编码的速度所阻塞。交换本身可能并不需要那么长的时间,但如果没有更多的空闲输入缓冲区,它需要等待一个。 - mstorsjo
1
好的,那么在同步模式下将超时设置为零没有影响。同步与异步模式也没有影响。更改编码器的质量也没有影响,更改编解码器类型也是如此。所以问题是我渲染的内容太多了,硬件无法有效地运行编码器?我想我唯一能做的就是减少渲染量(至少对于这个设备来说是这样)。感谢您提供的所有帮助,您正在为每个人的MediaCodec问题提供出色的答案! - Sam598

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接