Comparaison des solutions de vidéo-streaming sur Raspberry Pi

Cette page a été mise à jour pour comparer les performances sur Raspberry Pi 2.

Activation de la webcam du Raspberry Pi

Par défaut, la caméra du Raspberry est désactivée. Pour l'activer, il est nécessaire d'utiliser le programme raspi-config

sudo raspi-config

Aller dans la section "Enable Camera" et activez là. Vous devrez alors rebooter pour que le changement de configuration soit pris en compte.

Définitions possibles de la caméra

Raspberry Pi Caméra

La caméra fournit pour Raspberry fonctionne dans différents modes vidéo. Il est important de savoir quand dans le mode 1080p (1920x1080), le champ de vision est tronqué (l'angle de vision est dans réduit par rapport aux capacités du capteur). Il ne faut donc pas utiliser le capteur dans la résolution 1920x1080 mais préférer la résolution de 1296x730 qui permet d'avoir l'angle de vision maximum (ou bien en résolution native du capteur 2592x1944 spot 5MP, mais la vidéo est limitée à 15 images par secondes dans ce mode). Ces points seront à prendre en considération lors de vos tests et pour la mise en production.

Pilote UV4L (Userspace Video 4 Linux)

Le caméra Raspicam n'est pas vue par votre système comme un périphérique classique (via un /dev/videoX). Cela conduit à devoir utiliser des applications qui ont été modifiées pour pouvoir prendre en compte la caméra du Raspberry Pi et donc à utiliser une version particulière (facilement trouvable, mais si on peut éviter les correctifs multiples, cela n'est pas plus mal).

Pour remédier à ce problème, il est possible d'utiliser un pilote mettant à disposition le /dev/videoX qui convient pour l'utilisation de la caméra. D'autre part, ce pilote est dans l'espace utilisateur, ce qui est très pratique.

Pour de plus amples informations, consulter la page officielle de uv4l.

Cette facilitation pour faire les tests, ne sera pas à appliquer pour la solution finale retenue qui utilise raspivid et a donc un accès direct à la caméra sans passer par ce driver.

Installation et configuration

Pour installer le pilote uv4l pour Raspberry Pi:

wget -qO- http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -
sudo sh -c 'echo "deb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main" >> /etc/apt/sources.list'
sudo apt-get update
sudo apt-get install uv4l uv4l-raspicam uv4l-uvc uv4l-mjpegstream uv4l-raspicam-extras

uv4l-raspicam-extras installe un package permettant le démarrage automatique du driver au démarrage de la Raspberry Pi. Il est alors possible de démarrer, arrêter, ou redémarrer le pilote via le service uv4l-raspicam. Le fichier de configuration permettant de configurer le pilote se situe dans le fichier /etc/uv4l/uv4l-raspicam.conf.

sudo service uv4l_raspicam restart

Pour démarrer ou arrêter manuellement le pilote, il est aussi possible d'utiliser les commandes suivantes:

sudo uv4l --driver raspicam --sched-rr --auto-video_nr --encoding h264 --width 1280 --height 720 --framerate 25
sudo pkill uv4l

D'autres pilotes sont disponibles pour les périphériques USB ainsi que pour capturer l'écran ou bien encore les sources de streaming mjpeg.

sudo apt-get install uv4l uv4l-uvc uv4l-mjpegstream

Installation et test de différentes méthodes de streaming vidéo

Nous allons tester différentes solutions pour le streaming vidéo depuis le Raspberry Pi. Le but est de trouver la solution qui sera la moins consommatrice en ressources (cpu, mémoire, i/o, ...) et fournissant la meilleure qualité visuelle (pixelisation, décalage, ...). Pour faire nos comparaison, nous utiliserons toujours les même caractéristiques quelques que soient la solution testée: une vidéo avec une définition de 1280x720 à 25 images par secondes.

motion

Installation et configuration

motion permet de mettre en ligne un serveur web pour la visualisation de séquences de photographies prises à partir de la caméra Raspberry. Plus adapté à de la détection de mouvement pour de la vidéo surveillance, ce projet n'en est pas moins intéressant à tester pour notre projet.

sudo apt-get install motion
cd
wget http://stephane.lavirotte.com/perso/rov/motion.conf

Exécution et visualisation

LD_PRELOAD=/usr/lib/uv4l/uv4lext/armv6l/libuv4lext.so motion -c motion.conf

Après avoir lancé cette dernière commande, il ne reste plus qu'à se connecter avec un navigateur web à l'adresse: http://rov.local:8081 et ainsi pouvoir voir le flux vidéo retransmis par la webcam de la Raspberry Pi.

mjpg-streamer

Installation et configuration

mjpg-streamer n'est pas disponible sous la forme d'un paquetage dans la distribution raspbian. Il est donc nécessaire de récupérer le code source de l'application et de la compiler pour Raspberry Pi. J'ai choisi une fork de mjpeg qui est optimisé pour Raspberry Pi. On notera aussi les paramètres optimisés pour la compilation du binaire.

sudo apt-get install libjpeg8-dev imagemagick subversion
cd
mkdir mjpg-streamer
cd mjpg-streamer
git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer-experimental
CFLAGS+="-Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s" make
sudo make install

Exécution et visualisation

mjpg_streamer -i "/usr/local/lib/input_raspicam.so -x 1280 -y 720 -f 25 -rot 180" -o "/usr/local/lib/output_http.so -w /usr/local/www -p 9000"

Il ne reste alors plus qu'à se connecter avec un navigateur web à l'adresse http://rov.local:9000 et avoir ainsi accès à l'interface graphique de mjpg-streamer.

Il est aussi possible de se connecter avec vlc à l'adresse http://rov.local:9000/?action=stream

gstreamer

Installation et configuration

sudo sh -c 'echo "deb http://vontaene.de/raspbian-updates/ . main" >> /etc/apt/sources.list'
sudo apt-get update
sudo apt-get install gstreamer1.0

ffmpeg et avconv

Installation et configuration

sudo apt-get install ffmpeg
wget http://stephane.lavirotte.com/perso/rov/ffserver.conf

Exécution et visualisation

ffserver -f ffserver.conf &
export LD_PRELOAD=/usr/lib/uv4l/uv4lext/armv6l/libuv4lext.so
avconv -r 25 -s 1280x720 -f video4linux2 -i /dev/video0 http://rov.local:8080/raspicam.ffm

Il suffit alors de se connecter à l'adresse suivante avec un navigateur ou bien vlc: http://rov.local:8080/raspicam.mjpeg

vlc

Installation et configuration

Une autre possibilité de mettre en place un serveur de streaming est d'utiliser vlc. Le paquetage est directement disponible sous raspbian, donc rien de plus simple à installer.

sudo apt-get install vlc

Exécution et visualisation

Pour mettre en place un streaming au-dessus de http, donc visualisable directement dans un navigateur, utiliser les commandes suivantes:

cvlc v4l2:///dev/video0 --v4l2-width 1280 --v4l2-height 720 --sout '#transcode{vcodec=MJPG,width=1280,height=720,vb=1000}:duplicate{dst=std{access=http{mime=multipart/x-mixed-replace;boundary=--7b3cc56e5f51db803f790dad720ed50a},mux=mpjpeg,dst=:8080/video.mjpg}'

Mais nous pouvons aussi utiliser une diffusion en RTSP avec le protocole de transport RTP.

LD_PRELOAD='' cvlc v4l2:///dev/video0 --v4l2-width 1280 --v4l2-height 720 --v4l2-chroma h264 --sout '#rtp{sdp=rtsp://:8080/}'

Actuellement, je ne sais pas s'il est possible de visualiser ce flux directement dans un navigateur. Pour le visualiser, utiliser vlc avec l'adresse suivante: http://rov.local:8080/

ffmpeg, crtmpserver et lighttpd

Installation et configuration

sudo apt-get install ffmpeg crtmpserver lighttpd
cd /etc/lighttpd/conf-enabled
sudo ln -s ../conf-available/10-cgi.conf .
sudo nano 10-cgi.conf
# Activer cgi.assign et modifier le lien /usr/bin/python en /usr/bin/python2
cd && wget http://stephane.lavirotte.com/perso/rov/videostream.tgz
cd / && sudo tar xzvf /home/pi/videostream.tgz

Exécution et visualisation

sudo service crtmpserver start
sudo service lighttpd start
sudo service videostream start

Pour visualiser le streaming vidéo, il suffit alors de se connecter sur http://rov.local/videostreaming/. Il est alors aussi possible de commander les paramètres de la caméra, mais cette dernière option est à vérifier car il semblerait qu'il y ai quelques soucis.

Analyse des performances des différentes solutions

Plusieurs types de clients sont possibles: navigateur web, application dédiée, ... Dans le cas particulier de la visualisation à l'aide de vlc, on notera un grand décalage temporel entre la source et la visualisation. Cela provient d'un paramétrage de vlc (utilisation d'un cache pour éviter les coupures).

Pour éviter ce décalage lors de la lecture avec vlc, il suffit de procéder de la manière suivante: Menu "Média / Ouvrir un flux réseau", saisir l'URL, activer "Afficher plus d'options" et régler le paramètre mise en cache (par défaut 1000ms). Il est alors possible de mettre la valeur de ce paramètre à 0ms et ainsi obtenir la lecture du flux en direct sans aucun décalage avec la source.

motion

Même en faisant quelques réglages pour adapter le programme aux contraintes de l'usage envisagé, je n'ai pas pu obtenir mieux qu'un CPU à 100% quand un mouvement est détecté (lors de la visualisation du flux). De plus, j'ai testé en utilisant la version motion-mmal pour vérifier que le problème ne venait pas du mode d'accès au périphérique caméra. Ce test n'a pas été plus concluant. Seul le fait de baisser en résolution ou en nombre d'images par seconde permet d'avoir une utilisation cpu raisonnable. De plus, le décalage entre ce qui est filmé et la visualisation du flux est très important. Il y a bien entendu un un surcoût du aux algorithmes de détection de mouvement, fonctionnalité non nécessaire dans notre cas. Donc il semblerait que ce programme ne soit pas du tout adapté à nos besoins de streaming vidéo en live pour la visualisation en direct et donc pas adapté pour notre projet.

mjpeg-streamer

De bonnes performances avec une visualisation dans un navigateur et avec vlc. En termes de consommation cpu, ce n'est pas la solution la plus favorable. Sans client connecté, l'utilisation du cpu est limité à 25 à 30%, mais quand un client visualise le flux, l'utilisation du processeur peut monter à 75%. C'est pourtant la solution retenue par openrov-cockpit pour leur projet... Cela justifierait sûrement le besoin qu'ils ont eu d'utiliser une plate-forme plus puissante comme Beaglebone Black.

gstreamer

Le problème majeur avec cette solution est de pouvoir avoir un client qui n'est pas gstreamer lui-même. Tous les exemples trouvés sur le net se réfèrent un client gstreamer. Mais cette solution est moins portable que les autres étudiées en termes de client.

ffmpeg et avconv

Cette solution avec ffmpeg et avconv ne permet pas d'obtenir des performances satisfaisantes. Au maximum, j'ai pu obtenir 17fps avec une utilisation du CPU à 100% (et l'image est assez pixelisée). En fait, aucun de ces deux outils ne semble travailler avec le GPU du Raspberry, donc il est illusoire d'imaginer avoir des performances acceptables avec cette solution. D'autre part, la solution produit un fichier dans lequel est stocké le flux ce qui va faire vieillir prématurément la carte SD en écrivant en permanence sur ce fichier.

Donc cette solution est à écarter, sauf à trouver des améliorations significatives (utilisation de l'encodage, pas d'utilisation d'un fichier, ...). Il semblerait que ffmpeg dispose d'une version avec encodage hardware. A creuser si on ne trouve rien de mieux.

vlc

Les tests avec vlc n'ont pas pu être menés car les commandes précédentes ne fonctionnent plus. A vérifier donc.

ffmpeg, crtmpserver et lighttpd

Cette dernière solution semble la plus prometteuse. La diffusion est de bonne qualité, il semble y avoir très peu de décalage, et surtout la consommation cpu est très faible y compris avec la connexion d'un client.

Conclusion

Des tests ont été réalisés à l'aide du script suivant (monitor.sh) pour mesurer la consommation des ressources cpu de la Raspberry Pi lors de l'exécution d'une configuration.

#!/bin/sh

top -d 3.0 -n 20 -b > /tmp/top.log

echo "user;system;nice;idle;wait i/o;hardware interrupt;software interrupt;vm stolen"
cat /tmp/top.log | grep "Cpu(s)" | awk '{gsub(/[ ][ ]/," ")}1' | tr -d '[:alpha:]%():,' | awk '{gsub(/[ ][ ]/,";")}1' | sed 's/^.//' | tr '.' ','
rm /tmp/top.log

Ce test dure 1 minute (une mesure toutes les 3 secondes sur 20 itérations) et le résultat de la commande top est stocké dans un fichier pour une analyse ultérieure. Les informations sur la consommation cpu sont alors extraites de ce fichier et ont été ajoutées à un document Excel pour comparer les différentes solutions et tracer un graphique que vous pourrez retrouver ci-dessous.

Comparatif de solutions de vidéo-streaming sur Raspberry Pi

Vous trouverez ci-joint le document Excel contenant les données de comparaisons effectuées avec les différentes solutions de vidéo streaming sur le Raspberry Pi.

La meilleur solution en termes de consommation cpu et de rendu graphique est donc bien la dernière solution testée à base de ffmpeg, crtmpserver et un serveur lightttpd pour la diffusion.Cette dernière solution ne consomme qu'environ 20 à 25% de cpu quand un client y est connecté. Mais celle-ci a toutefois un inconvénient important: il est nécessaire d'avoir un plugin Flash dans le navigateur utilisé pour la visualisation car le protocole RTMP n'est reconnu que par Flash ou vlc. Cela limite donc très fortement les navigateurs utilisables pour se connecter au flux vidéo (iOS impossible et peu de chance sur Android). D'autre part, cela complique aussi l'intégration dans une application tiers pour le rendu graphique de l'interface de contrôle du robot. En résumé, si la solution est techniquement la meilleure sur Raspberry Pi 1, celle-ci pose problème quant à son utilisation du côté client de visualisation.

Programmes nécessaires et fichiers utiles

Vous pouvez trouver ci-joint tous les fichiers utiles ou référencés sur cette page.

Fichier de configuration de Motion Video Streaming package for lighttpd Script shell pour mesurer l'activité cpu Fichier excel des données brutes Schéma comparatif des résultats