Dans cette article j’apporte les modifications nécessaires au visionnage du flux vidéo dans mon application client ! La correction du code du précédent article y est apportée, ainsi que l’optimisation du cache vidéo sur l’application client !

1. VLC et Live555 – L’importance du TimeStamp !

Le « TimeStamp » ou « l’horodatage » en français est une unité de temps associant une date et une heure à un évènement. Le timestamp a généralement pour but d’enregistrer l’instant auquel une opération est effectuée. Dans notre cas, le timestamp permet de synchroniser des flux vidéos entre eux.

Lorsqu’on encode avec GStreamer pour envoyer un flux vidéo sur le réseau et que l’on décode de l’autre côté avec GStreamer, le mécanisme de synchronisation s’effectue sur l’heure de démarrage du flux qui est transmise du serveur au client. Donc pas de soucis de ce côté-là. GStreamer client se synchronise par rapport à une heure de diffusion et réajuste les images en fonction de cela. La synchronisation temps-réelle est désactivée par défaut (cela permet d’éviter certains lags dues à des perturbations réseau).

Par contre, lorsqu’on décode le flux avec VLC Media Player, ce dernier fait appel à des librairies Live555 et là où ça bloque, c’est lorsque la librairie demande un timestamp pour chaque image reçue. Or la librairie ne reçoit que le timestamp de première connexion et pas celle de chaque image à suivre. D’où le fait qu’on ne capte que la première image.

 

2. Corrections des commandes précédentes

Pour résoudre ce problème, rien de plus simple : activer l’envoi du timestamp pour chaque image-clé sur le serveur (dans notre cas, le Raspberry Pi), et cela grâce à l’option : do-timestamp=true.

Ma commande sur le Raspberry devient donc :

raspivid -n -w 640 -h 480 -b 1000000 -fps 15 -t 0 -o – | gst-launch-1.0 -v fdsrc do-timestamp=true ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=192.168.0.15 port=9000

 

J’en ai profité pour changer la résolution également et la diminuer pour un rendu plus fluide et un passage en 4/3 sur la tablette.

Côté VLC, pour le fichier RDP (h264.rdp), je ne change rien :

v=0
m=video 9000 RTP/AVP 96
c=IN IP4 192.168.0.23
a=rtpmap:96 H264/90000

 

Ensuite, dans mon application client, je prévois un bouton « Play » avec l’évènement qui va me charger le fichier h264.sdp (à la racine du dossier du programme Client) et lancer le flux streamé :

        private void OnPlayButtonClick(object sender, RoutedEventArgs e)
        {
            var currentAssembly = Assembly.GetEntryAssembly();
            var currentDirectory = new FileInfo(currentAssembly.Location).DirectoryName;
            video.MediaPlayer.Play(new Uri(System.IO.Path.Combine(currentDirectory, @"h264.sdp")));
        }

 

3. Estimation de la latence à travers le réseau local

Afin d’estimé la latence, j’ai filmé le chronomètre-en-ligne que j’avais lancé sur mon écran. Avec le retour vidéo avec Gstreamer pour Windows ou VLC.DotNet lancé dans mon application C#, je peux estimer la latence.

Mesure de la latence avec GStreamer <-> GStreamer : 172ms de décalage !

Mesure de la latence avec GStreamer GStreamer : 172ms de décalage !

La mesure de latence de GStreamer a GStreamer est très faible pour de la vidéo. La latence se remarque à peine. C’est l’idéal pour être réactif lors du pilotage du Robot !

Mesure de la latence avec GStreamer <-> VLC.dotNet : 1277ms de décalage !

Mesure de la latence avec GStreamer VLC.dotNet : 1277ms de décalage !

Avec VLC, le résultat est bien pire ! La latence est 7,33 fois plus élevée. Avec une latence supérieure à 1 seconde, la latence se fait ressentir. La mise en cache permet une vidéo fluide mais très décalée. Et je pense que la manière que VLC a de mettre en cache le flux streamé est en partie responsable de cette latence.

Pour changer cette mise en cache des flux réseau, je dois modifier la valeur de mise en cache, grâce à cette ligne de code placée juste avant l’initialisation du plugin VLC.DotNet :

video.MediaPlayer.VlcMediaplayerOptions = new[] {“–network-caching=400”};

 

J’ai réalisé des essais avec les valeurs suivantes :

  • Network-Caching = 1000ms (par défaut) : latence de 1277ms
  • Network-Caching = 100 ms : Trop faible, le flux ne synchronise plus, freeze à la première image.
  • Network-Caching = 300 ms : freeze de l’image toutes les 3 secondes, inexploitable.
  • Network-Caching = 400ms : retour sur image pas mal. Latence de 636ms !
L’optimisation apporte beaucoup ! On passe de 1277ms à 636ms !

L’optimisation apporte beaucoup ! On passe de 1277ms à 636ms !

Je divise la latence initiale par 2 ! 🙂 En terme de rendu visuel, c’est déjà bien mieux !

En optimisant ce paramètre à 340 (valeur basse limite, sinon j’ai de la saccade) ; j’arrive à une latence de 523ms !

Je pense qu’à ce niveau-là, il sera difficile de mieux optimiser la latence sur VLC. L’écart entre les librairies VLC.DotNet et GStreamer est notamment due à la manière de traiter et décoder l’information.

Pour obtenir une latence plus faible au sein de l’application, il me faudrait migrer le projet GStreamer-Sharp sur mon application, ce qui n’est pas vraiment aisé au vue de la documentation houleuse de GStreamer-Sharp qui est surtout orientée vers un univers Mono sous Linux.

Je pense que je vais quitter la partie stream vidéo un moment pour m’orienter à nouveau sur la partie serveur du PiRobot, afin de faire remonter les valeurs de couples moteur à l’application client. Je pourrai ainsi remonter quelques informations utiles et faire quelques statistiques :-).

Wait&See…

Joyeuses Pâques 🙂

BenTeK.

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

Recevez les bons outils pour débuter dans l'univers DIY et l'impression 3D !