【发布时间】:2018-10-23 10:18:32
【问题描述】:
我有一些自动化测试尝试使用 Android 的 MediaDecoder 和 MediaExtractor 将一些 m4a 文件解码为 PCM 数据。这些文件是使用各种编码器生成的:fdk-aac、ffmpeg(使用 fdk 或默认的 aac 编码器)、iOS。
在 Android 9 上,使用 ffmpeg 创建的剪辑的测试失败,这会导致 PCM 文件为空。在旧版本的 Android 上,相同的剪辑可以正常解码。
我仔细检查了我的代码,解码过程按预期进行:
- 我使用
MediaExtractor提取压缩数据 - 将其加入编解码器
- 从编解码器中取出输出缓冲区。
问题是,当最后一个可用的输入缓冲区入队并且带有MediaCodec.BUFFER_FLAG_END_OF_STREAM 的输出缓冲区出队时,所有输出缓冲区都是空的!
然后我注意到从带有MediaExtractor.getTrackFormat(int track) 的音频文件中提取的MediaFormat 信息包含一个未记录的"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 in提取的格式是文件为空的原因。
事实上,如果我在将"encoder-delay" 键传递给MediaCodec.configure(...) 之前尝试将格式中的"encoder-delay" 键设置为0,我会得到正确的未压缩数据,并具有预期的延迟。
此时我的猜测是MediaExtractor 编码器延迟值检索有一些错误,但也许我忽略了一些东西。
由于 ffmpeg 非常流行,我的许多应用程序用户很可能会尝试导入使用它生成的文件,而此时我还看不到一个万无一失的解决方案。
有人有建议/解决方法吗?
【问题讨论】:
标签: android android-mediacodec aac android-9.0-pie mediaextractor