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

Ket*_*tan 2 android android-mediacodec

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

我的问题是:

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

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

我的要求是:

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

我已经使用 ffmpeg 编写了基本播放器,但我无法使用硬件解码器,所以没有遵循它。

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

mst*_*sjo 6

一般来说,MediaCodec 是推荐的一种。

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

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

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

OpenMAX AL 的优点:

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

缺点:

  • 其他一切

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

MediaCodec 的优点:

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

MediaCodec 的缺点:

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

为了提取单个数据包,可以使用 MediaExtractor 类,该类对于静态文件的一些常见文件格式非常有用。我不认为它可用于流媒体,例如碎片 MP4。

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

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