Android 移动设备 (Snapdragon 820) 上使用 C++ 的播放器的 MediaCodec (NDK) 与 OpenMAX

MediaCodec (NDK) vs. OpenMAX for player on Android mobile (Snapdragon 820) using C++

根据审查​​ Android NDK 下可用的示例,似乎要使用硬件解码器 (OMX.xxx),我们可以使用 MediaCodec 或 OpenMAXAL 接口。

我的问题是:

  1. 这是在移动设备(Android 上的骁龙 820)上使用硬件解码器的最佳方式吗?

  2. 使用 OMX 比使用 MediaCodec 有什么优势吗?当前 Android headers 实际上只支持 MPEG2/.ts mimetype。我希望您可以通过 OpenMax 支持视频(mp4 等)的流式解码 - 评估正确吗?

我的要求是:

  1. 支持普通容器流式播放音视频
  2. 利用移动硬件 (GPU + DSP) 进行解码。
  3. 逐帧执行图像处理。
  4. 避免为音频和视频编写自己的时间同步。

我用ffmpeg写了基本的播放器,但是我不能使用硬件解码器,所以没有遵循它。

我对可以实现上述目标的任何其他框架(免费或商业)持开放态度。

一般来说,MediaCodec 是推荐的。

在 MediaCodec 在 Android 4.1 中可用之前,在 Android 4.0 中添加了 OpenMAX AL API 作为权宜之计。它实际上已被弃用(尽管我不确定是否有任何官方声明这么说)。

它们在略有不同的抽象级别上运行,并且在大多数情况下,MediaCodec 的工作较少。

使用 OpenMAX AL,您需要提供数据的 MPEG TS 流来解码和播放。它不支持其他容器格式。它也不会让您直接访问解码数据,但会直接播放。但是,它确实负责音频和视频的同步。

OpenMAX AL 的优点:

  • 如果您的输入是 MPEG TS,则可以避免整个额外的步骤
  • 自动处理同步

缺点:

  • 其他一切

使用 MediaCodec,您需要提供单独的数据包进行解码。它本身根本不支持任何容器格式,但作为调用者的您应该处理好这一点。它确实可以让您直接访问解码后的输出数据,但要呈现它,您需要手动处理同步。 (在 Android 6.0 中,有一个新的 class MediaSync,它可以帮助解决这个问题。)

MediaCodec 的优点:

  • 通用、灵活
  • 适用于任何容器(不需要重新打包成 MPEG TS)

MediaCodec 的缺点:

  • 需要您手动处理同步
  • 水平很低,需要你做很多工作

要提取单个数据包,可以使用 MediaExtractor class,这对于静态文件的一些常见文件格式很有用。我不认为它可用于流式传输,例如虽然 MP4 支离破碎。

因此,如果您想对 MPEG TS 以外的格式进行流式播放,您需要自己处理数据包的提取(或使用其他库,例如 libavformat,来完成该任务)。如果您使用 OpenMAX AL,则需要将各个数据包打包回 MPEG TS(使用例如 libavformat)。如果您使用 MediaCodec,您将需要在播放期间处理音频和视频的同步。

如果您需要对解码帧进行处理,MediaCodec 可能是唯一的选择。您可以将解码后的图像数据作为原始 YUV 获取,或者将其获取到可以使用着色器修改的 GL 表面。 (不过,后者也可能使用 OpenMAX AL。)