java.lang.IllegalStateException: Failed to stop the muxer
at android.media.MediaMuxer.nativeStop(Native Method)
at android.media.MediaMuxer.stop(MediaMuxer.java:225)
MediaMuxer在录制完成时调用stop接口抛异常崩溃,往上翻看崩溃日志有两行下面的错误
E/textview: initAddtionalStyle default
E/MPEG4Writer: Missing codec specific data
这个异常跟编码器有关,到网上查找资料,看别人写的代码,发现是调用MediaMuxer.addTrack的时机不对;
MediaMuxer.addTrack应该在编码器MediaCodec编码过程开始,dequeueOutputBuffer返回
INFO_OUTPUT_FORMAT_CHANGED状态时才调用
_mediaMuxer = new MediaMuxer(...);
_videoEncoder = MediaCodec.createEncoderByType(...);
_videoEncoder.configure(...);
_videoEncoder.start();
2.把要压缩的帧数据压入Codec排队
if (inputBufferIndex >= 0)
{
inputBuffers[inputBufferIndex].put(...);
_videoEncoder.queueInputBuffer(inputBufferIndex);
}
else
{
...
}
3.从Codec顺次得到编码好的数据,跟第二步设计好时序,可以并行处理
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
{
// *Codec输出格式,这里是重点,否则可能会出现前面的异常崩溃
MediaFormat newFormat = _videoEncoder.getOutputFormat();
int trackIndex = _mediaMuxer.addTrack(newFormat);
if (所有track准备好)
{
_mediaMuxer.start();
}
}
else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
{
outputBuffers = _videoEncoder.getOutputBuffers(bufferInfo, ...);
}
else if (outputBufferIndex >= 0)
{
// 真实压缩帧数据
if (bufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0)
{
// *一帧数据前可能有Codec配置信息,需要单独保存起来和第一帧真实数据合并
outputBuffers[outputBufferIndex].get(codecConfig, 0, bufferInfo.size());
}
else
{
int configSize = codecConfig.limit();
sample = ByteBuffer.allocate(...);
if (codecConfig != null)
{
codecConfig.get(sample.array(), 0, configSize);
codecConfig = null;
}
outputBuffers[outputBufferIndex].get(sample.array(), configSize, bufferInfo.size());
// 保存压缩帧,如果有多个Track,这里MediaMuxer可能还没start,也可以放入一个队列,等准备好再保存
_mediaMuxer.writeSampleData(trackIndex, sample, bufferInfo);
}
_videoEncoder.releaseOutputBuffer(outputBufferIndex, false);
}