gstorto
Posts: 2
Joined: Mon Dec 18, 2017 2:33 pm

Non-blocking streaming and saving to a file (not a duplicate)

Mon Dec 18, 2017 3:15 pm

I am trying to implement a camera module for my model rocket using a RPi Zero W and the camera module. I have the following objectives:
  • Write video from my Raspberry Pi Camera to disk without any interference from streaming
  • Stream the same video through the network optimizing latency
It is important streaming does not interfere with the video being written to disk, since network connection may be unstable, such as WiFi router may be out of range, etc.

In threads that concern the same problem:

viewtopic.php?t=72405
viewtopic.php?f=43&t=55867
viewtopic.php?f=43&t=76532

The suggestion is to use tee as such:

Code: Select all

#RPi side
FPS="30"
mkfifo netcat_fifo
raspivid -t 0 -md 5 -fps $FPS -o - | tee --output-error=warn netcat_fifo > $video_out &
cat netcat_fifo | netcat -v 192.168.0.101 5000 &> $netcat_log &
And while the stream works perfectly, when there is a network problem, netcat hangs and $video_out loses about 5 seconds of video. So I have tried to use a non-blocking variant of tee called ftee:

https://stackoverflow.com/questions/736 ... nd-logging

And the best results were achieved using:

Code: Select all

#RPi side
FPS="30"
MULTIPIPE="ftee"
mkfifo netcat_fifo
raspivid -t 0 -md 5 -fps $FPS -o - | ./${MULTIPIPE} netcat_fifo > $video_out &
cat netcat_fifo | mbuffer --direct -t -s 2k 2> $mbuffer_log | netcat -v 192.168.0.101 5000 &> $netcat_log &
Receiver side, the code is:

Code: Select all

#Receiver side
FPS="30"
netcat -l -p 5000 | mplayer -vf scale -zoom -xy 1280 -fps $FPS -cache-min 50 -cache 1024 - &
When I check the mbuffer log, I diagnose a FIFO that remains most of the time empty, but has peaks of 99-100% utilization. During these peaks, my mplayer receiver-side has many errors decoding the video and takes about 5 seconds to recover itself. After this interval, the mbuffer log shows again an empty FIFO. The empty->full->empty goes on and on.

I have two questions:
  • Am I using the correct approach to solve my problem?
  • If so, how could I render my streaming more robust while keeping the $video_out file intact?

cpunk
Posts: 85
Joined: Thu Jun 29, 2017 12:39 pm

Re: Non-blocking streaming and saving to a file (not a duplicate)

Tue Dec 19, 2017 6:06 pm

If nothing else worked, maybe you could:

- tell netcat to use UDP transfer instead of TCP?
- use socat instead of netcat?
- modify "raspivid" to have dual outputs, one being "udp://" (it already supports that) and the other being a file?
- or alternatively, write a "tee" like program yourself, containing a UDP broadcaster and file appender?
- make your Pi the access point in the network... from the viewpoint of the access point, network interfaces don't get reshuffled if a client disconnects

Also, with regard to latency... there is a way to reduce network latency to its absolute minimum, and that is by using WiFi in packet injection (sender) and monitor (receiver) mode... a good starting point for these methods might be here:

https://befinitiv.wordpress.com/wifibro ... ideo-data/

(beware: packet injection / packet monitor is *much* more hassle than simple UDP)

P.S.

My way of displaying UDP-based video streams on a PC (using gstreamer directly, no netcat involved):

Code: Select all

gst-launch-1.0 udpsrc udp://0.0.0.0:3333 ! h264parse ! avdec_h264 ! videoconvert ! autovideosink sync=false

gstorto
Posts: 2
Joined: Mon Dec 18, 2017 2:33 pm

Re: Non-blocking streaming and saving to a file (not a duplicate)

Tue Dec 19, 2017 8:51 pm

cpunk wrote:
Tue Dec 19, 2017 6:06 pm
If nothing else worked, maybe you could...
Thanks for the very helpful tips cpunk ;)

Finally, I implemented the following things:
  • Modified raspivid to include a second output called -o2 (RaspiVid.c) and stream through UDP.
  • Modified my launch.bash and remote.bash to use gstreamer (UDP) instead of mplayer.
If anyone wants to replicate the project, I recommend to checkout the repo: rocket. Modify the IPs to satisfy your network scheme, and 'bash launch.bash' on your terminal. Note it only works on Linux.

Return to “Camera board”