Stream and save video on client Gstreamer

I have found the best options for my needs, but need some help to combine them.
I can save video with the following code:

(Jetson Nano)
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=300 do-timestamp=true ! image/jpeg,width=1920,height=1080,framerate=30/1 ! queue ! avimux ! filesink location=test.avi

I stream video to rasberry with the following code:

Host (Jetson Nano):
gst-launch-1.0 v4l2src device=/dev/video0 ! ‘video/x-raw, format=YUY2’ ! nvvidconv ! ‘video/x-raw(memory:NVMM), width=640, height=480’ ! tee name=t t. ! omxh264enc ! h264parse ! rtph264pay config-interval=1 ! udpsink host=10.0.0.9 port=5000

Client (Rasberry Pi4):
gst-launch-1.0 udpsrc port=5000 ! ‘application/x-rtp, encoding-name=H264, payload=96’ ! rtph264depay ! h264parse ! avdec_h264 ! xvimagesink


The setup is:
Camera: IMX 322 Sony
Host: Jetson Nano
Client: Rasberry Pi 4
Communication: Ethernet

Question: How can I combine these files to get displayed and saved video on Rasberry Pi4 (Client)?

I have done lots of research and tried to use countless “tee” links in different formats, but no one will work. Anyone can help me?

Hi eliasf16,

The tee element is the one that you need but, in my experience, this element is a bit tricky, sometimes fails due to missing queues on the branches. Sadly I don’t have a hardware setup right now to the your pipelines but I can suggest you an example with tee.

From your stream pipeline (which already has a tee) just let’s add another branch and queues to save the file:

gst-launch-1.0 v4l2src device=/dev/video0 ! ‘video/x-raw, format=YUY2’ ! nvvidconv ! ‘video/x-raw(memory:NVMM), width=640, height=480’ ! queue ! tee name=t t. ! queue ! omxh264enc ! h264parse ! rtph264pay config-interval=1 ! udpsink host=10.0.0.9 port=5000 t. ! queue ! nvvidconv ! 'video/x-raw, width=1920,height=1080,framerate=30/1' ! nvjpegenc ! queue ! avimux ! filesink location=test.avi

Please, test the pipeline above, this has both features together but it may fails due to caps or something else. You can add GST_DEBUG=3 gst-launch-1.0 … to the pipeline to obtain information from errors.

Let me know if this help you, otherwise attach error log to check the possible issue.

Greivin F.

2 Likes

Hi,
Please try Greivin’s suggestion. It should work fine.

Hello, thank you so much! This saves and send file on the host machine.
The challenge is that the video being sent and the video being saved are of the same quality.
I want it to be viewed and stored on the client computer.

The actual video being viewed does not have to be high quality. but the video that is saved I want as high quality as possible. I think that the video needs to be in jpeg file in order to provide the highest quality possible.

v4l2-ctl --device /dev/video0 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
Index : 0
Type : Video Capture
Pixel Format: ‘MJPG’ (compressed)
Name : Motion-JPEG
Size: Discrete 1920x1080
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Size: Discrete 1280x720
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Size: Discrete 800x600
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Size: Discrete 640x480
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Size: Discrete 640x360
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Size: Discrete 352x288
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Size: Discrete 320x240
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)
Size: Discrete 1920x1080
Interval: Discrete 0.033s (30.000 fps)
Interval: Discrete 0.040s (25.000 fps)
Interval: Discrete 0.067s (15.000 fps)

Index       : 1
Type        : Video Capture
Pixel Format: 'YUYV'
Name        : YUYV 4:2:2
	Size: Discrete 640x480
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.067s (15.000 fps)
	Size: Discrete 800x600
		Interval: Discrete 0.067s (15.000 fps)
	Size: Discrete 640x360
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.067s (15.000 fps)
	Size: Discrete 352x288
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.067s (15.000 fps)
	Size: Discrete 320x240
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.067s (15.000 fps)
	Size: Discrete 640x480
		Interval: Discrete 0.033s (30.000 fps)
		Interval: Discrete 0.040s (25.000 fps)
		Interval: Discrete 0.067s (15.000 fps)

The code you gave me is a huge step in my project already. Thanks!

1 Like

Hi,

Great, I’m happy that the pipeline worked.

This pipeline first downscale from camera input to 640x480, the tee here does the following:

  • Encoded 640x480 to h264 with omxh264enc, this may suffer quality issues, check encoder’s properties to fine-tune the output, example the properties profile and bitrate may help here, Run gst-inspect-1.0 omxh264enc for more information related to encoder’s properties.

  • The second branch upscale from 640x480 to 1920x1080, this scaling may introduce quality issues.

Regarding your suggestion, avimux already uses jpeg.
If you are referring to the video stream quality, you can change the encoder/payloader from h264 to jpeg in case you can give it a try.
Just remember that depayloader on receiving pipeline must change to jpeg.

Greivin F.