Pausing DeepStream playback in Python

Please provide complete information as applicable to your setup.

**• Hardware Platform (Jetson / GPU) : NX
• DeepStream Version 5.0
• JetPack Version (valid for Jetson only) 4.4
• TensorRT Version
• NVIDIA GPU Driver Version (valid for GPU only)

Running: deepstream_imagedata-multistream.py

pipeline.set_state(Gst.State.PAUSED)
enum GST_STATE_CHANGE_ASYNC of type Gst.StateChangeReturn
pipeline.set_state(Gst.State.PLAYING)
enum GST_STATE_CHANGE_SUCCESS of type Gst.StateChangeReturn

Playing and pausing in DS is only possible if loop.run is NOT executed. Its unclear what the purpose of the loop object is as inference is done correctly if this code is bypassed. Executing loop.run causes the pipeline object to null out.

loop = GObject.MainLoop()
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect ("message", bus_call, loop)

Hi @foobar.warren
Sorry for late!

The loop object is used to terminate the pipeline on EOS or other exceptions. Could you share sample code to help us understand what exactly you want to get done .

Thanks!

Hi Mchi,
Just by way of observation, I noticed the pipeline object context is lost once inside loop.run, for your python DS sample apps.

Really what I’m after is a post-processing pipeline component example. So once the frame goes thru the inference pipeline component, I’d like access to the generated metadata. I think the SSD example has a post-processing step, but it requires Triton, which I haven’t learned yet.

Hi @foobar.warren,
Where do you want to access the meta data, just after nvinfer plugin?

Regarding accessing metadata, I see an example of the event handler osd_sink_pad_buffer_probe being called and NvDsObjectMeta is processed in test#1.

I was looking for a way do hit a breakpoint inside this handler. Is there any particular debugging technique you know of to achieve this goal?

I’m using vscode and perhaps since the control passes from the app to the pipeline then back to app the debugging context is lost.

maybe you can use gdb

1 Like

Its unclear what the purpose of the loop object is

GStreamer is an asynchronous framework, so it needs a main loop (like asyncio’s Main Loop). When you do this:

bus.connect ("message", bus_call, loop)

You’re saying, "when bus emits the message signal (gets a message), call bus_call and pass it loop as it’s final argument (so bus_call function can quit the main loop when it gets an error).

You can set up or schedule a bunch of things, but not a lot will actually happen until loop.run() at which point it blocks (same as asyncio’s loop.run_forever()). A MainLoop is absolutely mandatory for GStreamer to do much of anything (this applies to a lot of GLib/Gtk stuff in general).

If you want to put a breakpoint inside that handler, I have never done it personally, but gdb appears to be a good suggestion by @mchi and what is recommended when I Google.

That is actually not true. The MainLoop is only required for handling bus messages, and gstreamer works just fine without bus message handling as well (although it’s recommended to at least handle error messages).

If you don’t believe me, see the following answer from Sebastian Droge, one of the main developers of gstreamer: http://gstreamer-devel.966125.n4.nabble.com/Gstreamer-and-GLib-Mainloop-td4682266.html

Moreover, it’s also possible to handle bus messages by having your own custom thread and looping with message = bus.pop_timed(timeout) (although it’s probably easier to just use a signal watch and MainLoop).

For example I run my gstreamer apps without MainLoop, because for some mysterious reason it’s not compatible with opencv highgui backend (QT) and I get a segfault whenever I try to run both in the same process…

1 Like

Oh, I believe you, so thanks for the correction @dorin.clisu.ntt . This example i found (vala) runs fine even without a MainLoop:

// See http://docs.gstreamer.com/x/NwAF
// for a detailed description

public static int main (string[] args) {
	// Initialize GStreamer:
	Gst.init (ref args);


	// Build the pipeline:
	Gst.Element pipeline;
	try {
		pipeline = Gst.parse_launch("playbin uri=http://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm");
	} catch (Error e) {
		stderr.printf("Error: %s\n", e.message);
		return -1;
	}

	// Start playing:
	pipeline.set_state(Gst.State.PLAYING);

	// Wait until error or EOS:
	Gst.Bus bus = pipeline.get_bus();
	bus.timed_pop_filtered(Gst.CLOCK_TIME_NONE, Gst.MessageType.ERROR | Gst.MessageType.EOS);

	// Free resources:
	pipeline.set_state (Gst.State.NULL);
	
	return 0;
}

If I comment out the bus.timed_pop_filtered, it immediately hits the end of context, so something is needed to block. It appears a busy wait or putting the thread to sleep both work, albeit without error handling (in both cases below the Sintel video plays).

	while (true) { }
	Thread.usleep(1000000000);

Huh. I always figured it was the MainLoop that was responsible for buffers traveling down the pipeline but apparently that’s a job for Gst.Task . Neat, but confusing. Thanks!

Re: issues with MainLoop and other event loops are why I’ve put the Gstreamer stuff in a separete process in the past. I’ve seen people re-implement an event loop to check for message as you suggest, or swap Glib’s MainLoop for python’s. but never put much thought into how the buffers themselves flow.