GTK 4 中的媒体

显示动态图像变得越来越重要。GTK 4 将使 GTK 应用程序更容易显示动画;无论是程序化动画、webm 文件还是直播流。

一切皆可绘制

在了解动画之前,有必要花一点时间了解 GTK 用于可绘制内容的底层抽象。在 GTK 2 和 3 中,主要是 GdkPixbuf:你加载一个文件,然后得到一个像素数据块(或多或少以单一格式)。如果你想让它动起来,可以使用 GdkPixbufAnimation,但可以公平地说,它并不是一个非常成功的 API。

GTK 4 引入了一个新的 API,称为 GdkPaintable,其灵感来自 CSS Houdini 工作。它非常灵活——任何你认为可以绘制的东西都可以成为 GdkPaintable。内容可以是可调整大小的(如 svg),也可以随时间变化(如 webm)。

通常显示图像内容的窗口小部件,如 GtkImage 或 GtkPicture 知道如何使用可绘制对象。过去以某种形式生成像素数据的许多东西现在都可以表示为可绘制对象:纹理图标,甚至 窗口小部件

如果你有更专业的需求,任何可以在 GtkSnapshot 中捕获的内容都可以使用 gtk_snapshot_to_paintable() 转换为可绘制对象。如果你制作了一个想要绘制可绘制对象的自定义窗口小部件,这非常简单。只需调用 gdk_paintable_snapshot()

开始动画

正如我之前所说,可绘制对象可以随时间改变其内容。它所需要做的就是发出 ::contents-changed 信号,像 GtkPicture 这样的窗口小部件就会正确地更新它们的显示。

那么,我们从哪里获得一个内容会变化的 GdkPaintable 呢?我们可以使用 GTK 4 的内置 GtkMediaFile API 从文件中加载它。这是一个高级 API,类似于 GstPlayer:你放入一个 URI,然后得到一个具有 play() 函数和 pause() 函数的对象,并且可以作为可绘制对象使用。

GTK 附带了 GtkMediaFile 的两个实现,一个使用 gstreamer,另一个使用 ffmpeg。由于我们不想让这两者成为 GTK 的硬依赖,所以它们是可加载模块。

你可以打开 GTK 检查器来找出正在使用的是哪一个

保持控制

GtkMediaFile API 是 gtk4-widget-factory 在其首页上演示动画 GTK 徽标的方式

正如你所看到的,它不仅仅是一张动态图片,还有媒体控件——通过使用 GtkVideo 窗口小部件,你可以免费获得这些。

超越基础

从文件中加载动画可能不是那么令人兴奋,所以这里是另一个 示例,它更进一步。这是一个结合了 GtkVideo、libportalpipewire 的周末小项目,用于演示如何在 GTK 应用程序中显示视频流。

坏消息是我们还没有为支持代码找到永久的家(一个 GstSink、一个 GdkPaintable 和一个 GtkMediaStream)。它不适合 GTK,因为正如前面提到的,我们不想依赖 gstreamer,而且它也不适合 gstreamer,因为 GTK 4 尚未发布。我们肯定会在不久之后解决这个问题,因为用几行代码将 gstreamer 管道转换为可绘制对象非常方便。

好消息是,代码的核心只有几行

fd = xdp_portal_open_pipewire_remote_for_camera (portal);
stream = gtk_gst_media_stream_new_for_pipewire_fd (fd, NULL);
gtk_video_set_media_stream (video, stream);