Gstreamer (python) with appsrc need-data is called more times than FPS is set

Hi guys,

I do use appsrc which grabs image from redis.
This pipeline is used in video , and therefore I want appsrc to grab image only 30times a second.
Even though I have in CAPS framerate 30/1 , need-data callback calls function at least 80times/second making my compute resources on jetson nano exhausted. Why is that and how can I fix it?

This is my appsrc element

 appsrc = Gst.ElementFactory.make("appsrc", "source")
    appsrc.set_property("format", Gst.Format.TIME)
    appsrc.set_property("do-timestamp", True)
    appsrc.set_property("is-live", True)

    appsrc.set_property(
        "caps",
        Gst.Caps.from_string(
            "video/x-raw,width=(int){width},height=(int){height},format=(string){format},framerate={framerate}/1".format(
                width=frame.shape[1],
                height=frame.shape[0],
                format=FLAGS.format,
                framerate=30,
            )
        ),
    )
    appsrc.connect("need-data", get_frame_buffer, (db, FLAGS.input_key))

and this is my get_frame_buffer function which just grabs image, converts it to bytes and then wraps it to GstBuffer

# python callback for the 'need-data' signal
def get_frame_buffer(appsrc, length, udata):
    tic = time()
    # grab frame from basler
    frame = get_frame(*udata)
    if frame is None:
        appsrc.emit("end-of-stream")
    else:
        appsrc.emit("push-buffer", Gst.Buffer.new_wrapped(frame.tobytes()))
    toc = time()
    logging.debug("Framerate: {:.1f} fps".format(1 / (toc - tic)))

thanks in advance

I mean, I am aware that i could do like blocking sleep in my get_frame_buffer function

# python callback for the 'need-data' signal
def get_frame_buffer(appsrc, length, udata):
    tic = time()
    # grab frame from basler
    frame = get_frame(*udata)
    if frame is None:
        appsrc.emit("end-of-stream")
    else:
        appsrc.emit("push-buffer", Gst.Buffer.new_wrapped(frame.tobytes()))
        # sleep for the desired fps
        sleep(1 / FLAGS.fps - (time() - tic))
    logging.debug("Framerate: {:.1f} fps".format(1 / (time() - tic)))
    return Gst.FlowReturn.OK

but i believe there should be more reasonable way

Hi,
We don’t have experience about running this in python. Have tried this C sample and it works fine:
gst-rtsp-server/test-appsrc.c at 1.14.5 · GStreamer/gst-rtsp-server · GitHub

Not sure if it helps, but please set timestamp to GstBuffer for a try.

Hello @DaneLLL ,
I have modified my appsrc to similar behavior as in shared code

# python callback for the 'need-data' signal
def get_frame_buffer(appsrc, length, udata):

    # grab frame from basler
    frame = get_frame(*udata)
    if frame["frame"] is None:
        appsrc.emit("end-of-stream")
    else:
        # convert frame["frame"] to buffer and add frame["timestamp"] to metadata
        buf = Gst.Buffer.new_wrapped(frame["frame"].tobytes())
        buf.pts = frame["timestamp"]
        # push buffer to appsrc
        appsrc.emit("push-buffer", buf)

    return Gst.FlowReturn.OK

aka adding timestamp to each buffer, and to be precise adding timestamp from frame as it was captured in camera. However it is not changing gstreamers behaviour , still pooling that get_frame_buffer as crazy :)

Hope someone will see this and be able to help.

Hi,
Search online and find a sample similar to this use-case:
send opencv frame over gstreamer pipe using python · GitHub

You may try it and check if the issue is observed. If it happens in both you sample and this sample, it may be a bug in python gstreamer.

Hi,
The issue look specific to python(python 2). Please try python3.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.