繁体   English   中英

使用MediaMuxer编码MP4文件,但在调用mediaMuxer.stop()时崩溃

[英]Use MediaMuxer to encode a MP4 file but it crashes when calling mediaMuxer.stop()

我正在使用MediaMuxer和MediaCodec对来自摄像机的音频(H264)数据和音频(AAC-LC)数据进行编码,并将其编码为MP4文件。 但是MediaMuxer对象有时会在mediaMuxer.stop()崩溃,并且错误日志为

11-03 16:28:36.956: A/DEBUG(711): Abort message: 'frameworks/av/media/libstagefright/MPEG4Writer.cpp:2983 CHECK_LT( mCodecSpecificDataSize + 23,128) failed: 399 vs. 128'
11-03 16:28:36.957: A/DEBUG(711):     x0   0000000000000000  x1   0000000000001184  x2   0000000000000006  x3   0000000000000000
11-03 16:28:36.957: A/DEBUG(711):     x4   0000000000000000  x5   0000000000000001  x6   0000000000000000  x7   0000000000000000
11-03 16:28:36.957: A/DEBUG(711):     x8   0000000000000083  x9   0000000000000000  x10  0000000000000000  x11  0000007f91bb0df8
11-03 16:28:36.958: A/DEBUG(711):     x12  0000007f91bb0cd0  x13  0000000000000077  x14  0000007f91bb0ea8  x15  0000000000000000
11-03 16:28:36.958: A/DEBUG(711):     x16  0000007faca8d6a8  x17  0000007faca4fb2c  x18  0000007face14418  x19  0000007f91bb3510
11-03 16:28:36.959: A/DEBUG(711):     x20  0000007f91bb3450  x21  000000000000000b  x22  0000000000000006  x23  00000055a17fd260
11-03 16:28:36.959: A/DEBUG(711):     x24  0000007f91bb1c58  x25  0000007f91bb18b4  x26  0000007f91bb1f90  x27  0000007fa9715000
11-03 16:28:36.960: A/DEBUG(711):     x28  0000007f91bb1898  x29  0000007f91bb0d60  x30  0000007faca4d2c8
11-03 16:28:36.960: A/DEBUG(711):     sp   0000007f91bb0d60  pc   0000007faca4fb34  pstate 0000000020000000

我尝试过多次只编码一条音轨(视频或音频)。 mediaMuxer.stop()的执行完全正常。

为什么我对两条音轨进行编码时CHECK_LT失败?

好吧,我在这里回答自己。

昼夜MediaMuxer.stop()工作后,我发现有很多因素会导致在MediaMuxer.stop() AAC轨道时导致MediaMuxer.stop()崩溃。

为了避免崩溃,您最好在实现时遵循以下规则:

  1. 在同步模式下使用MediaCodec进行AAC编码。 通过使用同步模式,您可以将AudioRecorder的音频样本(即DirectByteBuffer )快速输入到MediaCodec的inputbuffer中,而无需进行任何额外的内存复制。 如果您放下太多样本, MediaMuxer将崩溃。

  2. 使用同步模式的另一个原因是,您可以使用MediaMuxer.dequeueInputBuffer(-1)来确保始终可以在writeAudioSample方法中获得可用的InputBuffer, writeAudioSample方法实现了将样本写入MediaCodec

  3. 另一个理由使用同步模式是,你需要之前排放的AAC编码数据MediaMuxer.stop() (请参阅规则9)

  4. 自行设置MediaFormat.KEY_MAX_INPUT_SIZE ,该值应为2048的倍数(1024个16位样本,对于字节,长度为2048)。 我通常将其设置为8192 ,这取决于音频源的采样率,通道数以及应用程序和设备的性能。

  5. 确保输入样本中充满音频数据,并且长度应为您设置为MediaFormat.KEY_MAX_INPUT_SIZE的值。 并以毫秒为单位计算演示时间。 任何两个相邻输入样本之间的显示时间间隔应相同。 通过以下公式计算样本的持续时间: 1_000_000L * KEY_MAX_INPUT_SIZE / SAMPLE_RATE / NUMBER_OF_CHANNELS / 2 您无需将演示时间对齐或移动到0 我强烈建议您使用long initialTime = System.nanoTime() / 1000L来获取初始时间并将其传递给MediaCodec 因此,下次编写示例时,显示时间应为initialTime + 1_000_000L * KEY_MAX_INPUT_SIZE / SAMPLE_RATE / NUMBER_OF_CHANNELS / 2 ,依此类推。

  6. 这部分是最大的坑。 将AAC编码数据写入MediaMuxer ,请检查演示时间,即使在将音频样本输入到MediaCodec时已经设置了演示时间。 AAC编码数据的显示时间有时可能不会增加。 您应该记录您写入MediaMuxer的上次演示时间。 如果发现AAC数据presentationTime = ++lastPresentationTime通过presentationTime = ++lastPresentationTime调整演示时间。 此外,您可能会获得一些零表示时间的AAC数据。 别管他们。 不要将它们写入MediaMuxer

  7. 如果MediaMuxer还有其他轨道,请确保每个轨道的演示时间在相同范围内(允许几秒钟的错误)。

  8. 一个MediaMuxer一个AAC MediaCodec 并且不要重复使用输出MediaFormat对象。

  9. 在执行MediaMuxer.stop()之前,请停止调用writeAudioSample方法,并通过queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)将EOS发送到MediaCodec 并从MediaCodec排出剩余的AAC数据以写入MediaMuxer 执行MediaMuxer.stop()看看发生了什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM