meta données pour cette page
Intellij/VsCode et les raccourcis non fonctionnels
Étant utilisateur du clavier bépo j’ai parfois des problèmes de raccourcis dans Intellij et VsCode.
Certains raccourcis bien pratique comme Ctrl+/ pour commenter Ctrl+Alt+M pour refactorer ne sont pas fonctionnels.
De plus certains caractères comme l’accent circonflexe “^” ne sont parfois pas évident à tapper en bépo et génère un tas de caractère au lieu du simple circonflexe.
Pour Ctrl+/ il semblerait que ce soit liés à des problèmes de touche mortes j’ai donc éssayé d’installer le clavier bépo tronqué et ça semble fonctionner. https://bepo.fr/wiki/Windows
Pour le raccourci Ctrl+Alt+M ne fonctionnait pas à cause de Nvidia qui capturait le raccourci voici la marche à suivre pour le rendre disponible dans Intellij https://superuser.com/questions/1282799/what-is-preventing-ctrl-alt-m-from-reaching-intellij-on-windows-10
Install Composer on Debian
sudo apt-get install curl php5-cli curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
Verify installation:
composer --version Composer version 4ecdbf89c4a3d1e5dfe73c57e3202a5e2a18c87e 2014-07-28 20:12:27
http://www.bravo-kernel.com/2014/08/how-to-install-composer-on-debian/
Inclure des dépendances locale grâce à Maven
On peut ajouter des dépendances locales directement en mentionnant dans le build MAVEN une dépendance avec un scope System.
<dependency> <groupId>sample</groupId> <artifactId>com.sample</artifactId> <version>1.0</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/yourJar.jar</systemPath> </dependency>
http://stackoverflow.com/questions/4955635/how-to-add-local-jar-files-in-maven-project
GStreamer 0.10
Installation
Avec l'installateur GStreamer
<WRAP center round important 60%> Nécéssite les droits administrateurs </WRAP> Téléchargez l'installateur Page de téléchargement <WRAP center round info 60%> Si vous constatez des bugs ou des problèmes avec la dernière version proposé n'hésitez pas à télécharger d'anciennes version GStreamer 2012.11 </WRAP> l'installateur va se charger de créer vos variable d'environnement et de configurer GStreamer pour qu'il soit utilisable clé en main. <WRAP center round important 60%> J'ai rencontré des difficulté avec la variable de GStreamer dans le PATH Windows, il faut parfois la réécrire ou supprimer des entrée pour que ça puisse fonctionner </WRAP>
Sans installateur GStreamer
Si vous ne disposez pas des droit d'administration ce n'est pas grave j'ai préparé une version de GStreamer portable. Il s'agit d'une installation 2013.6 LGPL ( je n'ai pas intégré les plugins GPL dont le H264).
Téléchargez : GStreamer Portable 0.10.
décompresser le à l'endroit où vous le souhaitez.
Pour utiliser GStreamer en ligne de commande il va falloir configurer votre variable PATH. par exemple dans un terminal :
set GStreamerPATH=C:\Chemin\Vers\GStreamer set PATH=%PATH%;%GStreamerPATH%\bin
Afin de gagner mon temps et ne pas avoir à configurer ma variable path dans windows je me suis créé un script “gstreamer.bat” me permettant de me trouver avec un environnement GStreamer bien configurer quand j'en ai besoin
set GStreamerPATH=C:\Chemin\Vers\GStreamer set PATH=%PATH%;%GStreamerPATH%\bin cls cmd /k
Test de votre environnement
lancer un terminal si GStreamer est configuré dans le PATH windows ou “gstreamer.bat” puis executez :
gst-launch-0.10 videotestsrc ! autovideosink
Principe de GStreamer
GStreamer fonctionne sur le principe de Pipeline :
Le Pipeline est composé d'éléments qui peuvent être de plusieurs types :
- Sources
- Filtres
- Sorties
un pipeline doit être composé d'au moins d'une sources et d'une sorties pour fonctionner.
Les sources, les filtres et les sorties doivent être composés dans un ordre particulier comme dans l'exemple suivant :
Exemples de Pipeline
Lire une vidéo
- Version facile :
gst-launch-0.10 playbin2 uri=file:///C:/video/trailer.mp4
Ici tous le Pipeline est déjà créé dans playbin2 pour permettre de fournir un lecteur vidéo facilement
- Version complexe :
gst-launch-0.10 filesrc location=C:/video/trailer.mp4 ! decodebin2 name=demux \ demux. ! autovideosink demux. ! autoaudiosink
Ici on a l'équivalent de Playbin2 décomposé en pipeline
- filesrc est un élement sources
- decodebin2 permet de décoder tous type de fichier vidéo et audio sans avoir à se préoccuper du format
- lien entre decodebin2 “demux” et l'affichage vidéo
- lien entre decodebin2 “demux” et l'affichage audio
Lire le flux d'une Webcam
gst-launch-0.10 ksvideosrc ! autovideosink
ksvideosrc : permet de récupérer le flux d'une webcam installé sur votre ordinateur <WRAP center round info 60%> si vous avez deux ou plus de webcam de brancher sur votre ordinateur vous pouvez sélectionner la webcam que vous souhaitez ouvrir grâce au paramètre “device-index” </WRAP>
gst-launch-0.10 ksvideosrc device-index=1 ! autovideosink
cette commande sélectionne la caméra correspondant à l'index 1
Lire le flux d'une webcam et l'enregistrer en même temps
gst-launch-0.10 ksvideosrc ! tee name=videoOutput videoOutput. ! queue \ ! autovideosink videoOutput. ! queue ! ffmpegcolorspace ! ffenc_mpeg4 ! avimux \ ! filesink location=destination.avi
- ksvideosrc : On récupère le flux d'une webcam
- tee : On divise le flux en deux sous flux nommé videoOutput
- Première partie :
- Queue : On met le flux dans une queue pour éviter tous problème d'interbloquage
- autovideosink : on affiche la vidéo
- Deuxième partie :
- Queue : On met le flux dans une queue pour éviter tous problème d'interbloquage
- ffmpegcolorspace : On converti le flux brute dans l'espace de couleur ffmpeg
- ffenc_mpeg : on encode en mp4 à l'aide du plugin ffmpeg
- avimux : on encapsule le flux dans le format avi
- filesink : on enregistre la vidéo dans un fichier
<WRAP center round info 60%> Ici on voit que l'élément tee permet de décomposer un flux en deux flux que l'on va traiter de manière différentes. </WRAP>
Création d'un serveur RTP
gst-launch-0.10 ksvideosrc device-index=0 ! videoscale ! video/x-raw-yuv, \ width=640,height=480 ! videorate ! video/x-raw-yuv,framerate=25/1 \ ! ffmpegcolorspace ! ffenc_mpeg4 bitrate=1000000 ! rtpmp4vpay send-config=true \ ! udpsink host=127.0.0.1 port=50000
- ksvideosrc : on récupère le flux de la webcam
- videoscale : on la redimensionne au format 640×480
- videorate : on défini le nombre d'image par seconde à 25
- ffmpegcolorspace : on transforme le flux dans l'espace de couleur ffmpeg
- ffenc_mpeg4 : on encode le flux en mpeg4 avec un débit de 100ko/s.
- rtpmp4vpay : on encapsule le flux dans un flux rtp
- udpsink : on envoi le flux vers 127.0.0.1 sur le port 50000 en UDP
<WRAP center round info 60%> Ici on voit que l'on peut retravailler le format de la vidéo et l'envoyer à travers le réseau. </WRAP>
Création d'un client RTP
gst-launch-0.10 udpsrc caps="application/x-rtp, media=(string)video,\ clock-rate=(int)90000, encoding-name=(string)MP4V-ES" port=50001 \ ! .recv_rtp_sink_0 gstrtpbin ! rtpmp4vdepay ! ffdec_mpeg4 ! ffmpegcolorspace \ ! autovideosink
- udpsrc : récupère le flux udp sur le port 50001
- gstrtpbin : decode le flux udp
- rtpmp4vdepay : decapsule le flux rtp
- ffdec_mpeg4 : décode le flux mpeg4
- ffmpegcolorspace : converti l'espace de couleur ffmpeg
- autovideosink : affiche le flux distant
Portage GStreamer dans Java
GStreamer a été porté sur java grâce à la bibliothèque jna qui permet d'appeler du code C directement depuis Java. GStreamer Java
Un Pipeline simple
le pipeline correspondant à la commande suivante :
gst-launch-0.10 videotestsrc ! autovideosink
peut être codé de la manière suivante :
package gstreamer; import java.io.File; import java.util.ArrayList; import java.util.List; import org.gstreamer.Gst; import org.gstreamer.Pipeline; import org.gstreamer.State; public class VideoTest { private static void loadGStreamerLibrary(String libraryPath) { File f = new File(libraryPath); String[] names = f.list(); List<String> dllLoaded = new ArrayList<String>(); boolean allLibraryLoaded = false; int count = 0; while (!allLibraryLoaded && count < 10) { count++; System.out.println("Try: " + count); allLibraryLoaded = true; for (String name : names) { if (name.contains("dll")) { if (!dllLoaded.contains(name)) { try { System.load(libraryPath + name); System.out.println("succeed to load: " + name); dllLoaded.add(name); } catch (UnsatisfiedLinkError e) { System.out.println("failed to load: " + name); allLibraryLoaded = false; } } } } } } public static void main(String[] args) { //charge la libraire gstreamer se trouvant dans bin et les plugin se trouvant dans ../lib //à partir de bin loadGStreamerLibrary("C:/gstreamer-sdk/vers/repertoire/bin/"); Gst.init("VideoTest", args); Pipeline pipe = Pipeline.launch("videotestsrc ! autovideosink"); pipe.setState(State.PLAYING); while (true) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
Cependant ce code n'affiche la vidéo que dans une fenêtre externe à Java. pour lancer il faut faire
java gstreamer.VideoTest -Djna.library.path=C:/gstreamer-sdk/vers/repertoire/bin/
Charger les librairies GStreamer dans OSGI
Pour mes besoins liés à la compatibilité OSGI j'ai créé une classe utilitaire permettant de charger chacune des librairie dynamique nécéssaire au fonctionnement de GStreamer sans avoir à spécifier le jna.library.path il suffit donc d'appeler la méthode initGStreamer et celle-ci se chargera pour vous d'ajouter toutes les librairies nécéssaires si ce n'est pas déjà fait de plus si comme moi vous avez besoin de créer plusieurs lecteur vidéo en parallèle j'ai implémenté la méthode initGStreamer de manière bloquante pour qu'elle ne charge qu'une seule fois les classes dynamique et que si d'autre appel à initGStreamer sont effectué pendant le chargement qu'il attendent le chargement du premier appel.
<WRAP center round info 60%> Si vous n'utilisez pas OSGI cette classe n'est pas nécéssaire mais permet de simplifier le lancement de votre programme (Le paramètre -Djna.library.path=C:/gstreamer-sdk/vers/repertoire/bin/ n'étant plus nécéssaire). </WRAP>
package com.thales.tms.video.utils; import java.awt.Toolkit; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; import org.gstreamer.Gst; /** * The Class GStreamerUtils provide utils method to load GStreamer native * library. */ public class GStreamerUtils { /** The Constant GSTREAMER_CONFIGURATION_ENVIRONMENT_PROPERTY. */ public static final String GSTREAMER_CONFIGURATION_ENVIRONMENT_PROPERTY = "gstreamer.lib"; /** The Constant DEFAULT_GSTREAMER_FOLDER_RELATIVE_PATH. */ private static final String DEFAULT_GSTREAMER_FOLDER_RELATIVE_PATH = "..\\lib\\gstreamer\\bin\\"; /** The Constant DLL_EXTENSIONS. */ private static final String DLL_EXTENSIONS = "dll"; /** The Constant LOAD_RETRY. */ private static final int LOAD_RETRY = 10; /** The is GStreamer library loaded. */ private static Boolean isGStreamerLibraryLoadedStart = false; /** The is GStreamer library loaded success. */ private static Boolean isGStreamerLibraryLoadedSuccess = false; /** The mutex. */ private static ReentrantLock mutex = new ReentrantLock(); /** The gstreamer loaded. */ private static Condition gstreamerLoaded = mutex.newCondition(); /** The Constant SWING_START_WAIT. */ private static final int SWING_START_WAIT = 100; /** * Instantiates a new GStreamerUtils. */ private GStreamerUtils() { } /** * Patch to wait until Swing is running This method monitor the EventQueue * of The default toolkit and wait until it has been instantiated. */ public static void waitForSwingLaunch() { while (Toolkit.getDefaultToolkit().getSystemEventQueue() == null) { try { Thread.sleep(SWING_START_WAIT); } catch (final InterruptedException e) { e.printStackTrace(); } } } /** * Inits the GStreamer instances and load native dynamic library associated. * * @param instanceName * the instance name of GStreamer */ public static void initGStreamer(final String instanceName) { final StringBuilder libraryPath = new StringBuilder(); libraryPath.append(System.getProperty("user.dir")); String gstreamerFolderRelativePath = System.getProperty(GSTREAMER_CONFIGURATION_ENVIRONMENT_PROPERTY); if (gstreamerFolderRelativePath == null) { gstreamerFolderRelativePath = DEFAULT_GSTREAMER_FOLDER_RELATIVE_PATH; } libraryPath.append("\\").append(gstreamerFolderRelativePath); mutex.lock(); try { if (!isGStreamerLibraryLoadedStart) { // if the GStreamer dynamic Libraries have never been loaded isGStreamerLibraryLoadedStart = true; loadGStreamerLibrary(libraryPath.toString()); isGStreamerLibraryLoadedSuccess = true; // Signal other GStreamer init that the GStreamer library have // been loaded gstreamerLoaded.signalAll(); } else { if (!isGStreamerLibraryLoadedSuccess) { // if GStreamer dynamic libraries have not finished to be // loaded wait for GStreamer library loading to end try { gstreamerLoaded.await(); } catch (final InterruptedException e) { e.printStackTrace(); } } } } finally { mutex.unlock(); } // Use the default glib main context to prevent launch problem. Gst.setUseDefaultContext(true); Gst.init(instanceName, new String[] {}); } /** * Load GStreamer library. * * @param libraryPath * the library path .to load */ private static void loadGStreamerLibrary(final String libraryPath) { final File f = new File(libraryPath); final String[] names = f.list(); final List<String> dllLoaded = new ArrayList<String>(); boolean allLibraryLoaded = false; int count = 0; while (!allLibraryLoaded && count < LOAD_RETRY) { count++; allLibraryLoaded = true; for (final String name : names) { if (name.contains(DLL_EXTENSIONS)) { if (!dllLoaded.contains(name)) { try { System.load(libraryPath + name); dllLoaded.add(name); } catch (final UnsatisfiedLinkError e) { allLibraryLoaded = false; } } } } } } }
Un Serveur RTP
Voici le code pour créer un simple Server RTP en java
public static void startRTPServer(final String ip, final String port) { System.setProperty(GStreamerUtils.GSTREAMER_CONFIGURATION_ENVIRONMENT_PROPERTY, "..\\..\\executable\\com.thales.tms.felix\\lib\\gstreamer\\bin\\"); GStreamerUtils.initGStreamer("RTPMP4Server"); final Pipeline pipe = Pipeline .launch("ksvideosrc device-index=0 ! videoscale ! video/x-raw-yuv,width=640,height=480 ! videorate ! video/x-raw-yuv,framerate=25/1 ! ffmpegcolorspace ! ffenc_mpeg4 bitrate=1000000 ! rtpmp4vpay send-config=true ! udpsink host=" + ip + " port=" + port); pipe.setState(State.PLAYING); while (true) { try { Thread.sleep(100); } catch (final InterruptedException e) { e.printStackTrace(); } } }
Sources
GStreamer pipeline cheat sheet For Windows
raw live webcam display
gst-launch-1.0.exe autovideosrc ! videoconvert ! capsfilter caps=video/x-raw,width=640,height=480 ! autovideosink
Creating VP8 Test Source video
gst-launch-1.0 -v videotestsrc num-buffers=1000 ! vp8enc ! webmmux ! filesink location=videotestsrc.webm
Display VP8 video
gst-launch-1.0 -v filesrc location=videotestsrc.webm ! matroskademux ! vp8dec ! videoconvert ! videoscale ! autovideosink
Live encoding VP8 video from raw Webcam
gst-launch-1.0 -v autovideosrc ! videoconvert ! queue ! vp8enc ! queue ! webmmux ! queue ! filesink location=testvp8.webm
Live encoding VP8 video from raw Webcam with two thread (Not sure it works)
gst-launch-1.0 -ev autovideosrc ! timeoverlay ! queue ! videoconvert ! vp8enc cpu-used=2 ! queue ! matroskamux ! queue ! filesink location=test.mkv
Live encoding VP9 video from raw Webcam high latency low rate vp9 encoding 320/240 (cpu 50%)
gst-launch-1.0 -v autovideosrc ! videoconvert ! videoscale ! video/x-raw,width=320,height=240 ! vp9enc target-bitrate=30000 end-usage=cbr ! webmmux ! filesink location=testvp9.webm
Live encoding VP9 video from raw Webcam high latency low rate vp9 encoding 320/240 (cpu 50%) SSIM and undershoot 50%
gst-launch-1.0 -v autovideosrc ! videoconvert ! videoscale ! video/x-raw,width=320,height=240 ! vp9enc target-bitrate=30000 end-usage=cbr tuning=ssim undershoot=50 ! webmmux ! filesink location=testvp9.webm
Paramètres VP9
https://www.webmproject.org/docs/encoder-parameters/
Explication SSIM/PSNR
http://www.hardware.fr/articles/828-5/mesurer-qualite-psrn-ssim-leurs-travers.html
Live encoding VP9 video from raw Webcam with low framerate 5fps high latency low rate vp9 encoding 320/240 (cpu 50%) SSIM and undershoot 50%
gst-launch-1.0 -v autovideosrc ! videoconvert ! videoscale ! video/x-raw,framerate=25/1,width=320,height=240 ! videorate drop-only=true ! video/x-raw,framerate=5/1 ! vp9enc target-bitrate=30000 end-usage=cbr tuning=ssim undershoot=50 cpu-used=4 threads=16 ! webmmux ! filesink location=testvp9.webm
Display VP9 video
gst-launch-1.0 -v filesrc location=testvp9.webm ! matroskademux ! vp9dec ! videoconvert ! videoscale ! autovideosink
Live low latency encoding X264 video from raw Webcam
gst-launch-1.0 -v autovideosrc ! videoconvert ! queue ! x264enc tune=zerolatency ! matroskamux ! filesink location= videotestsrc.mkv
Live encoding AVIvideo from raw Webcam
gst-launch-1.0 autovideosrc ! timeoverlay ! queue ! videoscale method=1 ! video/x-raw,width=320,height=240 ! avimux ! filesink location=webcam.avi
Live encoding X264 low latency low bitrate(60kbits) from raw Webcam 320/240
gst-launch-1.0 -v autovideosrc ! videoconvert ! video/x-raw,width=320,height=240 ! queue ! x265enc tune=zerolatency bitrate=60 ! matroskamux ! filesink location=videotestsrc.mkv
Live encoding X264 low latency low bitrate(60kbits) from raw Webcam 320/240
gst-launch-1.0 -v autovideosrc ! videoconvert ! video/x-raw,framerate=5/1,width=320,height=240 ! queue ! x264enc tune=zerolatency bitrate=30 ! matroskamux ! filesink location=videotestsrc.mkv
Low Latency low bitrate VP8 high cpu usage
gst-launch-1.0 -v autovideosrc ! videoconvert ! video/x-raw,framerate=5/1,width=320,height=240 ! queue ! vp8enc end -usage=cbr target-bitrate=60000 sharpness=2 threads=5 ! webmmux ! filesink location=testvp8.webmgst-launch-1.0 -v aut ovideosrc ! videoconvert ! video/x-raw,framerate=5/1,width=320,height=240 ! queue ! vp8enc end-usage=cbr target-bitrate=60000 sharpness=2 threads=5 ! webmmux ! filesink location=testvp8.webm
plugin list https://gstreamer.freedesktop.org/documentation/plugins.html https://blogs.gnome.org/rbultje/2015/09/28/vp9-encodingdecoding-performance-vs-hevch-264/
rtp x264 sender 320×240 5 fps zerolatency 30kbits
gst-launch-1.0 -v autovideosrc ! videoconvert ! video/x-raw,framerate=5/1,width=320,height=240 ! queue ! x264enc tune=zerolatency bitrate=30 ! rtph264pay ! udpsink host=127.0.0.1 port=50000
rtp x264 receiver
gst-launch-1.0 udpsrc caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H 264, payload=(int)96" port=50000 ! rtph264depay ! decodebin ! videoconvert ! autovideosink
rtp vp9 sender 320×240 5 fps 3/4 seconds latency 30kbits
gst-launch-1.0 -v autovideosrc ! videoconvert ! videoscale ! video/x-raw,width=320,height=240 ! vp9enc target-bitrate=30000 end-usage=cbr ! rtpvp9pay ! udpsink host=127.0.0.1 port=50000
rtp VP9 Receiver
gst-launch-1.0 udpsrc caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)VP9, payload=(int)96" port=50000 ! rtpvp9depay ! decodebin ! videoconvert ! autovideosink
Exemples de commandes GStreamer :
https://blog.42pillistreet.com/doku.php?id=blog:gstreamer_pipeline_cheat_sheet