Et bien ca attire pas les foules :) Je pensais que y'avais des dieux de Java dans le coin ..
Ceci dit j'ai reussi avec JMF par contre j'ai un autre soucis, car c'est pas du temps reel quoi ... J'ai un delay de 100 ms a vue d'oreille sur le stream.
Voici le code:
CODE
import javax.media.*;
import javax.media.format.*;
import javax.media.protocol.*;
import javax.media.control.*;
import java.util.*;
import java.io.*;
import javax.media.rtp.*;
import java.net.InetAddress;
import javax.media.control.BufferControl;
public class RtpServer {
/**
* @param args
*/
public static void main(String[] args) {
int i, j;
int nCount=0;
CaptureDeviceInfo infoCaptureDevice;
Format arrFormats [];
// TODO Auto-generated method stub
CaptureDeviceInfo di=null;
System.out.println("test");
// Get the CaptureDeviceInfo for the live audio capture device
Vector deviceList = CaptureDeviceManager.getDeviceList(new
AudioFormat("linear", 22050, 8, 1));
if (deviceList.size()>0)
{
nCount=deviceList.size();
System.out.println("Enumerating devicelist");
for ( i = 0; i < nCount; i++ ) {
infoCaptureDevice = (CaptureDeviceInfo) deviceList.elementAt ( i );
arrFormats = infoCaptureDevice.getFormats ();
for ( j = 0; j < arrFormats.length; j++ ) {
if ( arrFormats[j] instanceof AudioFormat ) {
//vectorAudioDevices.addElement ( infoCaptureDevice );
System.out.println(infoCaptureDevice);
break;
}
}
}
}else{System.exit(0);}
/*cdiAudio = getAudioDevice();
if ( cdiAudio != null && isAudioDeviceUsed() ) {
deviceURL = cdiAudio.getLocator ();
if ( strValue.length() > 0 )
strValue = strValue + " & ";
strValue = strValue + deviceURL.toString ();
}*/
di = (CaptureDeviceInfo) deviceList.elementAt(0);
// Create a Player for the capture device: */
/*try{
Player p = Manager.createPlayer(di.getLocator());
p.start();
} catch (IOException e) {
} catch (NoPlayerException e) {}*/
// Création du MediaLocator à partir du fichier
MediaLocator FichierLocator = di.getLocator();
// Déclaration du processeur
Processor FichierCessor = null;
DataSource ds=null;
try{
//Création du Processor à partir du MediaLocator
try{
ds = Manager.createDataSource(FichierLocator);
}
catch(Exception e){}
// Check to see if there's a buffer control on the data source.
// It could be that we are using a capture data source.
Control c = (Control)ds.getControl("javax.media.control.BufferControl");
if (c != null){
((BufferControl)c).setBufferLength(1);
((BufferControl)c).setMinimumThreshold(2);
((BufferControl)c).setEnabledThreshold(true);
}
FichierCessor = Manager.createProcessor(ds);
//FichierCessor = Manager.createProcessor(ds);
//Appel des fonctions qui vont permettre le lancement du flux RTP
configure(FichierCessor);
SetSupportedFormat(FichierCessor);
//passer dans l'etat realized du processor
realize(FichierCessor);
//start
Demarre(FichierCessor);
launchRTPManager(FichierCessor);
}
catch(IOException e)
{
System.out.println("Erreur : "+e.getMessage());
}
catch(NoProcessorException e)
{
System.out.println("Erreur : "+e.getMessage());
}
}
public static Processor configure(Processor p)
{
//Attendre tant que le Processor n'est pas configuré.
while(p.getState() < Processor.Configured)
{
//Configuration du Processor
p.configure();
}
return p;
}
public static void SetSupportedFormat(Processor p)
{
//On met la description du contenu de sortie à RAW_RTP
ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
p.setContentDescriptor(cd);
//On obtient les différentes pistes du processor
TrackControl track[] = p.getTrackControls();
for(int i = 0; i < track.length; i++)
{
//on obtient les formats supportés pour cette piste
Format suppFormats[] = track[i].getSupportedFormats();
//Si il y a au moins un format supporté
//System.out.println();
for ( int t=0; t < suppFormats.length;t++)
{
System.out.println("RTP supported format: "+suppFormats[t]);
}
if(suppFormats.length > 0)
{
track[i].setFormat(suppFormats[5]);
System.err.println("Track " + i +" est transmis as :"+suppFormats[5]);
if (track[i].getFormat() instanceof AudioFormat) {
int packetRate = 5;
PacketSizeControl pktCtrl = (PacketSizeControl) p.getControl(PacketSizeControl.class.getName());
if (pktCtrl != null) {
try {
pktCtrl.setPacketSize(getPacketSize(track[i].getFormat(), packetRate));
//pktCtrl.setPacketSize(pktCtrl.getPacketSize());
//pktCtrl.setPacketSize(1);
}
catch (IllegalArgumentException e) {
pktCtrl.setPacketSize(80);
// Do nothing
}
}
}
}
else
{
track[i].setEnabled(false);
}
}
}
private static int getPacketSize(Format codecFormat, int milliseconds) throws IllegalArgumentException {
String encoding = codecFormat.getEncoding();
if (encoding.equalsIgnoreCase(AudioFormat.GSM) ||
encoding.equalsIgnoreCase(AudioFormat.GSM_RTP)) {
return milliseconds * 4; // 1 byte per millisec
}
else if (encoding.equalsIgnoreCase(AudioFormat.ULAW) ||
encoding.equalsIgnoreCase(AudioFormat.ULAW_RTP)) {
return milliseconds * 8;
}
else {
throw new IllegalArgumentException("Unknown codec type");
}
}
public static Processor realize(Processor p)
{
//Attendre tant que le Processor n'est pas réalisé.
while(p.getState() < Processor.Realized)
{
//Réalisation du Processor
p.realize();
}
return p;
}
public static void Demarre(Processor p)
{
//Demarrage du Processor
p.start();
System.err.println("Processor started");
}
public static void launchRTPManager(Processor p)
{
//Creation du DataSource correspondant au Processor
DataSource OutputSource = p.getDataOutput();
PushBufferDataSource pbds = (PushBufferDataSource)OutputSource;
PushBufferStream pbss[] = pbds.getStreams();
//Nouvelle Instance d'un RTPManager
RTPManager rtpm[] = new RTPManager[pbss.length];
//System.out.println("taille:" +pbss.length);
//RTPManager rtpm;
for(int i=0; i < pbss.length;i++)
{
try{
rtpm[i] = RTPManager.newInstance();
int port = 22224 + 2*i;
//Création d'une SessionAddress
SessionAddress localaddr = new SessionAddress(InetAddress.getLocalHost(),port);
//Initialisation du RTPManager
rtpm[i].initialize(localaddr);
//Création d'une SessionAddress
SessionAddress destaddr = new SessionAddress(InetAddress.getByName("192.168.1.11"),6666);
//Ajout de cette SessionAddress dans le RTPManager
rtpm[i].addTarget(destaddr);
System.err.println("Creation RTP session 192.168.1.12 port : "+port);
//Creation d'un SendStream à partir du DataSource
SendStream ss2 = rtpm[i].createSendStream(OutputSource,i);
//Demarrage du SendStream
ss2.start();
System.out.println("Started ");
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}
Et voici le code du client utilisé:
CODE
import java.io.IOException;
import java.net.MalformedURLException;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoPlayerException;
import javax.media.Player;
public class SimpleVoiceReceiver{
/**
* @param args
*/
public static void main(String[] args) {
String url= "rtp://192.168.1.11:6666/audio/1";
MediaLocator mrl= new MediaLocator(url);
if (mrl == null) {
System.err.println("Can't build MRL for RTP");
System.exit(-1);
}
// Create a player for this rtp session
Player player = null;
try {
player = Manager.createPlayer(mrl);
} catch (NoPlayerException e) {
System.err.println("Error:" + e);
System.exit(-1);
} catch (MalformedURLException e) {
System.err.println("Error:" + e);
System.exit(-1);
} catch (IOException e) {
System.err.println("Error:" + e);
System.exit(-1);
}
if (player != null) {
System.out.println("Player created.");
player.realize();
// wait for realizing
while (player.getState() != Player.Realized){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
player.start();
} else {
System.err.println("Player doesn't created.");
System.exit(-1);
}
}
}
J'ai le meme probleme de delay quand j'utilise VLC comme client meme en reglant le jitter RTP à 1 ...
Quand je fait du direct microphone vers Haut parleur ( sans utiliser le processor ni RTP) j'ai aucun delay, par contre des que je fous sur RTP ca delay... Vla le protocole real time ca fait peur quoi ....
J'ai essayer de virer toute les compression, de changer le packetsize du controlleur, de changer la taille du buffer etc ... et pas moyen d'avoir mieux que 100 ms ..
Je precise que les test RTP ce font sur la meme machine de port à port donc on est meme pas sur le reseau...
Une expertise Java serait la bienvenue.
MERCI