3

我有一些自动化测试尝试使用 AndroidMediaDecoderMediaExtractor. 这些文件是使用各种编码器生成的:fdk-aac、ffmpeg(使用 fdk 或默认的 aac 编码器)、iOS。

在 Android 9 上,使用 创建的剪辑的测试失败ffmpeg,这会导致 PCM 文件为空。在旧版本的 Android 上,相同的剪辑可以很好地解码。

我仔细检查了我的代码,解码过程按预期进行:

  • 我使用提取压缩数据MediaExtractor
  • 将其排入编解码器
  • 从编解码器中取出输出缓冲区。

问题是,当最后一个可用的输入缓冲区入队并且输出缓冲区MediaCodec.BUFFER_FLAG_END_OF_STREAM出队时,所有输出缓冲区都是空的!

然后我注意到MediaFormat从音频文件中提取的信息MediaExtractor.getTrackFormat(int track)包含一个未记录的"encoder-delay"密钥。

对于 android 8 及更低版本,该密钥仅存在于使用iTunSMPB标签信息编码的 m4a 剪辑中。这是我为测试文件获得的值的摘要:

iOS-encoded file:           2112 frames
fdkaac with iTunSMPB tag:   2048 frames
fdkaac with ISO delay info: key not present
ffmpeg:                     key not present
ffmpeg (fdk):               key not present

相反,在 Android 9上,我得到以下结果:

iOS-encoded file:           2112 frames
fdkaac with iTunSMPB tag:   2048 frames
fdkaac with ISO delay info: 2048 frames
ffmpeg:                     45158 frames
ffmpeg (fdk):               90317 frames

看起来有些东西发生了变化,MediaExtractor现在能够检索所有被测文件的编码器延迟。这在理论上很好,因为没有"encoder-delay"信息的文件确实显示解码的 PCM 数据有延迟(这是一个已知问题)。

但是......虽然“fdkaac with ISO delay info”的值是正确的,并且导致一个没有初始填充的有效 PCM 文件(终于!),但 ffmpeg 生成的文件的值看起来很大并且可能是错误的!

我知道真正的编码器延迟值对于 ffmpeg 情况是 1024,对于ffmpeg (fdk)情况是 2048 ,我认为提取格式中 key 的高值是文件为空的原因。

事实上,如果我在将"encoder-delay"密钥传递给之前尝试将格式中的密钥设置为 0,MediaCodec.configure(...)我会得到具有预期延迟的正确未压缩数据。

我在这一点上的猜测是MediaExtractor编码器延迟值检索有一些错误,但也许我忽略了一些东西。

由于 ffmpeg 非常流行,我的许多应用程序用户很可能会尝试导入使用它生成的文件,而此时我看不到一个万无一失的解决方案。

有人有建议/解决方法吗?

4

1 回答 1

2

我在 android 问题跟踪器上打开了一个问题: https ://issuetracker.google.com/issues/118398811

现在我刚刚实现了一个解决方法:当MediaFormat对象中存在“编码器延迟”值并且它是一个不可能的高值时,我只是将它设置为零。就像是:

if (format.containsKey("encoder-delay") && format.getInteger("encoder-delay") > THRESHOLD) {
    format.setInteger("encoder-delay", 0);
}

注意:这意味着初始间隙不会被修剪掉,但对于没有此类信息的 M4a 文件,在 android-9 之前的设备上已经存在这种情况。

于 2018-10-25T07:49:39.730 回答