Android 9 AAC解码器输出带有ffmpeg编码文件的零样本

时间:2018-10-23 10:18:33

标签: android mediacodec aac android-9.0-pie mediaextractor

我有一些自动化测试,尝试使用Android的MediaDecoderMediaExtractor将一些m4a文件解码为PCM数据。这些文件是使用各种编码器生成的: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数据中显示了延迟(这是一个已知问题)。

但是...虽然“具有ISO延迟信息的fdkaac具有ISO延迟信息” 情况下的值是正确的,并导致没有初始填充的有效PCM文件(最终!),但ffmpeg的值生成的文件看起来很大,很可能是错误的!

我知道 ffmpeg 情况下的实际编码器延迟值为1024,而 ffmpeg(fdk)情况下的编码器延迟值为2048,我认为键入的高值提取的格式是文件为空的原因。

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

现在,我只是实现了一种解决方法:当MediaFormat对象中存在“ encoder-delay”值并且该值不可能很高时,我只需将其设置为零即可。像这样:

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

注意::这意味着不会消除初始差距,但是对于没有此类信息的M4a文件,在android-9之前的设备上已经存在这种情况。