avatarJason Kim

Summary

The web content provides guidance on writing GStreamer plugins using Python, detailing the development process, benefits, and practical examples.

Abstract

The article "Writing GStreamer Plugin with Python" delves into the creation of GStreamer plugins using Python, emphasizing the language's ease of development, flexibility, and rapid prototyping capabilities. It outlines the benefits of using Python over C for plugin development, including its high-level, interpreted nature, which simplifies the coding process. The article specifies the required environment, including Ubuntu 22.04, Python 3.10, and GStreamer 1.20.3, and provides instructions for installing GStreamer Python bindings on Ubuntu 22.04. It includes example source code for two plugins, pyvideotestsrc and pydentity, demonstrating how to wrap a videotestsrc element and how to create a simple identity transform element, respectively. The article also shows how to test these plugins and concludes by suggesting a cost-effective AI service, ZAI.chat, as an alternative to ChatGPT Plus.

Opinions

  • The author suggests that Python's simplicity and readability make it a preferable language for writing GStreamer plugins compared to C.
  • Python's dynamic typing, extensive standard library, and community support are seen as advantages for GStreamer plugin development.
  • The dynamic nature of Python is praised for its suitability in quickly prototyping and testing new ideas for GStreamer plugins.
  • The article promotes the use of the gst-python examples as a starting point for plugin development.
  • The author endorses ZAI.chat as a cost-effective AI service alternative to ChatGPT Plus, implying it offers similar performance and functionality.

Writing GStreamer Plugin with Python

This post shows how to write GStreamer plugins in Python with examples.

A GStreamer plugin is a software component that can be used in the GStreamer pipeline. People write new plugins to add new functionalities, such as supporting new audio or video formats, applying effects, interacting with hardware devices etc.

There are several benefits to writing GStreamer plugins with Python:

Ease of Development

Python is a high-level, interpreted language that is known for its simplicity and readability. Writing GStreamer plugins in Python can be faster and easier than using C. Python’s dynamic typing, extensive standard library, and large community of developers and resources can further streamline the development process.

Flexibility and Extensibility

Python’s dynamic nature allows developers to quickly prototype and test new ideas, making it well-suited for exploring new GStreamer plugin concepts.

Rapid Prototyping and Integration

Python’s interactivity and rapid development cycle make it ideal for rapid prototyping of GStreamer plugins. The ability to quickly write, test, and iterate on code can accelerate the development process and allow developers to experiment with different plugin designs.

Environment

  • Ubuntu 22.04
  • Python 3.10
  • GStreamer 1.20.3

Install GStreamer Python Bindings on Ubuntu 22.04

$ sudo apt install python3-gst-1.0 gstreamer1.0-python3-plugin-loader

After installing the packages, gst-inspect-1.0 python should return the Plugin details as follow;

If the command doesn’t work, delete the GStreamer registry cache file and try again;

$ rm ~/.cache/gstreamer-1.0/registry.x86_64.bin

Reference

https://github.com/GStreamer/gst-python/

The provided link contains several Python examples of GStreamer plugins which could serve as a great starting point for your own plugin development. I use one of them, identity.py to check the buffer.pts.

Example #1

Unlike other source examples, this example uses Gst.Bin as the base class and uses the videotestsrc inside the Bin. pyvideotestsrc is just a wrapper of videotestsrc element.

Source Code

#!/usr/bin/env python3
#
# $ GST_PLUGIN_PATH=./ gst-launch-1.0 pyvideotestsrc num-buffers=50 ! ximagesink

import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GLib, GObject

Gst.init(None)

ANY_SRC_TEMPLATE = Gst.PadTemplate.new("src",
                                       Gst.PadDirection.SRC,
                                       Gst.PadPresence.ALWAYS,
                                       Gst.caps_from_string("ANY"))
DEFAULT_NUM_BUFFER = -1

class PyTestSrc(Gst.Bin):
    '''
    '''
    GST_PLUGIN_NAME = "pyvideotestsrc"
    __gstmetadata__ = ("videotestsrc in python",
                       "Source",
                       "videotestsrc element",
                       "Jason Kim")
    __gproperties__ = {
        "num-buffers": (int,
                        "num-buffers",
                        "Number of Buffers to produce",
                        -1, # unlimited
                        GLib.MAXINT,
                        DEFAULT_NUM_BUFFER,
                        GObject.ParamFlags.READWRITE)
    }
    __gsttemplates__ =(ANY_SRC_TEMPLATE)

    def __init__(self):
        super(PyTestSrc, self).__init__()
        self._videotestsrc = Gst.ElementFactory.make("videotestsrc", "source")
        self._videotestsrc.set_property("num-buffers", DEFAULT_NUM_BUFFER)
        self.add(self._videotestsrc)

        self.add_pad(
            Gst.GhostPad.new_from_template(
                "src",
                self._videotestsrc.get_static_pad("src"),
                ANY_SRC_TEMPLATE
            ))

    def do_get_property(self, prop):
        if prop.name == "num-buffers":
            return self._videotestsrc.get_property(prop.name)
        else:
            raise AttributeError('unknown property %s' % prop.name)

    def do_set_property(self, prop, value):
        if prop.name == "num-buffers":
            return self._videotestsrc.set_property(prop.name, value)
        else:
            raise AttributeError('unknown property %s' % prop.name)


GObject.type_register(PyTestSrc)
__gstelementfactory__ = (PyTestSrc.GST_PLUGIN_NAME, Gst.Rank.NONE, PyTestSrc)

Test the plugin

Example #2

This example is from the link above. This prints the buffer’s pts. I tweaked the code a little bit to print out the pts less frequently.

Source Code

#!/usr/bin/env python3
#
# $ GST_PLUGIN_PATH=./ GST_DEBUG=python:4 gst-launch-1.0 videotestsrc  ! pydentity ! ximagesink

import gi
gi.require_version('Gst', '1.0')
gi.require_version('GstBase', '1.0')

from gi.repository import Gst, GObject, GstBase
Gst.init(None)

ANY_SRC_TEMPLATE = Gst.PadTemplate.new("src",
                                       Gst.PadDirection.SRC,
                                       Gst.PadPresence.ALWAYS,
                                       Gst.Caps.new_any())
ANY_SINK_TEMPLATE = Gst.PadTemplate.new("sink",
                                        Gst.PadDirection.SINK,
                                        Gst.PadPresence.ALWAYS,
                                        Gst.Caps.new_any())
#
# Simple Identity in python
#
class Pydentity(GstBase.BaseTransform):
    GST_PLUGIN_NAME = "pydentity"
    __gstmetadata__ = ('identity in python',
                       'Transform',
                       'python identity element',
                       'Jason Kim')
    __gproperties__ = {}
    __gsttemplates__ = (ANY_SRC_TEMPLATE, ANY_SINK_TEMPLATE)

    def __init__(self):
        super().__init__()
        self.cnt = 0

    def do_transform_ip(self, buffer):
        if self.cnt == 40:
            Gst.info("buffer.pts: %s" % (Gst.TIME_ARGS(buffer.pts)))
            self.cnt = 0

        self.cnt += 1

        return Gst.FlowReturn.OK

GObject.type_register(Pydentity)
__gstelementfactory__ = (Pydentity.GST_PLUGIN_NAME, Gst.Rank.NONE, Pydentity)

Test the plugin

Combine the two plugins

pyvideotestsrc and pydentity can be used together;

GST_PLUGIN_PATH=./ GST_DEBUG=python:4 gst-launch-1.0 pyvideotestsrc  ! pydentity ! ximagesink
Gstreamer
Python
Recommended from ReadMedium