当前位置: 首页 > 知识库问答 >
问题:

使用MediaMuxer对MP4文件进行编码,但调用MediaMuxer.stop()时会崩溃

公良云
2023-03-14

我正在使用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在编码两个音轨时失败?

共有1个答案

田易安
2023-03-14

好吧,我来回答我自己。

经过日以继夜的工作,我发现有很多因素会导致mediamuxer.stop()在多路复用AAC轨道时崩溃。

为了避免崩溃,您最好按照以下规则执行:

>

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

    使用同步模式的另一个原因是,您可以使用MediaMuxer.DequeueInputBuffer(-1)来确保始终可以在WriteAudioSample方法中获得可用的InputBuffer,该方法用于将示例写入MediaCodeC

    使用同步模式的另一个原因是,您需要在mediamuxer.stop()之前排出AAC编码数据。(见第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等等。

    这部分是最大的坑。在将AAC编码数据写入MediaMuxer时检查演示时间,即使在将音频样本输入MediaCodeC时已经设置了演示时间。AAC编码数据的呈现时间有时可能不是递增的。您应该记录上次写入mediaMuxer的演示时间。如果您发现错误排序的AAC数据,请通过presentationtime=++lastpresentationtime调整演示时间。此外,您可能会得到一些零表示时间的AAC数据。别理他们。不要将它们写入mediaMuxer

    如果mediaMuxer有其他音轨,请确保每个音轨的呈现时间在相同的范围内(允许错误数秒)。

    一个AACmediaCodec对应一个mediaMuxer。并且不重用outputmediaformat对象。

    在执行mediaMuxer.stop()之前,停止调用您的writeaudiosample方法,并通过queueinputbuffer(index,0,0,0,mediaCodeC.buffer_flag_end_of_stream)mediaCodeC发送EOS。并从mediaCodeC中排出剩余的AAC数据以写入mediaMuxer。执行mediamuxer.stop()并查看发生了什么。

  •  类似资料:
    • 我正在开发一个应用程序,在其中我解码视频,替换某些帧,并使用和重新编码。如果我不替换任何帧(我在下面解释的1080p视频除外),该应用程序就可以工作,但当我替换帧时,被替换帧之后的帧会被像素化,并且视频会有起伏。 此外,当我使用1920x1080个视频尝试我的应用程序时,我会得到一个奇怪的输出,其中视频没有显示任何内容,直到我滚动到视频的开头,然后视频开始显示(但与之前提到的相同问题编辑后的像素化

    • 问题内容: 我在处理JNA中的回调时遇到问题。 我正在尝试使用C API,该API使用回调来处理多个会话事件(登录,注销,连接问题…)。 会话对象(称为)是不透明的结构。所有回调均在结构中注册。根据API,我应该声明回调对象,并将其放入创建对象时将提供的Config对象中。如果我不想使用某些回调,则应该使用对其进行初始化。API正在使用调用约定。 这是与我的问题有关的C标头的代码段: 这是我等效的

    • 我有以下功能,它获取一个WAV(PCM)文件并使用Android的MediaCode和MediaMuxer类将其编码为AAC编码的MP4文件。这只是音频。该函数成功运行并输出一个合理的. mp4,该函数被识别为AAC编码。但它不能在Android、Web或iOS播放器上播放,并使Audacy崩溃。我错过了什么吗?代码如下所示。

    • 我在服务器端对JSON进行了编码(使用ESAPI编码器),然后客户机检索bean的字段并进行进一步的处理。 在服务器端 编码的JSON字符串 \x7b\x22name\x22\x3a\x22sameer\x22,\x22company\x22\x3a\x22company\x22,\x22designation\x22\x3a\x22developer\x22\x7d 在客户端

    • 问题内容: 我正在尝试使用(使用最新的Webkit)下载二进制文件,并使用以下简单功能对base64的内容进行编码: 附带说明一下,以上所有内容都是标准Javascript内容,包括和 这工作非常顺利,我什至可以使用Javascript解码base64内容: 现在,我想使用Python解码base64编码的内容,该内容使用一些JSON字符串来获取字符串值。天真的,这就是我的工作: 但是生成的文件无

    • 我正在修改一个Android框架示例,将MediaCodec生成的基本AAC流打包成一个独立的。mp4文件。我使用的是一个实例,其中包含一个由实例生成的AAC曲目。 然而,我总是最终得到一个错误消息调用: