5

I'm using Python3.6 with GStreamer-1.0 and PyGObject (for python access) to read video frames from a camera (tiscamera).

The frames are gotten via python code and eventually I get a GstBuffer:

import gi
gi.require_version("Gst", "1.0")
from gi.repository import 

# Set up
Gst.init([])
pipeline = Gst.parse_launch("tcambin serial=12345678 name=source ! video/x-raw,format=GRAY8,width=1920,height=1080,framerate=18/1 ! appsink name=sink")
sink = pipeline.get_by_name("sink")
sink.set_property("max-buffers", 10)
sink.set_property("drop", 1)
sink.set_property("emit-signals", 1)
pipeline.set_state(Gst.State.PLAYING)

# Get sample
sample = sink.emit("pull-sample")
buffer = sample.get_buffer()
meta = buffer.get_meta("TcamStatisticsMetaApi")

The type of meta is gi.repository.Gst.Meta, but in C it's actually TcamStatisticsMeta*, as can be understood by looking at tiscamera's c code example 10-metadata.c. The C code there is:

GstBuffer* buffer = gst_sample_get_buffer(sample);
GstMeta* meta = gst_buffer_get_meta(buffer, g_type_from_name("TcamStatisticsMetaApi"));
GstStructure* struc = ((TcamStatisticsMeta*)meta)->structure;

My problem is that in Python, I can't access struct attributes defined in TcamStatisticsMeta. I'm simply missing the casting bit from GstMeta* to TcamStatisticsMeta* and the translation of TcamStatisticsMeta* into a PyObject.

Does anyone have a direction of how this can be done without needing to modify/recompile the gstreamer-1.0 C code? Using Cython perhaps?

I've started using Cython to try and call a C function with data I get from Python. The python object is of type gi.repository.Gst.Buffer and the function should get a GstBuffer*, but I can't find a way to get the struct pointer from the Python object.

Here is my .pxd file:

cdef extern from "gstreamer-1.0/gstmetatcamstatistics.h":
    ctypedef unsigned long GType
    ctypedef struct GstBuffer:
        pass
    ctypedef struct GstMeta:
        pass

    GstMeta* gst_buffer_get_meta(GstBuffer* buffer, GType api)
    GType g_type_from_name(const char* name)

And my .pyx file:

from my_pxd_file cimport GType, g_type_from_name, GstMeta, gst_buffer_get_meta

cdef void c_a(buffer):
    cdef char* tcam_statistics_meta_api = "TcamStatisticsMetaApi"
    cdef GType gt = g_type_from_name(tcam_statistics_meta_api)
    cdef GstMeta* meta = gst_buffer_get_meta(buffer, gt)


def a(buffer):
    c_a(buffer)

And my python file:

# No need to use pyximport as I've cythonized the code in setup.py
from . import my_pyx_file
...
buffer = sample.get_buffer()
my_pyx_file.a(buffer)

This results in a SIGSEGV error:

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

The problem is that I can't cast buffer into a GstBuffer*. Does anyone know how to do that?

Debugging in Pycharm, I can actually see the GstBuffer* address:

<Gst.Buffer object at 0x7f3a0b4fc348 (GstBuffer at 0x7f39ec007060)>

But how do I get this address so I can pass it to gst_buffer_get_meta? Is there a canonical Cython way to do that?

yoel
  • 305
  • 4
  • 17
  • @ead Sorry about that, you're absolutely correct. I've added more information and will keep adding as I get along. Hope someone has an idea how to continue. – yoel Sep 18 '20 at 08:00

0 Answers0