How to make gstreamer buffer writable in Python?

      Want to modify Gst.Buffer in your Gstreamer application? Next information could be very useful. Estimated reading time: 10m, with code, no images:(

      Gstreamer in Python has some issues when it comes to advanced filters, plugins or behaviour. Most common issues connected to Gst.Buffer. 

#1. Problem

      Let’s create Gst.Buffer from simple string.

      In order to change something in buffer it’s required to map buffer to Gst.MapInfo with read/write flags.

      Data itself is accessible in data field.

     Now, let replace lower case ‘l‘ on upper case ‘L’:

     But you’ll get and error:

     This is because PyGObject does not properly expose struct MapInfo. Look at this issue.

#2. Solution

     Instead of calling Gst.Buffer.map(), use ctypes to call gst_buffer_map() and gst_buffer_unmap(). The solution is taken from stb-tester’s open source projects (Github)

#1. Define Gst.MapInfo in proper way (using C struct):

    Notes:

  • GST_PADDING is default padding for structues (from gstconfig). (GST_PADDING = 4)
  • To understand why used those fields check next example:

#2. Load Gstreamer from shared library

#3. Define input/output arguments for each function with ctypes

      Notes:

  • First look at gst_buffer_map in C. Arguments: GstBuffer* (pointer), GstMapInfo* (pointer), GstMapFlags (int). Returns: bool.
  • GstBuffer* -> c_void_p (in Python to convert Gst.Buffer (GObject) to pointer use hash(buffer), as hashing GObject gives the address of C structure)
  • GstMapInfo* -> ctypes.POINTER(GstMapInfo). For simplicity let define: GST_MAP_INFO_POINTER =  ctypes.POINTER(GstMapInfo)
 #4. Implement own function to make Gst.Buffer writable

Notes:

  • Implemented with @contextmanager in order to simplify function call using “with” statement
 #5. Run tests

      Result:

      Hope it’s works for you too. Code is available here 🙂

Additional:

  • This hack and some more interesting hacks are available here

 

Add a Comment

Your email address will not be published. Required fields are marked *