How to write a GStreamer plug-in in Cython

690 views Asked by At

I want to prototype a new type of audio filter. At the moment I use GStreamer to return a buffer of my audio, and Cython to apply the filter to it. Then I send the result back to GStreamer.

Everything is wrapped in a python main code, the GStreamer accesses are done using pygst. Using Cython to prototype is great because it automatically recompiles when the code is run, and it very efficient.

However I feel this would be even better if I could use my Cython files to produce a GStreamer native plug-in (those are written in C).

Do you have an idea on how that could be achieved?

2

There are 2 answers

1
Martin Atkins On BEST ANSWER

Cython is primarily designed for generating Python extension modules and isn't really designed to support other plugin APIs. However, if you're willing to hand-tweak the output you may be able to get something reasonable.

For example, you could hand-write a small C stub to initialize your module as a gstreamer plugin:

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

You can then export that register_plugin function from your cython module:

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

However, this is not the whole story. In order for this to work you'll have to somehow convince gstreamer to load libpython into its process, since cython depends on it even just to initialize. You'll probably need to initialize the Python interpreter a little before your code will run as you want. You'll need to define cython stubs for all of the gstreamer plugin registration APIs you want to use. And if anyone else tried to do the same thing in the same gstreamer process it'd probably all fall apart.

So with all of this said, a more straightforward path may be to make a gstreamer plugin that bridges to Python code, and then use that plugin to access your cython module. This way the python embedding is explicit and you'll get a chance to initialize the Python interpreter properly before loading your code. Such a plugin could be useful for other people trying to do similar projects to yours, whether using cython or the ctypes module.

Such a plugin would effectively be an upside-down PyGST: it'd load Python as a library into GStreamer, rather than loading GStreamer as a library into Python. There's probably some PyGST code you could re-use for this purpose, but you'd still have the limitation that each process can only contain one Python, so multiple modules using this mechanism would all need to share the same Python interpreter, much as when multiple applications are loaded into the mod_python module for the Apache webserver.

0
kuuko On

Cython generates Python extension modules which need to be initialized within Python context to be useful. I think what you're trying to accomplish won't be possible unless you work with gstreamer developers to add Python module support into gstreamer first.