I’m developing a multi-camera video compositing application for different vehicles using GStreamer on NVIDIA Jetson Orin AGX with ZED X One cameras. The application needs to dynamically switch between different camera view layouts (single camera, dual camera, quad view, etc.) at runtime based on operator commands, similar to switching between different security camera views.
My current pipeline architecture consists of multiple nvarguscamerasrc elements feeding into an nvcompositor, followed by nvv4l2h265enc for hardware encoding and udpsink for network streaming. Each camera source goes through nvvidconv for format conversion and capsfilter for format specification before connecting to the compositor. The pipeline works perfectly for static layouts, producing smooth 30fps H.265 encoded video streams.
The core issue I’m facing is that when I attempt to dynamically update the nvcompositor sink pad properties (xpos, ypos, width, height, alpha) to change camera layouts at runtime, the video feed freezes completely. The pipeline doesn’t crash or throw errors, but no new buffers flow through the system after the property update. I can see in my logs that the g_object_set calls on the compositor sink pads complete successfully, and the properties appear to be set correctly when I query them back, but the video output becomes static.
I’ve tried several approaches to solve this problem. Initially, I attempted to pause the entire pipeline using gst_element_set_state(pipeline, GST_STATE_PAUSED) before updating properties and then resuming with GST_STATE_PLAYING, but this causes the same freezing behavior. I also tried using pad blocking with gst_pad_add_probe and GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM to temporarily halt data flow during property updates, but this also results in frozen output. I experimented with sending custom events and EOS events to force buffer flushing, and even tried gst_pad_mark_reconfigure on the compositor sink pads, but none of these approaches restored proper data flow.
Looking at my implementation, I create all camera branches at startup and connect them to the nvcompositor with initial layout properties. When a layout change is requested, I iterate through each branch and call g_object_set on their respective compositor sink pads to update the positioning and scaling properties. The branches themselves remain connected throughout this process. I’m not unlinking or relinking any pads, just updating the compositor’s internal layout properties.
The expected behavior would be that updating these properties should cause the compositor to immediately reflect the new layout in subsequent output frames, similar to how other GStreamer elements handle dynamic property changes. However, it seems like the nvcompositor either doesn’t support dynamic property updates properly, or there’s a specific sequence of operations required to make it work correctly.
I’m wondering if this is a known limitation of the nvcompositor element, or if there’s a proper way to handle dynamic layout changes. Should I be using a different approach entirely, such as maintaining separate pipelines for each layout and switching between them? Is there a specific order for updating compositor properties or additional steps required after property changes? Are there alternative compositor elements that might handle dynamic updates better?
The application needs to switch layouts frequently during operation, so recreating the entire pipeline for each change introduces unacceptable latency and potential frame drops. Any insights into proper dynamic compositor usage or alternative approaches for runtime layout switching would be greatly appreciated.