如何在Cython中编写GStreamer插件



我想制作一种新型音频滤波器的原型。目前,我使用GStreamer返回我的音频缓冲区,Cython对其应用过滤器。然后我将结果发送回GStreamer。

所有内容都封装在python主代码中,GStreamer访问是使用pygst完成的。使用Cython进行原型非常棒,因为它在代码运行时会自动重新编译,而且非常高效。

然而,我觉得如果我可以使用我的Cython文件来生成GStreamer本地插件(这些插件是用C编写的),这会更好。

你对如何实现这一目标有想法吗?

Cython主要是为生成Python扩展模块而设计的,并不是真正为支持其他插件API而设计的。然而,如果你愿意手动调整输出,你可能会得到一些合理的结果。

例如,您可以手工编写一个小的C存根,将模块初始化为gstreamer插件:

#include "Python.h"
#include "gst_plugin.h"
static gboolean plugin_init (GstPlugin *plugin) {
// initialize the extension module
#if PY_MAJOR_VERSION < 3
initgstreamer();
#else
PyInit_gstreamer();
#endif
// call into function exported from cython module
return register_plugin(plugin);
}
GST_PLUGIN_DEFINE (
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
my_filter,
"My filter plugin",
plugin_init,
VERSION,
"LGPL",
"GStreamer",
"http://gstreamer.net/"
)

然后,您可以从cython模块导出register_plugin函数:

cdef public int register_plugin(void *plugin):
# use the gstreamer API in here to register your plugin

然而,这并不是故事的全部。为了实现这一点,您必须以某种方式说服gstreamer将libpython加载到其进程中,因为cython甚至只是初始化都依赖于它。您可能需要初始化Python解释器一点,然后您的代码才能按您的意愿运行。您需要为要使用的所有gstreamer插件注册API定义cython存根。如果其他人试图在同一个gstreamer过程中做同样的事情,可能会全部失败。

因此,说到这里,一个更简单的方法可能是制作一个gstreamer插件,连接到Python代码,然后使用该插件访问您的cython模块。通过这种方式,python嵌入是显式的,您将有机会在加载代码之前正确初始化python解释器。这样的插件对于其他试图做与您类似项目的人来说可能很有用,无论是使用cython还是ctypes模块。

这样的插件实际上是一个颠倒的PyGST:它将Python作为库加载到GStreamer中,而不是将GStreamer作为库加载在Python中。可能有一些PyGST代码可以重复使用,但每个进程只能包含一个Python,因此使用此机制的多个模块都需要共享同一个Python解释器,就像将多个应用程序加载到Apache Web服务器的mod_python模块中一样。

Cython生成Python扩展模块,这些模块需要在Python上下文中初始化才能使用。我认为,除非您与gstreamer开发人员合作,首先将Python模块支持添加到gstreamer中,否则您想要实现的目标是不可能的。

最新更新