完结篇:关于 OpenH264 的谢幕
完结篇:关于 OpenH264 的谢幕
2025年3月22日 星期六
可能有人注意到我提到过从 Freedesktop SDK 中移除 OpenH264 的事情。在这里,我将尝试深入探讨一下这段历史、时间线以及导致最终决定的原因。
简单介绍
如果您不熟悉 Freedesktop SDK 项目:它最初是 Alexander Larsson 创建的 1.6 Flatpak runtime image,旨在为 Flatpaks 提供一个与宿主机无关的 "runtime"。此后,在 Codethink 和其他人的帮助下,它成长为一个由社区维护的独立项目,旨在提供 "一个最小的 Linux runtime"。
目前,它包括 org.freedesktop.{Sdk, Platform}
Flatpak runtimes,以及一系列其他的 Flatpak extensions,例如 GL (Mesa) extensions、一个包含 Linux kernel、firmware 和 drivers 等内容的 bootable image stack,以及一系列 Docker images。
这些 runtimes(以及更广泛的 "Flatpak" 技术栈)构成了 GNOME 和 KDE Flatpak runtimes 的基础,它们共同被 2000 多个 Flatpaks 使用。而 bootable stack 和其他部分则构成了 GNOME OS 等的基础。
一些历史
H.264 是当今 使用最广泛 的 codecs 之一,但不幸的是,它拥有多项专利,并且其中一些专利 至今仍然有效。这样的专利阻碍了在基础 runtime 中发布处理该 codec 的软件(因为我们希望它能被各种供应商使用,并且没有任何法律上的灰色地带),这给所有相关人员带来了麻烦。
为了解决这个问题并向用户发布可用的软件,7 年前,在 2019 年,Tom Coldrick 将 OpenH264 extension 的前身,即 html5-codecs extension 添加到了 Freedesktop runtime 中。这个想法很简单——它将包含 FFMPEG 的内部 H.264 decoder,并且会是一个可选的 Flatpak extension,因为我们无法将其发布到 runtime 本身中。
快进几个月,在 2019 年 6 月,Robert McQueen 提出了一个 issue,建议将 Cisco 的 OpenH264(通常也称为 libopenh264
)作为 runtime 的 extension 包含进来。
libopenh264
代码是开源的,但由于 H.264 的专利问题,任何供应商在法律上都不允许发布自己的 binaries。对此的解决方案是直接将 Cisco 未修改的 binaries 分发给用户,这样实际上就可以免除任何 royalties。但问题在于,这些 binaries 有 一些 license restrictions。
因此,Endless 在那个时候为 Flatpak 添加了 extra-data 支持。这意味着 Flatpak extension 的 metadata 只会包含 Cisco binaries 的 URL、checksums 和一个 "recipe",用于从中创建一个可用的 extension。binary 会在最终用户的机器上、在一个 sandbox 内下载,然后执行 "recipe" 来创建一个可用的 extension。这完全避免了各种 "redistribution" 限制,因为我们并没有发布 binary 本身。
然而,这种方法仍然存在最后一个问题。除非最终用户的系统已经下载了 extension,否则 ABI 的一部分将从基础 runtime 本身中缺失。此外,extension 还会被 mount 到 Flatpak sandbox 内的一个非标准位置。因此,为了针对它进行构建,我们需要一个包含在 runtime 本身的 "public" library。
Endless 提出了一个名为 noopenhh264 的 stub OpenH264 library 来解决这个问题。它会与 Cisco 实际的 OpenH264 library 保持 ABI/API 兼容,并位于 runtime 内的 $libdir
中,以便软件链接到 libopenh264 并提供 fallback。在运行时,如果用户下载了实际的 OpenH264 extension,stub library 将通过 Flatpak 的 ld.so config 被 extension 中的 library 覆盖。瞧,您就拥有了一个可用的 OpenH264 设置!
OpenH264 extension 的开始
经过上述繁琐的细节,在 2019 年 8 月,Tom Coldrick 再次添加 了这个 "noopenh264" library 到 runtime,并设置了名为 org.freedesktop.Platform.openh264
的 extension point。
大约在那个时候,"stub" noopenh264 library 的开发也转移到了 Freedesktop SDK 旗下,而这个 extra-data extension 的开发则在一个 专用 repository 中进行。
我之前提到过 extra-data Flatpak extension 的 "recipe",它实际上只是一组在名为 apply_extra
的特殊文件中定义的命令,用于 stage 和 install source。例如,如果它是一个 .deb
文件,那么它将是一系列 ar
或 bsdtar
命令,用于提取它,然后将其安装到 Flatpak 的 extra-data prefix 中。
这里的关键在于,使用任何这样的 utility 都会使 extension 直接依赖于 Flatpak runtime 的特定 branch,以及由此提供的 API/ABI。
由于 Freedesktop runtime 的每个年度主要版本都是一个全新的 ABI,因此我们需要不断地为 OpenH264 extension 衍生新的 branches。例如,对于 libopenh264 的 2.1.0 版本,我们需要 org.freedesktop.Platform.openh264//2.1.0-{18.08, 19.08, 20.08}
branches 用于 extension,依此类推。这将使在 Freedesktop runtime 本身中更新 extension 变得有些繁琐,对于我们的下游 runtimes 也是如此。
作为对此的解决方案,编写了一个自定义的 apply_extra
脚本,它只使用几个标准 headers,并且将 静态构建 到一个固定的 toolchain。
这意味着一些复杂性,因为我们不允许使用大多数可以简化此过程的方法,但同时也意味着最终的 extension 独立于 runtime API/ABI,并且构建在 "NoRuntime" 之上。
缺陷开始显现
尽管 Cisco 在维护方面存在一些问题,但整个设置在很长一段时间内都运行良好。然而,也存在一些缺陷。
我之前说过,每个供应商都必须分发 Cisco 托管在 https://ciscobinary.openh264.org
上的 binaries。不幸的是,至少从 2014 年起,ciscobinary.openh264.org
缺少有效的 SSL certificate,并且 Cisco 既不提供 GPG signatures,也不提供像 SHA-256 这样的强 checksums 用于 binary releases。
这意味着我们无法验证 Cisco binaries 的真实性,从而使我们面临各种 MiTM 和 supply-chain vulnerabilities。我们联系了 Mozilla,并通过 Fedora/RedHat 敦促 Cisco 修复这个问题,正如您可以在线程中看到的评论,但什么也没有发生。
最近(大约在 2024-2025 年),这个 SSL 问题意味着该 domain 开始被 DNS 阻止,这会导致 extra-data 下载失败,从而破坏安装。
另一个关键问题是,如果 upstream 进行了安全修复,然后在发布时破坏了 ABI,我们将无法为 Flatpak runtimes 修复它。通过 extra-data 直接分发 binaries 意味着没有 cherry-picking patches 的余地,并且 ABI 的破坏意味着新版本只能进入 runtime 的新 branch。
我们真的别无选择。如果我们考虑到潜在的缺陷而放弃这个 extension,整个 Flatpak 用户群将失去 H.264 decoding 和 encoding 支持,因此我们不得不接受这种设置。
codecs-extra extension 的开始
大约在 2024 年 6 月,由于一系列安全问题,gdk-pixbuf
放弃了支持 许多 "fringe" loaders。由于我们不断分析稳定 branches 中的 ABI,我们立即注意到了这一变化。
为了弥补 dropped loaders,我们 决定 将 webp, avif, jxl, heif
支持(通过 pixbuf loaders)添加到 runtime。大约在同一时间,Will Thompson 提出了一个 issue,建议将 libheif
添加到 runtime,并将有问题的 HEIC decoder 作为 runtime extension。
因此,我们决定,仅仅为了两个 libheif plugins 而创建另一个 extension 不值得维护,这些应该放在 ffmpeg-full
extension 中(这是 html5-codecs
extension 的继任者,创建于 2019-2020 年左右)。所以我 再次 添加 了 libx265, libde265
和相应的 libheif plugins 到 ffmpeg-full extension。几个月后,我还 添加 了 libx264
到其中,因为我们已经发布了 libx265
,并且 Cisco 的 OpenH264 在 encoding 性能方面不太理想。
我对结果感到满意,所有这些都发布在了 Freedesktop SDK 24.08 中。但有些人因为合理的原因而不满意。
当 ffmpeg-full
extension 被创建时,由于各种原因,它从未被添加到 runtime 或 SDK manifest 中。它作为一个可选的 "app" extension 存在——这意味着 app developers 需要在他们的 Flatpak manifest 中添加一个 short snippet 才能使用它。
这在某些方面是有问题的——有时 app developers 不知道 extension 或者他们需要它,并且 app manifest 中缺少允许使用 extension 的 snippet。这使得用户和开发者的体验有些糟糕。一旦我们开始在 ffmpeg-full
中发布 libheif
,这个问题就变得稍微严重了,因为实际的 libheif library 在 runtime 中,但如果没有 extension,它就无法 decode 任何 HEIF/HEIC image。因此,extension 实际上是强制性的。Albert Astals Cid 是在 Flathub 上维护 KDE Flatpaks 的团队成员,他对此提出了抱怨,并且 Erick555 提出了一个 issue,讨论了将 ffmpeg-full 变成 runtime extension 的可能性。
最初,我出于各种原因不愿意这样做,并且情况再次有点超出我们的控制(这次是由于 H.265 的专利)。但我们询问了各个方面,例如 Endless,并且非常令人惊讶的是,事实证明没有人真正反对将其变为 runtime extension,甚至让它与 runtime 一起自动下载。
随着这个变化,我们决定再次重命名 ffmpeg-full
extension,这次将其命名为 codecs-extra
,以更好地反映它不仅会包含带有 patented parts 的 FFMPEG,还会包含其他处理 patented codecs 的 libraries。这有点类似于发行版为 patented 或 restricted codecs 提供的各种 "meta-packages"。
因此,种子被播下了,我 一个月前 将 ffmpeg-full
切换到 codecs-extra
。
这应该会在 Freedesktop SDK 25.08 中发布。app developers 的主要变化是,不再需要类似这样的内容:
add-extensions:
org.freedesktop.Platform.ffmpeg-full:
version: '24.08'
directory: lib/ffmpeg
add-ld-path: .
在 manifest 中。org.freedesktop.Platform.codecs-extra
将由 runtime 自动安装,并且对用户可用。
放弃 OpenH264 extension
上面的 codecs-extra
更改意味着我们现在真的没有使用 org.freedesktop.Platform.openh264
的用例了,因为 codecs-extra
已经包含了 FFMPEG 的内部 H.264 decoder 和 libx264
encoder。
因此,我最初禁用了自动下载,并考虑到上面讨论的 OpenH264 的各种 "缺陷",我 提出了一个 issue,计划在 26.08 中将其 retire。
当在 libopenh264 中发现了一个 high severity flaw,影响了 2.5.0 及更早版本时,这种情况完全被推翻了。
Freedesktop runtime 的 23.08 branch 被锁定为 2.2.0,并且由于多个 ABI breaks 和 upstream 的 SONAME bumps,无法升级到修复后的版本。如我之前所说,Patching 也不是一个选项。
我们紧急采取措施来缓解这种情况。对于 23.08,我们决定进行 "ABI break" 并 删除 extension,因为更新是不可能的。所以我发表了一个有些吓人的 公告。
但我们仍然有 24.08,它基于 2.4.1,并且由于 ABI bump,再次阻止了更新到修复后的版本,即 2.6.0。
然而,通过查看 2.4.1 和 2.6.0 之间的 commits,并通过 libabigail 分析 library,我们没有找到实际的 ABI break,并且考虑到 Cisco 过去进行了不必要的 SONAME bumps,我们尝试 patching 2.6.0 release 以提供旧的 ABI。
我 mess 与那个 venerable apply_extra,并编写了一个小型 utility 来 patching SONAMEs。但是 upstream 及时指出了 ABI break,这个想法不得不完全放弃。(在与 libabigail maintainer Dodji Seketeli 交谈后,我后来才发现 liabigail 无法显示 ABI break 的原因。)
然后,我们 要求 upstream 提供一个带有旧 ABI 的 patch release 2.5.1,令人惊讶的是,他们在几周内就做到了!这发布在 24.08.15 中,修复了 runtime 的 24.08 branch。
经过所有这些崩溃和额外的 "headache" 之后,我们没有人再觉得发布 openH264 extension 是一个好主意。因此,它被 删除 了 master branch,这意味着对于 25.08+,将不会有任何 org.freedesktop.Platform.openh264
extension 或 noopenh264
。
结语
考虑到所有因素,我认为并希望我们做出了正确的决定,并希望新的 org.freedesktop.Platform.codecs-extra
能够奏效。libx264, libx265
和其他 libraries 都是从 source 构建的,并且不涉及任何 binaries 或 extra-data。因此,从理论上讲,我们应该能够 patching 并修复将来出现的任何问题。
除了这些之外,我有点担心这种设置可能会出现法律问题,以及新的 extension 包含 "太多",但我们将不得不拭目以待事态的发展。
作为一个有趣的 tidbit,我不知道 Fedora 也在使用我们的 org.freedesktop.Platform.openh264
extension。我为他们造成了一些工作,因为 noopenh264 再次搬家,现在搬到了 Fedora,他们正在寻找方法来创建自己的 OpenH264 extension,类似于我们所做的方式。
我希望这里的经验可以帮助将来想要维护此类 extension 的任何人,并且这也将提醒我们,像这样的专利会导致多少额外的工作。