Hello everyone,
I’m working on designing an efficient slicer in DeepStream using GStreamer, and so far I’ve managed to split a 1920×1080 frame into overlapping tiles (212 px overlap) by chaining nvvideoconvert elements. However, because of DeepStream’s pipeline structure, the streams don’t seem to arrive in strict order, so I can’t guarantee I’m scanning each frame tile sequentially. My question is: is there a way within DeepStream to force the frames—or stream inputs—to be delivered in order?
Here’s a minimal example of my current setup (no overlap), including comments that explain each step:
def add_sources_to_pipeline(self):
for i, uri in enumerate(self.camera_urls):
if uri.startswith(“rtsp://”):
self.is_live = True
source_bin = create_source_bin(i, uri)
if not source_bin:
sys.stderr.write(f"Failed to create source bin: source-bin-{i}\n")
continue
# Add the source bin to the pipeline…
self.pipeline.add(source_bin)
# …then request a sink pad from nvstreammux and link the bin’s src pad to it
sink_pad_name = f"sink_{i}"
sink_pad = self.streammux.get_request_pad(sink_pad_name)
if not sink_pad:
sys.stderr.write(f"Failed to request sink pad: {sink_pad_name}\n")
continue
src_pad = source_bin.get_static_pad("src")
if not src_pad:
sys.stderr.write(f"Failed to get src pad from source-bin-{i}\n")
continue
src_pad.link(sink_pad)
# Parameters for tiling the 1920×1080 frame
frame_width = 640
frame_height = 640
overlap = 212
y_offset = 440
# Create two rows (y=0 and y=440) and four columns of tiles
for row in range(2):
for col in range(4):
crop_x = col * (frame_width - overlap) # each tile shifts 428 px horizontally
crop_y = row * y_offset # 0 for first row, 440 for second
crop_w = frame_width
crop_h = frame_height
# Clamp width if it would exceed the 1920px boundary
if crop_x + crop_w > 1920:
crop_w = 1920 - crop_x
index = row * 4 + col + 1
print(f"Tile {index}: x1,y1=({crop_x},{crop_y}) → "
f"x2,y2=({crop_x+crop_w},{crop_y+crop_h})")
# Create a new source bin for this tile
source_bin = create_source_bin(index, uri)
if not source_bin:
sys.stderr.write(f"Failed to create source bin: source-bin-{index}\n")
continue
self.pipeline.add(source_bin)
sink_pad_name = f"sink_{index}"
sink_pad = self.streammux.get_request_pad(sink_pad_name)
if not sink_pad:
sys.stderr.write(f"Failed to request sink pad: {sink_pad_name}\n")
continue
src_pad = source_bin.get_static_pad("src")
if not src_pad:
sys.stderr.write(f"Failed to get src pad from source-bin-{index}\n")
continue
# Insert an nvvideoconvert element to crop this region
nvconv_name = f"nvvideoconvert-{index}"
nvvideoconvert = Gst.ElementFactory.make("nvvideoconvert", nvconv_name)
if not nvvideoconvert:
sys.stderr.write(f"Failed to create element: {nvconv_name}\n")
continue
# Set the source crop rectangle
nvvideoconvert.set_property(
"src-crop",
f"{crop_x}:{crop_y}:{crop_w}:{crop_h}"
)
self.pipeline.add(nvvideoconvert)
# Link the pads: source_bin → nvvideoconvert → streammux
nv_src_pad = nvvideoconvert.get_static_pad("src")
nv_sink_pad = nvvideoconvert.get_static_pad("sink")
src_pad.link(nv_sink_pad)
nv_src_pad.link(sink_pad)
Here’s an example video where I slice the frames using GStreamer with no overlap:
Thanks in advance for any pointers on enforcing sequential frame/stream delivery in DeepStream!
