Mac OS X 视频解码技术之现状

最近,Adobe 在 Flash Player 10.1 的 release notes 中这样写到:

In Flash Player 10.1, H.264 hardware acceleration is not supported under Linux and Mac OS. Linux currently lacks a developed standard API that supports H.264 hardware video decoding, and Mac OS X does not expose access to the required APIs. We will continue to evaluate adding the feature to Linux and Mac OS in future releases.

然而实际上 Linux 下已经有了比较完善的 VDPAU API 用于视频硬件解码 — ffmpeg 和 mplayer 都对它有很好的支持。Mac OS X 呢?让我们罗列一下事实:

  • 这里说的解码 — 主要是指视频,尤其是 H.264 视频的解码,因为音频解码功能需要的资源较少,最耗资源的就是 H.264 解码。
  • 对于有 nVIDIA 9400M 显卡的机器,Snow Leopard 的 QuickTime X 支持使用未公开的接口来硬件解码特定 profile (low, standard) 的 H.264 视频,这个兼容性虽然没有人详细测试过,但可以认为是比较有限的。QuickTime X 最大的限制是限死了对封装 (container) 格式的支持,在它支持的封装格式中,能使用 H.264 视频编码也就是 mp4 和 mov 两种,而在电脑上观看的高清视频大部分是 mkv 封装的。
  • 传统的 QuickTime 7 (在 Snow Leopard 中仍然可用) 虽然可以通过 Perian 支持更多的格式,没有见到具体的报告讨论 QuickTime 7 能否使用 Apple 的 H.264 硬解码模块 (AppleVAH264HW.component),Perian 社区的讨论也没提到能否利用这个模块来解码 H.264,同时用 ffmpeg 来解析 mkv 封装格式。
  • 因为 Mac OS X 下所有显卡的驱动都是通过 Apple 分发的 — 显卡厂商自己没有发布过这些驱动,也没有权力提供用户空间的库来调用自己显卡中的硬件解码 API (实际上这显然还是得内核支持的),如果 Apple 不公开视频硬解码 API,造成的结果就是没有一个第三方的应用程序能利用 Mac 上完全充足的硬件 (9400M, 9600M 等等) 来解码 H.264 视频。
  • 除了硬件解码之外的方案还有纯软件解码和基于 GPGPU 的方案,前者,Mac OS X 下可用的是 ffmpeg 的 H.264 解码功能,mplayer, Perian, Movist 等播放器用的都是它,还有一种是 CoreAVC 开发者的 CorePlayer Pro,这是一个封闭的播放器,在 Mac 上不提供单独的解码器;至于 GPGPU 方案,市场上现有的只有 CoreAVC 基于 CUDA 的解码技术,他们确实有计划开发基于 OpenCL 的解码,但看起来仍然是一个很漫长的周期,而其他开发者因为缺乏足够的经验,很难涉足这个领域 — 没错,视频编解码的水很深。

以上这些事实造成的恶果是,Mac 用户空守着性能充足的显卡,在 OS X 上播放起 1080p 视频时往往 CPU 占用率在 100% 以上,播放高码率的 720p 视频也能到 70% ~ 80%。如果用了硬件解码,CPU 占用率会在 5% 以下,而基于 CUDA 的方案占用率也只有 10% 左右。

那我们能做什么呢?不管出于减少能耗还是减少机器发热的角度,都很有必要向 Apple 提交 bug 报告,要求提供公开的 H.264 硬解码 API。

CoreAVC 与 CorePlayer

CorePlayer Pro for OS X

昨天碰巧翻到一个叫 CoreAVC for Linux 的项目,其实应该之前很早就听说过,因为这个项目在去年五月份的时候曾经被 Google Code 停止提供服务,因为“DMCA complaint”,但现在又恢复了,不过可能 patch 更新得不够及时,不一定能够用在 svn HEAD 的 mplayer 上。

CoreAVC for Linux 到底是个怎么样的项目呢?众所周知的是,CoreAVC 是目前公认软解 H.264 效率最高的解码器,在 Windows 平台有提供,价格是 $15 (不过大部分 Windows 用户都用破解版本的)。开发这个解码器的公司还把它移植到了 Palm, Symbian, Windows CE 等平台上,是移动平台中最有名的一个通用播放器,叫 CorePlayer。

从去年二月开始,CorePlayer 被移植到了 Windows 和 Mac OS X 平台上,但官方没有提供给 Mac OS X 平台的 CoreAVC (假如有的话,应该是 Perian, Flip4Mac 那样作为 QuickTime 插件的形式,但不知道这个公司出于什么考虑,并没有像 Windows 平台那样提供)。而 Linux 平台下也没有提供公开销售的版本。所以 CoreAVC for Linux 就是为了能在 Linux 平台下使用这个解码器而产生的。

虽然细节比较复杂,我现在也不大了然,但原理也不难理解,修改 mplayer 的 DirectShow 支持代码,类似调用 RealMedia 的 DirectShow 插件那样来调用 CoreAVC 的 DirectShow 插件。开发者说有两种修改方法

  1. 使用一个外部程序 dshowserver 来提供服务,修改 mplayer 使之能够支持 dshowserver,这种方法能够适用于 x86_64 和 ia32
  2. 直接修改 mplayer 的 Win32 dshow 代码使之支持 CoreAVC,只适用于 ia32

作者说第一种是推荐的方法,但不能用于 Windows 和 Mac。而第二种完全没有提到具体步骤,也没见到具体的 patch。

正巧看到 CorePlayer Pro for OS X,虽然没提供试用版本,但好在也不算贵 ($17),就买了一个试试。下面是一点结论:

No AC3 support in CorePlayer OS X

  1. 最大的问题是音频解码支持很弱,不支持 AC3 解码,不支持 DTS 解码,而且发布之后一年内始终没得到解决,开发者很有点言而无信,一开始在去年二月说“数周内”能解决,到 12 月还没提供,又改说我们可能要依赖平台提供的功能实现 (Windows 下用 DirectShow, Mac 下用 Core Audio),这也没问题,可这都二月了,还没解决。感觉相比移动平台,这个公司并不怎么注重桌面平台的支持。

  2. 界面很土,非要做跨平台的界面,结果用起来非常不方便,更不用说完全不 Mac 化了。

  3. 解码 H.264 的效率确实比其他任何 Mac 平台的解码器都要好,手头一个 1080p 的 Fight Club 的 BDRe, 用 Plex 时的 CPU 占用率在 120% ~ 150% 左右,用 CorePlayer 时占用率在 75% ~ 80% 左右。

  4. 不支持外挂字幕,而且短期内不打算支持。

总的说来,我觉得他们最大的决策错误就是不提供单独的 CoreAVC,非要自己做播放器,结果给自己带来了过重的开发负担,比如界面、音频编码器这些,如果只提供一个 QuickTime 插件,就压根不需要他们操心了。H.264 的解码效率是好,但也没有好到超过一个数量级的程度,在 Snow Leopard 和新一代 Mac 提供了显卡硬解码支持的背景下,就更难让人看好这个产品的前景了。

用 MEncoder 编码 H. 264 流

MEncoder 是常用的离线编码器,属于 mplayer 项目的一部分,这里介绍了怎样用 MEncoder 编码常见的视频流。

首先,要安装 x264 编码库,mplayer 需要这个库才能加上 H. 264 编码支持:

$ git clone git://git.videolan.org/x264.git
$ cd x264
$ ./configure
$ make && sudo make install

注意 x264 库需要 yasm 汇编器,MacPorts 下可以用 sudo port install yasm 安装。

然后编译 mplayer (包括 mencoder)。

$ svn co svn://svn.mplayerhq.hu/mplayer/trunk mplayer
$ cd mplayer
$ ./configure # 注意输出中是否有 "Checking for x264 ... yes" 字样
$ make && sudo make install

然后就可以调用 MEncoder 了:

$ mencoder input.fmt -o output.fmt -ovc x264 -oac copy -x264encopts \
    bframes=4:b_pyramid:weight_b:pass=1:psnr:bitrate=1500:turbo=1

其中 input.fmt, output.fmt 分别是输入和输出文件,其调用格式见 MEncoder 的文档,而后面 -x264encopts 的参数制定的是 x264 编码参数,这是影响编码质量和速度的地方,文档中也有专门一节详细说明,这里选取的是一个中等偏上的效果。