<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>
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
lancer un terminal si GStreamer est configuré dans le PATH windows ou “gstreamer.bat” puis executez :
gst-launch-0.10 videotestsrc ! autovideosink
GStreamer fonctionne sur le principe de Pipeline :
Le Pipeline est composé d'éléments qui peuvent être de plusieurs types :
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 :
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
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
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
gst-launch-0.10 ksvideosrc ! tee name=videoOutput videoOutput. ! queue \ ! autovideosink videoOutput. ! queue ! ffmpegcolorspace ! ffenc_mpeg4 ! avimux \ ! filesink location=destination.avi
<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>
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
<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>
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
GStreamer a été porté sur java grâce à la bibliothèque jna qui permet d'appeler du code C directement depuis Java. GStreamer Java
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/
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; } } } } } } }
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(); } } }