6

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

一切都包含在 python 主代码中,GStreamer 访问是使用pygst完成的。使用 Cython 进行原型设计非常棒,因为它会在代码运行时自动重新编译,而且非常高效。

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

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

4

2 回答 2

5

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/"
)

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

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 解释器,就像什么时候一样多个应用程序被加载到mod_pythonApache 网络服务器的模块中。

于 2013-12-28T19:22:44.420 回答
1

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

于 2013-12-28T18:39:27.670 回答