MediaMuxer Stop抛异常崩溃

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状态时才调用


基本流程应该是(示意代码)

1.初始化各对象
_mediaMuxer = new MediaMuxer(...);
 
  
_videoEncoder = MediaCodec.createEncoderByType(...);
_videoEncoder.configure(...);
_videoEncoder.start();
 
  
2.把要压缩的帧数据压入Codec排队
inputBuffers = _ videoEncoder.getInputBuffers(...);
inputBufferIndex = _videoEncoder.dequeueInputBuffer(...);
if (inputBufferIndex >= 0)
{
	inputBuffers[inputBufferIndex].put(...);
	_videoEncoder.queueInputBuffer(inputBufferIndex);
}
else
{
...
}
 
  
3.从Codec顺次得到编码好的数据,跟第二步设计好时序,可以并行处理
 
  
outputBuffers = _ videoEncoder.getOutputBuffers(...);
outputBufferIndex = _ videoEncoder.dequeueOutputBuffer(...);
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);
}

你可能感兴趣的:(视音频)