use*_*481 0 video android mediamuxer android-mediacodec
我使用 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
Run Code Online (Sandbox Code Playgroud)
我多次尝试只对单个轨道(视频或音频)进行编码。执行mediaMuxer.stop()完全没问题。
为什么CHECK_LT我编码两个轨道时失败?
好吧,我是来回答我自己的。
经过夜以继日的工作,我发现有很多因素可能会导致MediaMuxer.stop()混音 AAC 轨道时崩溃。
为了避免崩溃,您最好在实施时遵循以下规则:
MediaCodec在 AAC 编码的同步模式下使用。通过使用同步模式,您可以将音频样本(即DirectByteBuffer)从 AudioRecorderMediaCodec快速输入到 的 inputbuffer 中,而无需进行任何额外的内存复制。如果丢弃太多样本,MediaMuxer就会崩溃。
使用同步模式的另一个原因是,您可以使用它MediaMuxer.dequeueInputBuffer(-1)来确保您始终可以在您writeAudioSample实现将样本写入到的方法中获得可用的InputBuffer MediaCodec。
使用同步模式的另一个原因是您需要先排出AAC 编码数据MediaMuxer.stop()。(见规则9)
自行设置MediaFormat.KEY_MAX_INPUT_SIZE,该值应为2048的倍数(1024个16位样本,对于字节来说,长度为2048)。我通常将其设置为8192,这取决于音频源的采样率、通道数量以及应用程序和设备的性能。
确保输入样本充满音频数据,长度应为您设置的值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如此。
这部分是最大的坑。MediaMuxer即使您在将音频样本输入到 时已经设置了呈现时间,但在写入 AAC 编码数据时请检查呈现时间MediaCodec。AAC编码数据的呈现时间有时可能不是增量的。您应该记录您上次写入的演示时间MediaMuxer。如果您发现 AAC 数据顺序错误,请将演示时间调整presentationTime = ++lastPresentationTime。此外,您可能会获得一些零呈现时间的 AAC 数据。别理他们。不要将它们写入MediaMuxer.
如果MediaMuxer有其他曲目,请确保每个曲目的演示时间在相同范围内(允许秒数误差)。
一张 AACMediaCodec一张MediaMuxer。并且不要重用输出MediaFormat对象。
在执行之前MediaMuxer.stop(),停止调用您的方法并向viawriteAudioSample发送 EOS 。并排出剩余的 AAC 数据以写入。执行并看看发生了什么。MediaCodecqueueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM)MediaCodecMediaMuxerMediaMuxer.stop()
| 归档时间: |
|
| 查看次数: |
1157 次 |
| 最近记录: |