Ici et ailleurs

Le blog d’un joueur … mais pas que le blog de Sky.

Le Java Media Framework ou comment véhiculer du son en Java

Aujourd’hui, j’ai décidé de vous parler de mon deuxième sujet de stage. Mon premier étant d’interfacer un IPS (Programme de détection d’attaques réseaux) avec un antivirus, ce qui c’est fini par la création d’un dynamic pre-processor pour l’IPS Snort. Je ne parlerais pas de ce premier sujet car il est un peu indigeste, en même temps, c’est du C, c’est normal.

Donc le Java, ce langage limite magique, qui gère la mémoire pas toujours de la meilleure manière qui soit mais qui reste, il faut l’avouer, agréable à coder et très bien documenté. Si je décide d’en parler, c’est aussi pour garder une trace de ce que j’aurais fait pendant mon stage.

Deuxième sujet donc, réalisation d’un soft/web phone en Java. Après avoir regardé du côté de ce qui se faisait déjà, entre les trucs trop lourds qui intègrent des choses dont on se servira jamais et les programmes qui conviendraient si seulement ils étaient open-sources, j’ai décidé de partir de rien.

Choix des outils

Comprendre de quoi on parle et repérer les outils nécessaires :

  • Pour récupérer le flux audio et l’envoyer, j’ai choisi JMF, facilité d’utilisation et surtout la possibilité de transformer le flux audio en paquet RTP (standard pour la diffusion de flux audio via un réseau) facilement.
  • Pour implémenter la couche SIP et pouvoir s’occuper de la VoIP, je me penche du côté de Jain-SIP mais rien encore de bien figé.

Ce qui est fait au moment où j’écris : la base de l’interface, le test du périphérique d’entrée et la transmission à un autre poste via son adresse IP donc l’implémentation du protocole SIP reste à faire (et oui, ça risque d’être compliqué), le truc cool, c’est qu’on peut déjà envoyer et recevoir à distance. Voilà à quoi ça ressemble :

Interface actuelle

Interface actuelle

Les bases du JMF

Comprendre le fonctionnement du Java Media Framework, heureusement pour moi, il existe pas mal de pdf sympa pour ça qui explique le fonctionnement des états des différents éléments qui le compose par exemple.

Globalement, voilà les éléments les plus importants :

  • Data Source : Encapsule le flux du média, ce qui permet ensuite d’être couplé à un Player pour la lecture sans se soucier d’où vient la source et de sa forme initiale.
  • Capture Device : Comme son nom l’indique, permet d’interagir avec les périphériques d’entrées.
  • Player : Prends un flux audio ou vidéo en entrée pour le rendre via l’écran ou les haut parleurs. C’est un objet à états, ce qui signifie qu’il doit se préparer avant de pouvoir être utilisé (je ne vais pas détaillé plus).
  • Processor : C’est un type particulier de Player, il contrôle et modifie les données en entrée/sortie.
  • DataSink : Interface de base pour lire un média à partir d’une source de données ou envoyer le résultat vers une destination.
  • Manager : Permet de connecter deux différents objets, on s’en sert par exemple pour créer un Player à partir d’une source de données, un processor, etc..

Utilisation du JMF

Le code à proprement parler. Je ne vais pas tout détailler, juste un exemple. Pour lire le flux envoyé par notre microphone, c’est très simple. Premièrement, il faut récupérer la liste des périphériques de capture, c’est ce que je fais pour remplir ma liste déroulante, grâce à  :

CaptureDeviceManager.getDeviceList(null)

Cette méthode du DeviceManager me retourne un vecteur qui me permet de remplir ma liste, j’ai ajouté un ActionListener qui, à chaque changement survenu dans la liste, stocke le MediaLocator (L’adresse vers la source de données) et le périphérique sélectionné dans ma classe “Capture” avec ma méthode :

public void setCaptureDevice(CaptureDeviceInfo captureDevice) {
this.currentCaptureDevice = captureDevice;
this.mediaLocatorCapture = this.currentCaptureDevice.getLocator();
}

Ce qui va me permettre de toujours l’avoir sous le coude. Une fois qu’on a récupéré le MediaLocator de notre micro, on peut s’attaquer au player, vous allez voir, c’est enfantin. Evidemment, je zappe les déclarations des variables et les import, et je simplifie au maximum :

try {
this.player = Manager.createPlayer(mediaLocator);
this.player.realize();
this.player.start();
} catch(Exception e) {
System.out.println(e);
e.printStackTrace();
}

On crée donc un Player grâce au manager qui nous permet facilement, d’envoyer le MediaLocator en paramètre et de pouvoir capturer le flux audio et là c’est magique, ça marche ! Alors oui, c’est un peu plus compliqué ça en réalité, là c’est le strict minimum a utilisé mais vous voyez peut-être déjà comment envoyer des données audio ou vidéo via le réseau, on utilise un processor pour transférer le flux qu’on capture en paquet RTP et on couple la DataSource obtenue avec un DataSink qui enverra cette source à une adresse du type rtp://192.168.0.12:2000/audio. Pour jouer, du côté client, on créera un Player avec comme MediaLocator : rtp://127.0.0.1:2000/audio par exemple. Le broadcast est alors enfantin en envoyant sur l’adresse de broadcast, de ce fait, tous les clients écoutant l’adresse : rtp://192.168.0.255:2000/audio (par exemple) pourront recevoir les données.

Fin

Voilà, j’espère que certains auront eu le courage d’aller jusqu’au bout de la lecture et que c’était pas trop technique, j’ai pas l’impression en tout cas. Si j’arrive au final à avoir mon application (je dois aussi créer un applet Java pour pouvoir l’utiliser à partir d’un navigateur), sachez qu’elle sera open-source et totalement à votre disposition, j’en reparlerais surement. Prochaine étape, implémentation de la couche SIP pour pouvoir communiquer avec un serveur Asterisk !

Liens qui m’ont servi à rédiger ce bref article :

Tags: , ,

8 commentaires pour “Le Java Media Framework ou comment véhiculer du son en Java”

  1. El_Porico dit :

    C’est étrange, je pensais que tous les nouveaux projets étaient bati sur .NET maintenant; Java étant une techno encore bonne mais plus sur laquelle on ne construit plus vraiment de nouvelles choses.

    Enfin bref, désolé de dériver sur une rant de techno. Tu sais ce qui se cache derrière cette lib? DirectSound? Un autre truc?

  2. Sky dit :

    .NET est un de mes framework préféré, le C#, c’est tellement magique comme langage ! Enfin là en l’occurrence, ce sera porté sur du linux donc ça doit être multi-plateforme est comme j’ai pas encore eu l’occasion de tester Mono (le portage de .NET sur linux), je me suis tourné vers Java. En ce qui concerne ce qui se cache derrière JMF, je n’en ai aucune idée mais ça à l’air de plutôt bien fonctionner, c’est ce qui m’importe :)

  3. Manuel_Calavera dit :

    J’utilise pas mal Java pour mes projets perso, et vu que mes projets ont rapport avec la MAO, j’ai pas mal cherché ce qui était faisable dans le domaine du son, avec Java.
    Même si JMF et JavaSound permettent de faire des chouettes trucs, elles sont complètement abandonnées par Sun (depuis 2003 il me semble).
    Du coup, je me suis rabattu sur NativeFmodEx, qui est un Wrapper de FmodEx.

  4. Sky dit :

    Fmod est en effet plus que sympa. Mais en ce qui concerne l’envoi sous forme de paquets RTP ? C’est nativement possible ? Je me suis pas trop posé de questions en fait puisque je cherche juste à récupérer le son du micro et JMF semble le faire très bien.

  5. Manuel_Calavera dit :

    je sais pas trop vu que c’est un domaine que je n’ai jamais eu à utiliser, mais il me semblait avoir lu que la partie streaming était assez puissante. ( http://www.fmod.org/index.php/products/fmodexdetailed )
    Bon après, c’est clair que si JMF fait tout ce que tu veux, t’as aucun intérêt à changer d’API.

  6. Sky dit :

    Ouai, je pense rester sur JMF pour le moment. Par contre, je garde ça sous le coude, ça peut-être sympa de jouer avec une API comme fmod, y’a l’air d’avoir certains trucs bien intéressant.

  7. lightningbuzz dit :

    “Donc le Java, ce langage limite magique, qui gère la mémoire pas toujours de la meilleure manière qui soit”
    puis
    “.NET est un de mes framework préféré, le C#, c’est tellement magique comme langage”

    Je n’ai jamais fait du .Net mais en quoi C#/.Net a une meilleure gestion de la mémoire que Java ? voir en quoi c’est un meilleur langage en général ?

    “C’est étrange, je pensais que tous les nouveaux projets étaient bati sur .NET maintenant;”
    Ou pas.
    Le “parc Java” existant de projets, de développeurs et de frameworks éprouvés est énorme.
    Ce n’est pas “orienté” Windows / Microsoft (Open source tout ca…).

    “Java étant une techno encore bonne mais plus sur laquelle on ne construit plus vraiment de nouvelles choses.”
    Du tout …. GWT 2, Scala, Groovy, Clojure, Grails, Play! et j’en sortirais des tonnes.
    Au contraire c’est impossible de suivre toutes les nouvelles choses du monde “Java”. Je pense que c’est d’ailleurs plutot le probleme par rapport à .Net.

  8. Sky dit :

    Je ne parlais pas de la mémoire puisque le .NET utilise aussi un garbage collector et que je ne sais pas lequel est le mieux. Reste que la documentation pour .NET est juste énorme et que la communauté est immense, alors oui pour Java aussi mais pas sûr que ce soit aussi énorme.

    Après, il y’a aussi le fait que le C# est un dérivé du C++ qui est un langage que j’apprécie tout particulièrement et pour finir, la JVM a tendance a bouffé pas mal de ressources. Alors certes avec le .Net, on se coltine aussi une couche intermédiaire mais comme elle est faite pour l’os lui même, on gagne en performance.

Laisser un commentaire

Si vous avez un compte sur WeFrag, connectez-vous pour publier un commentaire.

Vous pouvez, entre autres, utiliser les tags XHTML suivant :
<a href="" title="">...</a>,<b>...</b>,<blockquote cite="">...</blockquote>,<code>...</code>,<i>...</i>