这个问题主要发生在写入闪存速度较低的设备上,或者您尝试写入 SD 卡时。解决方案是将编码数据复制到临时 ByteBuffer,将数据释放回 MediaCodec,并在专用线程上异步调用 writeSampleData。
因此,假设您有一个线程用于排空 MediaCodec 的输出和一个用于馈送 MediaMuxer 的线程,这是一个可能的解决方案:
// this runs on the MediaCodec's draining thread
public void writeSampleData(final MediaCodec mediaCodec, final int trackIndex, final int bufferIndex, final ByteBuffer encodedData, final MediaCodec.BufferInfo bufferInfo) {
final ByteBuffer data = ByteBuffer.allocateDirect(bufferInfo.size); // allocate a temp ByteBuffer
data.put(encodedData); // copy the data over
mediaCodec.releaseOutputBuffer(bufferIndex, false); // return the packet to MediaCodec
mWriterHandler.post(new Runnable() {
// this runs on the Muxer's writing thread
@Override
public void run() {
mMuxer.writeSampleData(trackIndex, data, bufferInfo); // feed the packet to MediaMuxer
});
}
这种方法的问题是我们为每个传入的数据包分配一个新的 ByteBuffer。如果我们可以重新使用一个大的循环缓冲区来对新数据进行入队和出队会更好。我已经写了一篇关于这个问题的帖子,并提出了一个在这里解释起来相当冗长的解决方案。你可以在这里阅读。