Low image quality when using usb cam in Deepstream

Please provide complete information as applicable to your setup.

• Jetson Xavier AGX
*• DeepStream Version 6 *
• JetPack Version newest

When I use my Deepstream pipeline with a usb-cam input and get an image with a buffer probe, the image quality is really poor compared to the capability of the camera. How can I improve camera image quality within the pipeline? I need the image data for further processing.

Here is my Pipeline:

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()
    
    if not pipeline:
        sys.stderr.write(" Unable to create Pipeline \n")
        
    # Source element for reading from the file
    print("Creating Source \n ")
    source = Gst.ElementFactory.make("v4l2src", "usb-cam-source")
    if not source:
        sys.stderr.write(" Unable to create Source \n")
        
    caps_v4l2src = Gst.ElementFactory.make("capsfilter", "v4l2src_caps")
    if not caps_v4l2src:
        sys.stderr.write(" Unable to create v4l2src capsfilter \n")
        
    print("Creating Video Converter \n")
    
    # Adding videoconvert -> nvvideoconvert as not all
    # raw formats are supported by nvvideoconvert;
    # Say YUYV is unsupported - which is the common
    # raw format for many logi usb cams
    # In case we have a camera with raw format supported in
    # nvvideoconvert, GStreamer plugins' capability negotiation
    # shall be intelligent enough to reduce compute by
    # videoconvert doing passthrough (TODO we need to confirm this)
    
    # videoconvert to make sure a superset of raw formats are supported
    vidconvsrc = Gst.ElementFactory.make("videoconvert", "convertor_src1")
    if not vidconvsrc:
        sys.stderr.write(" Unable to create videoconvert \n")
    # nvvideoconvert to convert incoming raw buffers to NVMM Mem (NvBufSurface API)
    nvvidconvsrc = Gst.ElementFactory.make("nvvideoconvert", "convertor_src2")
    if not nvvidconvsrc:
        sys.stderr.write(" Unable to create Nvvideoconvert \n")
        
    caps_vidconvsrc = Gst.ElementFactory.make("capsfilter", "nvmm_caps")
    if not caps_vidconvsrc:
        sys.stderr.write(" Unable to create capsfilter \n")

    # 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")
        
    # Use nvinfer to run inferencing on camera's output,
    # behaviour of inferencing is set through config file
    yolo = Gst.ElementFactory.make("nvinfer", "yolov5-inference")
    #key = Gst.ElementFactory.make("nvinfer", "key-inference")
    if not yolo:
        sys.stderr.write(" Unable to create yolov5 \n")
    #if not key:
    #    sys.stderr.write(" Unable to create key detector \n")
        
    # Use convertor to convert from NV12 to RGBA as required by nvosd
    nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor")
    if not nvvidconv:
        sys.stderr.write(" Unable to create nvvidconv \n")
        
    # Create OSD to draw on the converted RGBA buffer
    nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay")
    if not nvosd:
        sys.stderr.write(" Unable to create nvosd \n")
    # Finally render the osd output
    if is_aarch64():
        print("Creating nv3dsink \n")
        sink = Gst.ElementFactory.make("nv3dsink", "nv3d-sink")
        #sink = Gst.ElementFactory.make("fakesink", "fakesink")
        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")
             
    print("Playing cam %s " %args[1])
    caps_v4l2src.set_property('caps', Gst.Caps.from_string("video/x-raw, framerate=30/1"))
    caps_vidconvsrc.set_property('caps', Gst.Caps.from_string("video/x-raw(memory:NVMM)"))
    source.set_property('device', args[1])
    streammux.set_property('width', 1920)
    streammux.set_property('height', 1080)
    streammux.set_property('batch-size', 1)
    streammux.set_property('batched-push-timeout', 4000000)
    #streammux.set_property('batched-push-timeout', 200)
    yolo.set_property('config-file-path', "/home/racing15/workspace/src/driverless-software/vision_ehawk/config/vision_yolo_config.txt")
    #key.set_property('config-file-path', "vision_key_config.txt")
    # Set sync = false to avoid late frame drops at the display-sink
    sink.set_property('sync', 0)                                                        
    
    
    print("Adding elements to Pipeline \n")
    pipeline.add(source)   ### THIS IS THE CAMERA INPUT
    pipeline.add(caps_v4l2src)
    pipeline.add(vidconvsrc)
    pipeline.add(nvvidconvsrc)
    pipeline.add(caps_vidconvsrc)
    pipeline.add(streammux)
    pipeline.add(yolo)   ### THIS IS YOLO INFERENCE
    pipeline.add(nvvidconv)  ###
    pipeline.add(nvosd)
    pipeline.add(sink)
    
    
    # we link the elements together
    # v4l2src -> nvvideoconvert -> mux -> 
    # nvinfer -> nvvideoconvert -> nvosd -> video-renderer
    print("Linking elements in the Pipeline \n")
    source.link(caps_v4l2src)
    caps_v4l2src.link(vidconvsrc)
    vidconvsrc.link(nvvidconvsrc) # as it should be
    #vidconvsrc.link(caps_vidconvsrc)
    nvvidconvsrc.link(caps_vidconvsrc) # as it should be
    sinkpad = streammux.get_request_pad("sink_0")
    if not sinkpad:
        sys.stderr.write(" Unable to get the sink pad of streammux \n")
    srcpad = caps_vidconvsrc.get_static_pad("src")
    if not srcpad:
        sys.stderr.write(" Unable to get source pad of caps_vidconvsrc \n")
    srcpad.link(sinkpad)
    streammux.link(yolo)
    yolo.link(nvvidconv)
    nvvidconv.link(nvosd)
    #nvvidconv.link(sink)
    nvosd.link(sink)
    #### key ???? ####   source -> caps_v4l2src -> vidconvsrc -> nvvidconvsrc  ... streammux -> yolo -> nvvidconv ->  nvvidconv -> nvosd -> sink 
    
    
    # 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)
    
    # Lets add probe to get informed of the meta data generated, we add probe to
    # the sink pad of the osd element, since by that time, the buffer would have
    # had got all the metadata.
    #osdsinkpad = nvosd.get_static_pad("sink")
    osdsinkpad = nvosd.get_static_pad("sink")
    if not osdsinkpad:
        sys.stderr.write(" Unable to get sink pad of nvosd \n")
        
    osdsinkpad.add_probe(Gst.PadProbeType.BUFFER, self.osd_sink_pad_buffer_probe, 0)
    # start play back and listen to events
    print("Starting pipeline \n")
    pipeline.set_state(Gst.State.PLAYING)
    try:
        loop.run()
    except:
        pass
    # cleanup
    pipeline.set_state(Gst.State.NULL)

Can you use “v4l2-ctl -d /dev/video0 --list-formats-ext” to get the capability of your camera?

Thank you for the fast reply. I am using a GoPro 7 with a capture card. When I use a Ubuntu camera app the image quality is fine. Here are the capabilities:
racing15@ubuntu:/opt/nvidia/deepstream/deepstream-6.2/sources/deepstream_python_apps/apps$ v4l2-ctl -d /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Type: Video Capture

[0]: 'MJPG' (Motion-JPEG, compressed)
	Size: Discrete 1920x1080
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 1600x1200
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 1360x768
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 1280x1024
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 1280x960
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 1280x720
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.020s (50.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 1024x768
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.020s (50.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 800x600
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.020s (50.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 720x576
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.020s (50.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 720x480
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.020s (50.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 640x480
		Interval: Discrete 0.017s (60.000 fps)
		Interval: Discrete 0.020s (50.000 fps)
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
[1]: 'YUYV' (YUYV 4:2:2)
	Size: Discrete 1920x1080
		Interval: Discrete 0.200s (5.000 fps)
	Size: Discrete 1600x1200
		Interval: Discrete 0.200s (5.000 fps)
	Size: Discrete 1360x768
		Interval: Discrete 0.125s (8.000 fps)
	Size: Discrete 1280x1024
		Interval: Discrete 0.125s (8.000 fps)
	Size: Discrete 1280x960
		Interval: Discrete 0.125s (8.000 fps)
	Size: Discrete 1280x720
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 1024x768
		Interval: Discrete 0.100s (10.000 fps)
	Size: Discrete 800x600
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
		Interval: Discrete 0.200s (5.000 fps)
	Size: Discrete 720x576
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
		Interval: Discrete 0.200s (5.000 fps)
	Size: Discrete 720x480
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
		Interval: Discrete 0.200s (5.000 fps)
	Size: Discrete 640x480
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.050s (20.000 fps)
		Interval: Discrete 0.100s (10.000 fps)
		Interval: Discrete 0.200s (5.000 fps)

I found out now, if I reduce that FPS I get better Image quality. Arent there other ways? I would assume a jetson xavier can handle at least 30 fps in full hd.

The problem is not caused by DeepStream but the usage with your camera. Your camera supports multiple formats and multiple resolutions, framerates. You should tell the v4l2src plugin which format and resolution you want to enable. Your camera can output MJPEG videos with higher resolution, please add JPEG decoder into the pipeline.

E.G.
gst-launch-1.0 v4l2src ! 'image/jpeg,width=1920,height=1080,framerate=30/1' ! nvv4l2decoder mjpeg=1 ! nvvideoconvert ! 'video/x-raw,format=NV12' ! nvstreammux width=1920 height=1080 batch-size=1 ! fakesink

Hello, i tried to add the JPEG decoder into my pipeline but I dont get it to work, since I dont find other examples for this case. Can you tell my what I am doing wrong?

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()
    
    if not pipeline:
        sys.stderr.write(" Unable to create Pipeline \n")
        
    # Source element for reading from the file
    print("Creating Source \n ")
    source = Gst.ElementFactory.make("v4l2src", "usb-cam-source")
    if not source:
        sys.stderr.write(" Unable to create Source \n")
        
        
    print("Creating Decoder \n")
    decoder = Gst.ElementFactory.make("nvv4l2decoder", "nvv4l2-decoder")
    if not decoder:
        sys.stderr.write(" Unable to create Nvv4l2 Decoder \n")
        
    caps_v4l2src = Gst.ElementFactory.make("capsfilter", "v4l2src_caps")
    if not caps_v4l2src:
        sys.stderr.write(" Unable to create v4l2src capsfilter \n")
        
    print("Creating Video Converter \n")
    # Adding videoconvert -> nvvideoconvert as not all
    # raw formats are supported by nvvideoconvert;
    # Say YUYV is unsupported - which is the common
    # raw format for many logi usb cams
    # In case we have a camera with raw format supported in
    # nvvideoconvert, GStreamer plugins' capability negotiation
    # shall be intelligent enough to reduce compute by
    # videoconvert doing passthrough (TODO we need to confirm this)
    
    # videoconvert to make sure a superset of raw formats are supported
    vidconvsrc = Gst.ElementFactory.make("videoconvert", "convertor_src1")
    if not vidconvsrc:
        sys.stderr.write(" Unable to create videoconvert \n")
    # nvvideoconvert to convert incoming raw buffers to NVMM Mem (NvBufSurface API)
    nvvidconvsrc = Gst.ElementFactory.make("nvvideoconvert", "convertor_src2")
    if not nvvidconvsrc:
        sys.stderr.write(" Unable to create Nvvideoconvert \n")
        
    caps_vidconvsrc = Gst.ElementFactory.make("capsfilter", "nvmm_caps")
    if not caps_vidconvsrc:
        sys.stderr.write(" Unable to create capsfilter \n")

    # 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")
        
    # Use nvinfer to run inferencing on camera's output,
    # behaviour of inferencing is set through config file
    yolo = Gst.ElementFactory.make("nvinfer", "yolov5-inference")
    #key = Gst.ElementFactory.make("nvinfer", "key-inference")
    if not yolo:
        sys.stderr.write(" Unable to create yolov5 \n")
    #if not key:
    #    sys.stderr.write(" Unable to create key detector \n")
        
    # Use convertor to convert from NV12 to RGBA as required by nvosd
    nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor")
    if not nvvidconv:
        sys.stderr.write(" Unable to create nvvidconv \n")
        
    # Create OSD to draw on the converted RGBA buffer
    nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay")
    if not nvosd:
        sys.stderr.write(" Unable to create nvosd \n")
    # Finally render the osd output
    if is_aarch64():
        print("Creating nv3dsink \n")
        sink = Gst.ElementFactory.make("nv3dsink", "nv3d-sink")
        #sink = Gst.ElementFactory.make("fakesink", "fakesink")
        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")
             
    print("Playing cam %s " %args[1])
    decoder.set_property('mjpeg', 1)
    caps_v4l2src.set_property('caps', Gst.Caps.from_string(" image/jpeg, width=1920, height=1080, framerate=30/1"))
    caps_vidconvsrc.set_property('caps', Gst.Caps.from_string("video/x-raw(memory:NV12)"))
    source.set_property('device', args[1])
    streammux.set_property('width', 1920)
    streammux.set_property('height', 1080)
    streammux.set_property('batch-size', 1)
    streammux.set_property('batched-push-timeout', 4000000)
    #streammux.set_property('batched-push-timeout', 200)
    #streammux.set_property('bitrate', 10000)
    yolo.set_property('config-file-path', "/home/racing15/workspace/src/driverless-software/vision_ehawk/config/vision_yolo_config.txt")
    #key.set_property('config-file-path', "vision_key_config.txt")
    # Set sync = false to avoid late frame drops at the display-sink
    sink.set_property('sync', 0)       
    #sink.set_property('bitrate', 5000)                                                       
    
    
    print("Adding elements to Pipeline \n")
    pipeline.add(source)   ### THIS IS THE CAMERA INPUT
    pipeline.add(caps_v4l2src)
    pipeline.add(vidconvsrc)
    pipeline.add(decoder) ### Added the mjpeg decoder to the pipeline
    pipeline.add(nvvidconvsrc)
    pipeline.add(caps_vidconvsrc)
    pipeline.add(streammux)
    pipeline.add(yolo)   ### THIS IS YOLO INFERENCE
    pipeline.add(nvvidconv)  ###
    pipeline.add(nvosd)
    pipeline.add(sink)
    
    
    # we link the elements together
    # v4l2src -> nvvideoconvert -> mux -> 
    # nvinfer -> nvvideoconvert -> nvosd -> video-renderer
    print("Linking elements in the Pipeline \n")
    source.link(caps_v4l2src)
    caps_v4l2src.link(vidconvsrc)
    #vidconvsrc.link(nvvidconvsrc) # as it should be
    vidconvsrc.link(decoder)
    decoder.link(nvvidconvsrc)
    nvvidconvsrc.link(caps_vidconvsrc)
    sinkpad = streammux.get_request_pad("sink_0")
    if not sinkpad:
        sys.stderr.write(" Unable to get the sink pad of streammux \n")
    srcpad = caps_vidconvsrc.get_static_pad("src")
    if not srcpad:
        sys.stderr.write(" Unable to get source pad of caps_vidconvsrc \n")
    srcpad.link(sinkpad)

    streammux.link(yolo)
    yolo.link(nvvidconv)
    nvvidconv.link(nvosd)
    nvosd.link(sink)
    
    
    # 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)
    
    # Lets add probe to get informed of the meta data generated, we add probe to
    # the sink pad of the osd element, since by that time, the buffer would have
    # had got all the metadata.
    osdsinkpad = nvosd.get_static_pad("sink")
    if not osdsinkpad:
        sys.stderr.write(" Unable to get sink pad of nvosd \n")
        
    osdsinkpad.add_probe(Gst.PadProbeType.BUFFER, self.osd_sink_pad_buffer_probe, 0)
    # start play back and listen to events
    print("Starting pipeline \n")
    pipeline.set_state(Gst.State.PLAYING)
    try:
        loop.run()
    except:
        pass
    # cleanup
    pipeline.set_state(Gst.State.NULL)

The command you sent me also doesn’t work …
gst-launch-1.0 v4l2src ! ‘image/jpeg,width=1920,height=1080,framerate=30/1’ ! nvv4l2decoder mjpeg=1 ! nvvideoconvert ! ‘video/x-raw,format=NV12’ ! nvstreammux width=1920 height=1080 batch-size=1 ! fakesink
WARNING: erroneous pipeline: could not link nvvideoconvert0 to nvstreammux0, nvstreammux0 can’t handle caps video/x-raw, format=(string)NV12

Can you try this pipeline?
gst-launch-1.0 v4l2src ! 'image/jpeg,width=1920,height=1080,framerate=30/1' ! nvv4l2decoder mjpeg=1 ! nvvideoconvert ! 'video/x-raw(memory:NVMM),format=NV12' ! nvstreammux width=1920 height=1080 batch-size=1 ! fakesink

If it fails, can you post the error log?

I tried the command and it failed. Here is the error log:

gst-launch-1.0 v4l2src ! ‘image/jpeg,width=1920,height=1080,framerate=30/1’ ! nvv4l2decoder mjpeg=1 ! nvvideoconvert ! ‘video/x-raw(memory:NVMM),format=NV12’ ! nvstreammux width=1920 height=1080 batch-size=1 ! fakesink
WARNING: erroneous pipeline: could not link nvvideoconvert0 to nvstreammux0, nvstreammux0 can’t handle caps video/x-raw(memory:NVMM), format=(string)NV12

Can you try this pipeline?
gst-launch-1.0 v4l2src ! 'image/jpeg,width=1920,height=1080,framerate=30/1' ! nvv4l2decoder mjpeg=1 ! nvvideoconvert ! 'video/x-raw(memory:NVMM),format=NV12' ! mux.sink_0 nvstreammux width=1920 height=1080 batch-size=1 name=mux ! fakesink

Hi, sorry for no response. I was gone for a few days. This Piepline seems to work!

Setting pipeline to PAUSED …
Opening in BLOCKING MODE
Pipeline is live and does not need PREROLL …
Setting pipeline to PLAYING …
New clock: GstSystemClock
NvMMLiteOpen : Block : BlockType = 277
NVMEDIA: Reading vendor.tegra.display-size : status: 6
NvMMLiteBlockCreate : Block : BlockType = 277
^Chandling interrupt.
Interrupt: Stopping pipeline …
Execution ended after 0:00:14.456275063
Setting pipeline to NULL …
Freeing pipeline …

started and ended without any error.

I tried to bring the name = mux and batchsize = 1 properties into my python Piepline.

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()
    
    if not pipeline:
        sys.stderr.write(" Unable to create Pipeline \n")
        
    # Source element for reading from the file
    print("Creating Source \n ")
    source = Gst.ElementFactory.make("v4l2src", "usb-cam-source")
    if not source:
        sys.stderr.write(" Unable to create Source \n")
        
        
    print("Creating Decoder \n")
    decoder = Gst.ElementFactory.make("nvv4l2decoder", "nvv4l2-decoder")
    if not decoder:
        sys.stderr.write(" Unable to create Nvv4l2 Decoder \n")
        
    caps_v4l2src = Gst.ElementFactory.make("capsfilter", "v4l2src_caps")
    if not caps_v4l2src:
        sys.stderr.write(" Unable to create v4l2src capsfilter \n")
        
    print("Creating Video Converter \n")
    # Adding videoconvert -> nvvideoconvert as not all
    # raw formats are supported by nvvideoconvert;
    # Say YUYV is unsupported - which is the common
    # raw format for many logi usb cams
    # In case we have a camera with raw format supported in
    # nvvideoconvert, GStreamer plugins' capability negotiation
    # shall be intelligent enough to reduce compute by
    # videoconvert doing passthrough (TODO we need to confirm this)
    
    # videoconvert to make sure a superset of raw formats are supported
    vidconvsrc = Gst.ElementFactory.make("videoconvert", "convertor_src1")
    if not vidconvsrc:
        sys.stderr.write(" Unable to create videoconvert \n")
    # nvvideoconvert to convert incoming raw buffers to NVMM Mem (NvBufSurface API)
    nvvidconvsrc = Gst.ElementFactory.make("nvvideoconvert", "convertor_src2")
    if not nvvidconvsrc:
        sys.stderr.write(" Unable to create Nvvideoconvert \n")
        
    caps_vidconvsrc = Gst.ElementFactory.make("capsfilter", "nvmm_caps")
    if not caps_vidconvsrc:
        sys.stderr.write(" Unable to create capsfilter \n")

    # 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")
        
    # Use nvinfer to run inferencing on camera's output,
    # behaviour of inferencing is set through config file
    yolo = Gst.ElementFactory.make("nvinfer", "yolov5-inference")
    #key = Gst.ElementFactory.make("nvinfer", "key-inference")
    if not yolo:
        sys.stderr.write(" Unable to create yolov5 \n")
    #if not key:
    #    sys.stderr.write(" Unable to create key detector \n")
        
    # Use convertor to convert from NV12 to RGBA as required by nvosd
    nvvidconv = Gst.ElementFactory.make("nvvideoconvert", "convertor")
    if not nvvidconv:
        sys.stderr.write(" Unable to create nvvidconv \n")
        
    # Create OSD to draw on the converted RGBA buffer
    nvosd = Gst.ElementFactory.make("nvdsosd", "onscreendisplay")
    if not nvosd:
        sys.stderr.write(" Unable to create nvosd \n")
    # Finally render the osd output
    if is_aarch64():
        print("Creating nv3dsink \n")
        sink = Gst.ElementFactory.make("nv3dsink", "nv3d-sink")
        #sink = Gst.ElementFactory.make("fakesink", "fakesink")
        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")
             
    print("Playing cam %s " %args[1])
    decoder.set_property('mjpeg', 1)
    caps_v4l2src.set_property('caps', Gst.Caps.from_string("image/jpeg, framerate=30/1, width=1920, height=1080"))
    #caps_v4l2src.set_property('caps', Gst.Caps.from_string("video/x-raw, framerate=30/1")) # THIS shit only work for YUV -> This is why resolution gets cutted
    caps_vidconvsrc.set_property('caps', Gst.Caps.from_string("video/x-raw(memory:NVMM),format=NV12"))
    source.set_property('device', args[1])
    streammux.set_property('width', 1920)
    streammux.set_property('height', 1080)
    streammux.set_property('name', 'mux')
    streammux.set_property('batched-push-timeout', 4000000)
    streammux.set_property('batch_size', 1)
    #streammux.set_property('batched-push-timeout', 200)
    #streammux.set_property('bitrate', 10000)
    yolo.set_property('config-file-path', "/home/racing15/workspace/src/driverless-software/vision_ehawk/config/vision_yolo_config.txt")
    #key.set_property('config-file-path', "vision_key_config.txt")
    # Set sync = false to avoid late frame drops at the display-sink
    sink.set_property('sync', 0)       
    #sink.set_property('bitrate', 5000)                                                       
    
    
    print("Adding elements to Pipeline \n")
    pipeline.add(source)   ### THIS IS THE CAMERA INPUT
    pipeline.add(caps_v4l2src)
    pipeline.add(vidconvsrc)
    pipeline.add(decoder) ### Added the mjpeg decoder to the pipeline
    pipeline.add(nvvidconvsrc)
    pipeline.add(caps_vidconvsrc)
    pipeline.add(streammux)
    pipeline.add(yolo)   ### THIS IS YOLO INFERENCE
    pipeline.add(nvvidconv)  ###
    pipeline.add(nvosd)
    pipeline.add(sink)
    
    
    # we link the elements together
    # v4l2src -> nvvideoconvert -> mux -> 
    # nvinfer -> nvvideoconvert -> nvosd -> video-renderer
    print("Linking elements in the Pipeline \n")
    source.link(caps_v4l2src)
    caps_v4l2src.link(decoder)
    #vidconvsrc.link(nvvidconvsrc) # as it should be
    #vidconvsrc.link(decoder) 
    #decoder.link(nvvidconvsrc)
    #nvvidconvsrc.link(caps_vidconvsrc)
    sinkpad = streammux.get_request_pad("sink_0")
    if not sinkpad:
        sys.stderr.write(" Unable to get the sink pad of streammux \n")
    #srcpad = caps_vidconvsrc.get_static_pad("src")
    srcpad = decoder.get_static_pad("src")
    if not srcpad:
        sys.stderr.write(" Unable to get source pad of caps_vidconvsrc \n")
    srcpad.link(sinkpad)

    streammux.link(yolo)
    yolo.link(nvvidconv)
    nvvidconv.link(nvosd)
    nvosd.link(sink)
    
    
    # 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)
    
    # Lets add probe to get informed of the meta data generated, we add probe to
    # the sink pad of the osd element, since by that time, the buffer would have
    # had got all the metadata.
    osdsinkpad = nvosd.get_static_pad("sink")
    if not osdsinkpad:
        sys.stderr.write(" Unable to get sink pad of nvosd \n")
        
    osdsinkpad.add_probe(Gst.PadProbeType.BUFFER, self.osd_sink_pad_buffer_probe, 0)
    # start play back and listen to events
    print("Starting pipeline \n")
    pipeline.set_state(Gst.State.PLAYING)
    try:
        loop.run()
    except:
        pass
    # cleanup
    pipeline.set_state(Gst.State.NULL)

Now I get the error:

Creating Pipeline

Creating Source

Creating Decoder

Creating Video Converter

Creating nv3dsink

Playing cam /dev/video0
Adding elements to Pipeline

Linking elements in the Pipeline

Starting pipeline

Opening in BLOCKING MODE
Deserialize yoloLayer plugin: yolo
0:00:07.096998395 8286 0x393ef070 INFO nvinfer gstnvinfer.cpp:680:gst_nvinfer_logger: NvDsInferContext[UID 1]: Info from NvDsInferContextImpl::deserializeEngineAndBackend() <nvdsinfer_context_impl.cpp:1909> [UID = 1]: deserialized trt engine from :/home/racing15/workspace/src/driverless-software/vision_ehawk/config/model_b1_gpu0_fp32.engine
INFO: [Implicit Engine Info]: layers num: 5
0 INPUT kFLOAT data 3x640x640
1 OUTPUT kFLOAT num_detections 1
2 OUTPUT kFLOAT detection_boxes 25200x4
3 OUTPUT kFLOAT detection_scores 25200
4 OUTPUT kFLOAT detection_classes 25200

0:00:07.165510330 8286 0x393ef070 INFO nvinfer gstnvinfer.cpp:680:gst_nvinfer_logger: NvDsInferContext[UID 1]: Info from NvDsInferContextImpl::generateBackendContext() <nvdsinfer_context_impl.cpp:2012> [UID = 1]: Use deserialized engine model: /home/racing15/workspace/src/driverless-software/vision_ehawk/config/model_b1_gpu0_fp32.engine
0:00:07.312562262 8286 0x393ef070 INFO nvinfer gstnvinfer_impl.cpp:328:notifyLoadModelStatus: [UID 1]: Load new model:/home/racing15/workspace/src/driverless-software/vision_ehawk/config/vision_yolo_config.txt sucessfully
NvMMLiteOpen : Block : BlockType = 277
NVMEDIA: Reading vendor.tegra.display-size : status: 6
NvMMLiteBlockCreate : Block : BlockType = 277
Error: gst-stream-error-quark: Internal data stream error. (1): gstbasesrc.c(3072): gst_base_src_loop (): /GstPipeline:pipeline0/GstV4l2Src:usb-cam-source:
streaming stopped, reason not-negotiated (-4)
nvstreammux: Successfully handled EOS for source_id=0

1 Like

The “name=mux” is the syntax for gst-launch tool to identify dynamic pad from the element. It is no use to set it as a property.

You should add a nvvideoconvert and the corresponding capsfilter after nvv4l2decoder and before nvstreammux.

There are python samples of DeepStream here NVIDIA-AI-IOT/deepstream_python_apps: DeepStream SDK Python bindings and sample applications (github.com). Please refer to the samples for how to use nvstreammux with python.

Please make sure you are familiar with GStreamer( https://gstreamer.freedesktop.org/) and pygst(Python GStreamer Tutorial) before you start with DeepStream and pyds.

Thank you for the tipp, I got the pipeline to work!

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