我正在使用mediacodec + mediamuxer进行android视频录制,现在我可以录制视频并生成可以播放的mp4文件。问题是我发现录制的视频有时会占用一秒钟。因此,我启动了traceview并发现MediaMuxer.nativeWriteSampleData()引起了问题。有时此功能非常快并且会在几微秒内返回,但是有时此功能非常慢并且会消耗大约一秒钟左右的时间,并且此时会出现视频块。我不知道为什么此功能有时会如此变化。录制目标文件位于外部SDCard或内部存储中,并且两种介质上均存在问题。
新
最佳答案
大多数在写入闪存速度较低的设备上或尝试写入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。如果我们可以重新使用一个大的循环缓冲区来入队和出队新数据会更好。我写了一篇有关此事的文章,并提出了一个解决方案,在这里要进行冗长的解释。您可以read it here。