背景
我已将Android的MediaCodec连接到FFmpeg,以便对MediaMuxer不支持的各种格式进行多路复用,包括通过rtmp://
容器输出.flv
。这样的流式复用器需要更长,不可预测的MediaCodec输出缓冲器的所有权,因为它们可以在任何数据包处理步骤上执行网络I / O.对于我的视频流,我正在使用为Surface输入配置的MediaCodec。要将muxing与编码分离,我将MediaCodec的ByteBuffer输出缓冲区通过Handler排队到我的muxer。
如果我将.flv
输出复用到文件而不是rtmp端点,那么所有工作都很出色。
问题:
当复用到rtmp://...
端点时,我注意到我的流媒体应用程序在eglSwapBuffers(mEGLDisplay, mEncodingEGLSurface)
处于dequeueOutputBuffer()
的调用时开始阻止一旦我在我的多路复用队列中保留了几个MediaCodec输出缓冲区MediaCodec似乎只锁定了4个输出缓冲区。
避免复制MediaCodec#dequeueOutputBuffers
返回的所有编码器输出并立即调用releaseOutputBuffer(...)
的任何技巧?
我的项目的完整资源可在Github上找到。具体来说,请参阅:
Muxer
实例。Muxer
Systrace
这是一些systrace输出流720p @ 2Mbps视频到Zencoder。
解决
复制然后释放MediaCodec编码器输出ByteBuffers在它们可用时解决问题而不会显着影响性能。我为每个复用器轨道在ArrayDeque<ByteBuffer>
中回收ByteBuffer副本,这限制了分配的数量。
答案 0 :(得分:3)
不幸的是,大多数Android手机都不支持这种用例。 MediaCodec只是设备上编解码器供应商使用的OMX IL API的抽象。供应商编解码器需要为给定配置提供一定数量的输入和输出缓冲区。
虽然理论上说,将一个与编码器排队的输出缓冲区应该足够,但很多时候供应商编解码器不支持这种情况,因为它会导致编码性能降低;因此编解码器停滞不前。输入缓冲区更为普遍。
对于为MediaCodec实例分配的输入/输出缓冲区的数量没有应用程序控制--Android会尝试分配所需的最小缓冲区数,以节省内存。因此,您唯一的选择是复制输出缓冲区。虽然这不是理想的,但编码的缓冲区往往相当小。