背景:
我已经将Android的MediaCodec连接到了FFmpeg,用于修改MediaMuxer不支持的各种格式,包括通过.flv
容器输出的rtmp://
。这种流屏蔽器需要对MediaCodec的输出缓冲区拥有更长、更不可预测的所有权,因为它们可以在任何数据包处理步骤上执行网络I/O。对于我的视频流,我使用配置为Surface输入的MediaCodec。为了从编码中分离多个变量,我通过一个Handler将MediaCodec的ByteBuffer输出缓冲区排队到我的muxer。
如果我将.flv
输出修改为文件,而不是rtmp端点,那么所有这些都能出色地工作。
问题:
当切换到rtmp://...
端点时,我注意到我的流应用程序一旦在muxing队列中保留了几个MediaCodec输出缓冲区,就开始阻止dequeueOutputBuffer()
上对eglSwapBuffers(mEGLDisplay, mEncodingEGLSurface)
的调用,因为MediaCodec似乎仅被锁定到4个输出缓冲区。
避免复制MediaCodec#dequeueOutputBuffers
返回的所有编码器输出并立即调用releaseOutputBuffer(...)
的任何技巧
我的项目的全部源代码可以在Github上获得。具体见:
Muxer
实例。Muxer
Systrace
以下是一些传输720 p@2 2Mbps视频到Z编码器的系统输出。
解决了
复制然后发布MediaCodec编码器输出ByteBuffers,一旦它们可用,就解决了这个问题,而不会对性能造成显著影响。我将每个muxer跟踪的ByteBuffer副本循环到一个ArrayDeque<ByteBuffer>
中,这限制了分配的数量。
发布于 2014-02-12 18:30:23
不幸的是,大多数Android手机不支持这种用例。MediaCodec只是对编解码器厂商在设备上使用的OMX的抽象。对于给定的配置,供应商编解码器需要一定数量的输入和输出缓冲区。
虽然从理论上讲,让一个输出缓冲区与编码器排队应该足够了,但是很多时候供应商编解码器不支持这一点,因为它导致编码性能降低;因此编解码器停止。这在输入缓冲区中更为普遍。
对于分配给MediaCodec实例的输入/输出缓冲区的数量没有应用程序控制-- Android试图分配所需的最小缓冲区数量,以节省内存。因此,您唯一的选择是复制输出缓冲区。虽然这并不理想,但编码的缓冲区往往相当小。
https://stackoverflow.com/questions/21714930
复制相似问题