Arrows cannot be drawn per stream in 4-stream input

Please provide complete information as applicable to your setup.

• Hardware Platform (Jetson / GPU): Jetson
• DeepStream Version: 6.0.1
• JetPack Version (valid for Jetson only):4.6.1
• TensorRT Version:8.2.1
• NVIDIA GPU Driver Version (valid for GPU only)
• Issue Type( questions, new requirements, bugs):question
• How to reproduce the issue ? (This is for bugs. Including which sample app is using, the configuration files content, the command line used and other details for reproducing)
• Requirement details( This is for new requirement. Including the module name-for which plugin or for which sample application, the function description)

Hello.
I want to do the following, but it does not work

Configuration:

  • Input:
    4 streams (rtsp :resolution 1920x1080
  • Pipeline:
    nvstreammux->nvinfer->nvtiler->nvosd->nv3dsink
  • Parameters for nvstreammux:
    streammux.set_property(“width”, 1920)
    streammux.set_property(“height”, 1080)
    streammux.set_property(“batch-size”, 4)
    streammux.set_property(“batched-push-timeout”, 3333333)
    streammux.set_property(‘live-source’, 1)
    streammux.set_property(‘sync-inputs’, 1)
  • Parameters for nvtiler:
    tiler.set_property(“rows”, 2)
    tiler.set_property(“columns”, 2)
    tiler.set_property(“width”, 1920)
    tiler.set_property(“height”, 1080)

Question:

  • The Nvtiler callback registered in the main function does not draw arrows for each stream.
    It appears to be drawing to 1920x1080 specified in streammux. Why is this?
    By the way, I am able to draw a rectangle per stream.

sourc(some):

def tiler_sink_pad_buffer_probe(pad,info,u_data,):

    gst_buffer = info.get_buffer()
    batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
    l_frame = batch_meta.frame_meta_list
    while l_frame is not None:
        try:
           frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
        except StopIteration:
            break

        l_user = frame_meta.frame_user_meta_list
        while l_user is not None:
            try:
                user_meta=pyds.NvDsUserMeta.cast(l_user.data)
                if user_meta.base_meta.meta_type == pyds.NvDsMetaType.NVDSINFER_TENSOR_OUTPUT_META:
                    tensor_meta=pyds.NvDsInferTensorMeta.cast(user_meta.user_meta_data)
                    parse_test_from_tensor_meta(batch_meta, frame_meta, tensor_meta, gst_buffer, 'tiler')
            except StopIteration:
                break
            try: 
                l_user=l_user.next
            except StopIteration:
                break

        try:
            l_frame=l_frame.next
        except StopIteration:
            break
        		
    return Gst.PadProbeReturn.OK

def parse_area_from_tensor_meta(batch_meta, frame_meta):
    draw(batch_meta, frame_meta)

def draw(batch_meta, frame_meta):
    display_meta = pyds.nvds_acquire_display_meta_from_pool(batch_meta)
    display_meta.num_rects = 1
    rect_params = display_meta.rect_params[0]
    rect_params.left = 10
    rect_params.top = 100
    rect_params.width = 500
    rect_params.height = 300
    rect_params.border_width = 5
    rect_params.border_color.set(255, 0, 0, 1)
    rect_params.has_bg_color = 0
    pyds.nvds_add_display_meta_to_frame(frame_meta, display_meta)
        
    display_meta=pyds.nvds_acquire_display_meta_from_pool(batch_meta)
    display_meta.num_arrows = 1
    arrow_params = display_meta.arrow_params[0]
    arrow_params.x1 = 100
    arrow_params.y1 = 400
    arrow_params.x2 = 1000
    arrow_params.y2 = 600
    arrow_params.arrow_width = 5
    arrow_params.arrow_color.set(0, 255, 0, 1.0)
    arrow_params.arrow_head = pyds.NvOSD_Arrow_Head_Direction.END_HEAD
    pyds.nvds_add_display_meta_to_frame(frame_meta, display_meta)

output screen:

Where did you add this API? Could you attach your whole code or just message to me(click on my icon)?

Sorry.
The parse_area_from_tensor_meta is a typo.
The code was wrong.
The correct code is as follows

def tiler_sink_pad_buffer_probe(pad,info,u_data,):

    gst_buffer = info.get_buffer()
    batch_meta = pyds.gst_buffer_get_nvds_batch_meta(hash(gst_buffer))
    l_frame = batch_meta.frame_meta_list
    while l_frame is not None:
        try:
           frame_meta = pyds.NvDsFrameMeta.cast(l_frame.data)
        except StopIteration:
            break

        l_user = frame_meta.frame_user_meta_list
        while l_user is not None:
            try:
                user_meta=pyds.NvDsUserMeta.cast(l_user.data)
                if user_meta.base_meta.meta_type == pyds.NvDsMetaType.NVDSINFER_TENSOR_OUTPUT_META:
                    tensor_meta=pyds.NvDsInferTensorMeta.cast(user_meta.user_meta_data)
                    print(f'dir(tensor_meta)={dir(tensor_meta)}')
                    parse_test_from_tensor_meta(batch_meta, frame_meta)
            except StopIteration:
                break
            try: 
                l_user=l_user.next
            except StopIteration:
                break

        try:
            l_frame=l_frame.next
        except StopIteration:
            break
        		
    return Gst.PadProbeReturn.OK

def parse_test_from_tensor_meta(batch_meta, frame_meta):
    draw(batch_meta, frame_meta)

def draw(batch_meta, frame_meta):
    display_meta = pyds.nvds_acquire_display_meta_from_pool(batch_meta)
    display_meta.num_rects = 1
    rect_params = display_meta.rect_params[0]
    rect_params.left = 10
    rect_params.top = 100
    rect_params.width = 500
    rect_params.height = 300
    rect_params.border_width = 5
    rect_params.border_color.set(255, 0, 0, 1)
    rect_params.has_bg_color = 0
    pyds.nvds_add_display_meta_to_frame(frame_meta, display_meta)
        
    display_meta=pyds.nvds_acquire_display_meta_from_pool(batch_meta)
    display_meta.num_arrows = 1
    arrow_params = display_meta.arrow_params[0]
    arrow_params.x1 = 100
    arrow_params.y1 = 400
    arrow_params.x2 = 1000
    arrow_params.y2 = 600
    arrow_params.arrow_width = 5
    arrow_params.arrow_color.set(0, 255, 0, 1.0)
    arrow_params.arrow_head = pyds.NvOSD_Arrow_Head_Direction.END_HEAD
    pyds.nvds_add_display_meta_to_frame(frame_meta, display_meta)

Could you attach the code that how you use the tiler_sink_pad_buffer_probe?

Hi,
I use tiler_sink_pad_buffer_probe() as follows

Four rtsp URLs are specified as arguments at startup

MUXER_OUTPUT_WIDTH = 1920
MUXER_OUTPUT_HEIGHT = 1080
TILED_OUTPUT_WIDTH = 1920
TILED_OUTPUT_HEIGHT = 1080
OSD_PROCESS_MODE= 0
OSD_DISPLAY_TEXT= 0

def create_pipeline_rtsp(pipeline, args):
    number_sources = len(args) - 1
    # Create nvstreammux instance to form batches from one or more sources.
    streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer")
    if not streammux:
        sys.stderr.write(" Unable to create NvStreamMux \n")
    pipeline.add(streammux)

    for i in range(number_sources):
        print("Creating source_bin ", i, " \n ")
        uri_name = args[i+1]
        source_bin = create_source_bin(i, uri_name)
        if not source_bin:
            sys.stderr.write("Unable to create source bin \n")
        pipeline.add(source_bin)
        padname = "sink_%u" % i
        sinkpad = streammux.get_request_pad(padname)
        if not sinkpad:
            sys.stderr.write("Unable to create sink pad bin \n")
        srcpad = source_bin.get_static_pad("src")
        if not srcpad:
            sys.stderr.write("Unable to create src pad bin \n")
        srcpad.link(sinkpad)

    queue1=Gst.ElementFactory.make("queue","queue1")
    queue2=Gst.ElementFactory.make("queue","queue2")
    queue3=Gst.ElementFactory.make("queue","queue3")
    queue4=Gst.ElementFactory.make("queue","queue4")
    queue5=Gst.ElementFactory.make("queue","queue5")
    pipeline.add(queue1)
    pipeline.add(queue2)
    pipeline.add(queue3)
    pipeline.add(queue4)
    pipeline.add(queue5)

    print("Creating Pgie \n ")
    pgie = Gst.ElementFactory.make("nvinfer", "primary-inference")
    if not pgie:
        sys.stderr.write(" Unable to create pgie \n")

    print("Creating tiler \n ")
    tiler = Gst.ElementFactory.make("nvmultistreamtiler", "nvtiler")
    if not tiler:
        sys.stderr.write(" Unable to create tiler \n")

    print("Creating nvvidconv \n ")
    nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor")
    if not nvvidconv:
        sys.stderr.write(" Unable to create nvvidconv \n")

    print("Creating nvosd \n ")
    nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay")
    if not nvosd:
        sys.stderr.write(" Unable to create nvosd \n")
    nvosd.set_property('process-mode', OSD_PROCESS_MODE)
    nvosd.set_property('display-text', OSD_DISPLAY_TEXT)

    if is_aarch64():
        print("Creating nv3dsink \n")
        sink = Gst.ElementFactory.make("nv3dsink", "nv3d-sink")
        if not sink:
            sys.stderr.write(" Unable to create nv3dsink \n")
    else:
        print("Creating EGLSink \n")
        sink = Gst.ElementFactory.make("nveglglessink", "nvvideo-renderer")
        if not sink:
            sys.stderr.write(" Unable to create egl sink \n")

    streammux.set_property("width", MUXER_OUTPUT_WIDTH)
    streammux.set_property("height", MUXER_OUTPUT_HEIGHT)
    streammux.set_property("batch-size", number_sources)  # 1 or number_sources
    streammux.set_property("batched-push-timeout", 3333333)
    streammux.set_property('live-source', 1)
    streammux.set_property('sync-inputs', 1)
    pgie.set_property("config-file-path", "config.txt")
    pgie.set_property('output-tensor-meta', True)
    tiler.set_property("rows", 2)
    tiler.set_property("columns", 2)
    tiler.set_property("width", TILED_OUTPUT_WIDTH)
    tiler.set_property("height", TILED_OUTPUT_HEIGHT)
    sink.set_property("sync", False)
    sink.set_property("qos", 0)
    sink.set_property("async", 1)

    pipeline.add(pgie)
    pipeline.add(tiler)
    pipeline.add(nvvidconv)
    pipeline.add(nvosd)
    pipeline.add(sink)

    streammux.link(queue1)
    queue1.link(pgie)
    pgie.link(queue2)
    queue2.link(tiler)
    tiler.link(queue3)
    queue3.link(nvvidconv)
    nvvidconv.link(queue4)
    queue4.link(nvosd)
    nvosd.link(queue5)
    queue5.link(sink)  
     
    return pgie, sink, nvosd, tiler

def main(args):

    # Standard GStreamer initialization
    Gst.init(None)

    # Create gstreamer elements
    # Create Pipeline element that will form a connection of other elements
    print("Creating Pipeline \n ")
    pipeline = Gst.Pipeline()

    pgie, sink, nvosd, tiler = create_pipeline_rtsp(pipeline, args)

    # create an event loop and feed gstreamer bus mesages to it
    loop = GLib.MainLoop()
    bus = pipeline.get_bus()
    bus.add_signal_watch()
    bus.connect ("message", bus_call, loop)

    pgiesrcpad = pgie.get_static_pad("src")
    if not pgiesrcpad:
        sys.stderr.write(" Unable to get src pad of pgie \n")
    pgiesrcpad.add_probe(Gst.PadProbeType.BUFFER, pose_sink_pad_buffer_probe, sink)

    tiler_sink_pad = tiler.get_static_pad("sink")
    if not tiler_sink_pad:
        sys.stderr.write(" Unable to get src pad \n")
    else:
        tiler_sink_pad.add_probe(Gst.PadProbeType.BUFFER, tiler_sink_pad_buffer_probe, sink)

    # start play back and listen to events
    print("Starting pipeline \n")
    pipeline.set_state(Gst.State.PLAYING)
    #pipeline.set_state("PLAYING")
    try:
        loop.run()
    except:
        pass
    # cleanup
    pipeline.set_state(Gst.State.NULL)
    #pipeline.set_state("NULL")

if __name__ == '__main__':
    sys.exit(main(sys.argv))

Could you update your DeepStream to the latest version DeepStream 6.4? It’s a bug and we have fixed in the latest version.

Thank you.
I feel better now that it’s resolved.

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