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

最近,Adobe 在 Flash Player 10.1 的 [release notes](http://labs.adobe.com/technologies/flashplayer10/releasenotes.pdf) 中这样写到:

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](http://en.wikipedia.org/wiki/VDPAU) API 用于视频硬件解码 — ffmpeg 和 [mplayer](http://www.mplayerhq.hu/design7/news.html#accelerationtips) 都对它有很好的支持。Mac OS X 呢?让我们罗列一下事实:

* 这里说的解码 — 主要是指视频,尤其是 [H.264](http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC) 视频的解码,因为音频解码功能需要的资源较少,最耗资源的就是 H.264 解码。
* 对于有 [nVIDIA 9400M](http://www.nvidia.com/object/product_geforce_9400m_g_us.html) 显卡的机器,Snow Leopard 的 [QuickTime X](http://www.apple.com/macosx/what-is-macosx/quicktime.html) 支持使用*未公开*的接口来硬件解码特定 profile (low, standard) 的 H.264 视频,这个兼容性虽然没有人详细测试过,但可以认为是比较有限的。QuickTime X 最大的限制是限死了对封装 (container) 格式的支持,在它支持的封装格式中,能使用 H.264 视频编码也就是 mp4 和 mov 两种,而在电脑上观看的高清视频大部分是 [mkv](http://en.wikipedia.org/wiki/Matroska) 封装的。
* 传统的 QuickTime 7 (在 Snow Leopard 中仍然可用) 虽然可以通过 [Perian](http://perian.org) 支持更多的格式,没有见到具体的报告讨论 QuickTime 7 能否使用 Apple 的 H.264 硬解码模块 ([AppleVAH264HW.component](http://arstechnica.com/apple/news/2008/10/digging-into-new-macbooks-support-of-gpu-accelerated-h-264.ars)),[Perian 社区](http://groups.google.com/group/perian-discuss)的讨论也没提到能否利用这个模块来解码 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](http://coreavc.com/) 开发者的 CorePlayer Pro,这是一个封闭的播放器,在 Mac 上不提供单独的解码器;至于 GPGPU 方案,市场上现有的只有 CoreAVC 基于 CUDA 的解码技术,他们确实有计划开发基于 OpenCL 的解码,但看起来仍然是一个很漫长的周期,而其他开发者因为缺乏足够的经验,很难涉足这个领域 — 没错,视频编解码的水很深。

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

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

Text Layout with Core Text (slides)

I did a talk in [Cocoaheads Beijing](http://cocoaheadsbj.org) yesterday on the topic “Text Layout with Core Text”, and [here](http://jjgod.org/docs/slides/TextLayoutWithCoreText.pdf) is my slides (4 MB, pdf).

slides download

I may write a more detailed article on [Core Text](http://en.wikipedia.org/wiki/Core_Text) typesetting later, stay tuned.

Effective code injection for Snow Leopard 64-bit apps?

Recently I’m looking for a way to make [Safari AdBlock](http://burgersoftware.com/en/safariadblock) support Safari in 64-bit.

64-bit apps stopped loading [Input Manager](http://www.cocoadev.com/index.pl?InputManager) bundles, so it is impossible to use [SIMBL](http://www.culater.net/software/SIMBL/SIMBL.php) in 64-bit apps either. Neither does [PlugSuit](http://infinite-labs.net/plugsuit/) (which is using [mach_inject](http://rentzsch.com/mach_inject/)). The [web plugin solution](http://www.switchersblog.com/2007/08/the-end-of-th-2.html) suggested by 1Password team stopped working too. Frankly, I think it’s time to start looking for a better code injection technique for 64-bit Snow Leopard apps seriously.

What still works?

1. [Scripting Additions](http://developer.apple.com/technotes/tn/tn1164.html), it’s what 1Password using for all its plugins (for Safari, WebKit, Camino, NetNewsWire, etc.), basically it works for all apps that support Apple Scripts, but the problem is you’ll need to run a daemon to watch the launch of these apps, then send a custom Apple event to trigger the initialization of the code you inject.

2. Use a DYLD constructor as initialization point, then use `DYLD_INSERT_LIBRARIES` or techniques described [in this faq](http://www.mikeash.com/?page=pyblog/friday-qa-2009-01-30-code-injection.html) to trigger the load of this bundle or dynamic library. The problem is you will need all the users to modify their environment variables, which is cumbersome.

Is there any other solution? I’ll be glad to hear.

说说对今早 WWDC Keynote 的想法

1. 大家一边纷纷怪 Keynote 没新意,一边在发布前使劲的刺探情报,所以这两年的热点产品往往在发布之前就被曝得体无完肤,就好比自己先去看了剧透,然后看电影的时候痛斥没有惊喜。

2. MacBook Pro 的升级对我而言算是个惊喜,本来以为要到 10 月以后才会发布的东西,居然现在就出来了,不过亮点不多,比如期望的 Nehalem 移动平台,显然不可能这么早就出现。

3. Safari 4 正式版的界面不得不说是一个妥协的结果,本来 Beta 中需要很大勇气的创新被巨大的反对意见逼退了,Apple 没有 “take one step further” 去继续改进,而是直接放弃了尝试,回到了传统的 tab 布局。总体来看,这个界面设计缺乏深思熟虑,不会很讨人喜欢。

4. Snow Leopard 针对用户的大更新不多,小改进不少,总的而言会是一个让人 (尤其是比较喜欢保持软件更新的人) 用着很舒服的平台。

5. 针对开发者的特性许多都是头一次出现的,不应该期望它们在 10.6 中就足够成熟,其实大部分都还是给有尝试热情的、勇敢的开发者,以及基于这些底层技术作二次开发的厂商做热身的。这算是为以后的改进搭下了一个很好的基础,单从底层技术而言,Apple 这个公司对于业界的影响也越来越大了,对 OpenCL, GCD, LLVM, WebKit 等技术的推动充分说明了这一点。

6. iPhone OS 3.0 的改进,主要是希望利用大量 app 的先发优势压倒 Palm webOS 这样的新秀,然而对比起来玩弄的噱头越来越多,聚焦在一个好用的手机、好用的交流、联络工具上的改进越来越少,所以相比 Palm webOS 显得格外苍白。毫无疑问的,iPhone OS 3.0 升级让这个系统更完整、更有潜力了,但 Apple 自己开发的内置 app 却乏善可陈,这是自今年 3 月的发布会以来最大的遗憾,更遗憾的是 Apple 没能在 WWDC 前解决它。

7. iPhone 3GS 正是那种“被剧透得体无完肤”的产品,所以其实也没什么好说的,我自己没什么升级的打算,但对于还没买过 iPhone 的人来说,不失为一个好选择,当然,这是在解锁版的价格合适的前提下。

Packaging for Installation on Mac OS X

在 Mac OS X 下为程序打包该用什么格式?这是个很有趣的问题,首先,显然绝大部分的应用程序都应该:

* 使用手动安装,也就是一个独立的 `.app`,里面通过 `@executable_path/../Frameworks/` 的方式[链接所有依赖的第三方库](http://www.cocoadevcentral.com/articles/000042.php),也就是说,不往系统相关目录里乱放东西。这是 Apple 官方的 Software Delivery Guide 中[推荐的安装方式](http://developer.apple.com/documentation/DeveloperTools/Conceptual/SoftwareDistribution/Introduction/Introduction.html)。
* 支持用 Sparkle 这样的自动更新框架,实际上符合上一点的也就自然可以用 Sparkle 完全自动的完成更新。
* 用 `.zip` 格式分发。为什么不用 `.dmg`?因为 `.dmg` 不容易直接解压,挂载速度比 `.zip` 慢得多,增加拖动的手续,所以我支持这篇 [zip vs dmg](http://0xced.blogspot.com/2006/11/zip-vs-dmg.html) 的观点。

SunPinyin 安装界面

但是如果遇到特殊的情况呢?比如你写的是一个**非得**往系统目录 (`/Library/…`) 安装内容的软件呢?比如我最近参与改进的 [SunPinyin 输入法](http://blogs.sun.com/yongsun/entry/sunpinyin_for_mac_leopard_updated6),就必须打包为 Installer 支持的 `.pkg` 格式安装了,否则很难确保软件被正确的安装。

关于这个打包方式,最重要的一点心得是:千万不要用 Apple 自己提供的 [PackageMaker](http://developer.apple.com/DOCUMENTATION/DeveloperTools/Conceptual/PackageMakerUserGuide/index.html),这恐怕是 Apple 开发的最恐怖的一个开发辅助工具了,因为:

* 它必须用图形界面修改内容
* 它保存的 `.pmdoc` 格式非常混乱,而且居然喜欢把*绝对路径*存入文件中
* 不支持 [Installer Plugins](http://developer.apple.com/samplecode/InstallerPluginSample/listing1.html) 扩展

那替代的工具是什么呢?是一个非常棒的第三方工具: [Iceberg](http://s.sudre.free.fr/Software/Iceberg.html),它能:

* 打包出 Mac OS X 10.2+ 以上都支持的 `.pkg` bundle 格式
* 界面比 PackageMaker 友好得多,而且有非常详尽的文档,也很方便调试
* 支持 Installer Plugin

涉及打包、Sparkle 的 appcast 自动生成,Iceberg 的使用等问题,都可以参考 SunPinyin [目前使用的代码](http://src.opensolaris.org/source/xref/nv-g11n/inputmethod/sunpinyin/ime/wrapper/macos/packaging/)。