Combination View Flat View Tree View
Threads [ Previous | Next ]
Hello Everyone,
 
  I have been advised to use JMF for sending an audio file after the call is connected as the Cisco JTAPI implementation doesn't support javax.telephony.media.* , and hence its methods can not be used. The problem however is that I amfinding it very difficult to have the two integrated (JTAPI and JMF).
 
  I am able to caputure the callConnectedEv and I guess, in that block of callConnectedEv, that I have to use the JMF portion when the stream will be sent to the receiver. The issue is that how will we connect the two pieces. How would my JMF piece know that it is this connection that the stream should be transmitted.
 
Can some one who has an idea on this or has worked with similar kind of problem throw some light on this. Any sample piece of code would be of great help. Any new solution without the use of JMF to pass audio file in Cisco JTAPI is also welcomedemoticon
 
Thanks
Manas Varma

I have no problems with use of JMF with JTAPI. You need to use a CTI Port to transmit your files into a call. When you register CTI Port you specify a port where you will receive RTP traffic for an active call. Connect CTI Port to Cisco Call and you will receive a CiscoRTPOutputStarted event that will inform you about port and ip address where you need to transmit your file. But i need to warn you that JMF is very buggy. And sometimes you need to find a JMF sources and corrent them yourself (or write your own plgins for it). But, i am working with JTAPI and JMF about two years and still don't find better solution than JMF. All other solutions is more worse.

RE: JMF and JTAPI
Answer
2/27/12 1:37 PM as a reply to Sergei Gorbunov.
Hi Sergei,

Can you provide some code example? As Manas Varma, i spent my last weeks trying to put JMF and JTAPI working together, but no luck with this.

RE: JMF and JTAPI
Answer
2/28/12 1:28 AM as a reply to Nuno Magalhaes.
With my personal experience as developer, I wouldnt suggest JMF. In my opinion, JMF is ok if you are writing a client application(like a soft phone) and would be handling one or few streams at any time.
I have burnt my hands trying out JMF with server side applications trying to handle multiple streams and JMF wasnt any good with that. After a certain call load(it wasnt too huge), rtp streams started breaking up. I didnt fight too much trying to fit JMF into my solution after initial test results but it could be that I wasnt doing it right but there was very little help available to me. It was hard to find any documentation or support on JMF, most of the support and document links on Oracle website are broken and its hard to move in right direction even if you know how basic processor works with streams.
Moreover, there hasnt been any work done on JMF by Sun (and oracle now) since its last release in 2001 which was more than 10 years ago. So, it seems like an abaondoned initiative.
 
Coming to the problem as such, I have had trouble finding a robust media library/server based on JAVA so as lot of others, I had exact same question on what to use for Media streaming which can actually be seen in one of the other posts on forum. The best answer I got was writing your own RTP stack based on RFC which is what was done by one of the application developer who had responded to my post. I am myself still trying to find if ther are any better alternatives(java based) available to JMF.

RE: JMF and JTAPI
Answer
2/28/12 4:01 AM as a reply to Abhishek Malhotra.
Abhishek, we use JMF in our applications in many circumstances and with huge load too (SPANless recorder as example). Yes, it was buggy, but i am have fixed some JMF sources and wrote some plugins (RTPConnectors and DataSources) and it works fine for us. I think writing library of the same level is very expensive. I think this is best JAVA solutuon by its time/cost.

Nuno, i dont understand what you mean when you said " put JMF and JTAPI working together".

Manas, i dont understand what case you trying to implement, please give me more details.

RE: JMF and JTAPI
Answer
2/28/12 7:30 AM as a reply to Sergei Gorbunov.
Hi Sergei,

In my scenario , below are the sequence of events that needs to take place.

1. Place a call to "A".
2. After the call is connected( A picks up), send an audio file to him asking him to press "1".
3. Once he presses "1", connect a call to B.
4. Put A and B into conference.


While we are able to implement the part 1 and 4 of our scenario , we are stuck at 2 and 3. Can you please help us with the snippet if yours where you are using JMF to send the audio file to a connected party. That will really solve our problem.

Regards,
Manas Varma

Hi Sergei

When i say put JMF and JTAPI working toghether, i mean the same you suggest to Manas Varma, use a cti port to transmit the audio file to the call. If you can provide some snippet of code, i will be very grateful. I never worked with JMF, and i can't understand the examples i saw, and i don't have experience working with cti ports in JTAPI. Please help me if you can.
Thanks in advance.

Regards
Nuno Magalhães

RE: JMF and JTAPI
Answer
3/1/12 8:46 AM as a reply to Nuno Magalhaes.
Hi Sergei/Abhishek,

Can you guys please help me out with some code snippet of yours where you are using JMF . That will really help me get going with the project.

Regards,
Manas Varma

This is will be a very huge snippet. You must read JMF fundamentals. And there are many code examples of using JMF.

Manas, IP Phones Services may be helpful for you for playing a sound to Agent (see RTPRx command).

In all cases you got an IP address and port (from CTI port OutputStarted event or from RTPRx command) where you must play a sound in desired format via RTP protocol (in most cases PCMU 8000 samples 20 ms). There are many examples on the net of how to play a sound file via network.

RE: JMF and JTAPI
Answer
3/1/12 5:46 PM as a reply to Sergei Gorbunov.
Hi Sergei,

I already implemented the transmiting of a sound file to the ctiport, but i can't ear any sound on the ctioport, but if i use JMFStudio and open a rtp session to the ip and port of the ctiport, i can ear the sound. I tried almost all CiscoMediaCapability on ctiport registration, but no success, what i´m doing wrong?

Code of ctiport registration:
....
CiscoMediaTerminal cmterm = provider.getMediaTerminal(ctiport);
CiscoMediaCapability[] caps = new CiscoMediaCapability[]{
CiscoMediaCapability.G711_64K_30_MILLISECONDS
};
cmterm.register(inetaddr, portInt, caps);
....

Code of JMF to transmit sounf file to ctiport:

Format[] FORMATS = new Format[]{new AudioFormat(AudioFormat.MPEG_RTP)};
ContentDescriptor CONTENT_DESCRIPTOR = new ContentDescriptor(ContentDescriptor.RAW_RTP);

......
DataSource ds = Manager.createDataSource(new MediaLocator("file:\\c:\\a.wav"));
mediaProcessor = Manager.createRealizedProcessor(new ProcessorModel(ds, FORMATS, CONTENT_DESCRIPTOR));
mediaLocator = new MediaLocator("rtp://192.168.32.47:8500/audio"); // ip and port of ctiport
dataSink = Manager.createDataSink(mediaProcessor.getDataOutput(), mediaLocator);
mediaProcessor.start();
dataSink.open();
dataSink.start();
......


Thanks in advance

Regards
Nuno Magalhães

RE: JMF and JTAPI
Answer
3/5/12 3:36 AM as a reply to Nuno Magalhaes.
Don't use a medialocator as output, use RTPManager for transmitting processor output. And, by default JMF make packet size bigger than you want and in result you transmitting in format of 60 msec between packets instead of 20 msec. Most of cisco phone will play it fine, but some models will play nothing, you must do one of two things: get Control of RTPPacetizer from processor and set right packet size or find a source of RTPPacketizer on the net, compile your own class and make your own JMF jar.

RE: JMF and JTAPI
Answer
3/7/12 12:55 PM as a reply to Sergei Gorbunov.
Now with RTPManager i have the following code:

...
RTPManager rtpManager = RTPManager.newInstance();
SessionAddress localAddress = new SessionAddress();
rtpManager.initialize(localAddress);
InetAddress ipAddress = InetAddress.getByName("192.168.32.47");
SessionAddress remoteAddress = new SessionAddress(ipAddress, 8500);
rtpManager.addTarget(remoteAddress);
DataSource dataOutput = Manager.createDataSource(new MediaLocator("file:\\c:\\a.wav"));
sendStream = rtpManager.createSendStream(dataOutput, 1);
mediaProcessor = Manager.createProcessor(dataOutput);
mediaProcessor.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
mediaProcessor.configure();
sendStream.start();
mediaProcessor.start();
...



But the code is executed till line "sendStream = rtpManager.createSendStream(dataOutput, 1);" the code after this line isn't executed and i don't get any exception, what i'm doing wrong?
Can help me with setting the packet size, i can't find any example in the net, and i don't see how to do that..

RE: JMF and JTAPI
Answer
3/15/12 11:53 AM as a reply to Nuno Magalhaes.
Hi All,

We have incorporated the JMF integration with JTAPI and are able to send the audio file over the Call after the call is connected. However, what we have observed is that there is a distinct "noise" that gets transmitted along with the wave file , making it absouloutely impossible for the reciever at the other end to listen. I presume , its an issue with codec

Below is the snippet , where we have passed the codec information. Can you please help us in finding out , where the problem lies. Whats the fault in the codec or is our assumption of a codec fault itself is wrong and the noise is due to some other reason ?

Thanks
Manas Varma

processr.setContentDescriptor( new ContentDescriptor( ContentDescriptor.RAW_RTP));
TrackControl track[] = processr.getTrackControls();
boolean encodingOk = false;

for (int i = 0; i < track.length; i++)
{
if (!encodingOk && track instanceof FormatControl)
{

if (((FormatControl)track). setFormat( new AudioFormat(AudioFormat.ULAW_RTP,
8000,
8,
1)) == null)
{

track.setEnabled(false);

}
else {


encodingOk = true;
}
}
else
{
track.setEnabled(false);
}
}

As i sad earlier this noise happens because JMF Packetizer default packet size 480 instead of 160. You need to manipulate a packetizer controls over the processor or find a "Packetizer extends com.ibm.media.codec.audio.AudioPacketizer" sources on the net, change default packet size and reassembly yours JMF package. There is a site with most complete JMF sources, enjoy emoticon

http://jcs.mobile-utopia.com/servlet/Source?type=s&q=Packetizer

Hi Sergei & Manas,

We are facing some issue while trying to play wav file to phone using CTI Port. I am attaching my code 7 excecption here (value of i will indicate where we r geiing the error i.e. in line sendStream = rtpManager.createSendStream(dataOutput, 1); in our case) -


==================== CODE ===================================
SendStream sendStream;
ip="192.168.4.120";
RTPManager rtpManager = RTPManager.newInstance();
i=1;
SessionAddress localAddress = new SessionAddress();
i=2;
rtpManager.initialize(localAddress);
i=3;
InetAddress ipAddress = InetAddress.getByName(ip);
i=4;
System.out.println(" ********* ipAddress ************ "+ipAddress);
SessionAddress remoteAddress = new SessionAddress(ipAddress, 8500);
i=5;
rtpManager.addTarget(remoteAddress);
i=6;
DataSource dataOutput = Manager.createDataSource(new MediaLocator("file:\\c:\\a.wav") );
i=7;
sendStream = rtpManager.createSendStream(dataOutput, 1);
i=8;
mediaProcessor = Manager.createProcessor(dataOutput);
i=9;
mediaProcessor.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
i=10;
mediaProcessor.configure();
i=11;
sendStream.start();
i=12;
mediaProcessor.start();
i=13;

=================================================================

********************* EXCEPTION *************************************

java.lang.ClassCastException: com.sun.media.protocol.file.DataSource cannot be cast to javax.media.protocol.PushBufferDataSource i 7

******************************************************

Your input will help me to proceed further.

Thanks in advance.

Regards,
Vinay

RE: JMF and JTAPI
Answer
5/21/12 3:29 AM as a reply to javavinay88 (simulated).
What is your wav file payload type?

RE: JMF and JTAPI
Answer
5/21/12 4:01 AM as a reply to javavinay88 (simulated).
you make mistake in your code, i think this is what you want :

SendStream sendStream;
ip="192.168.4.120";
RTPManager rtpManager = RTPManager.newInstance();

InetAddress ipAddress = InetAddress.getByName(ip);

//This you need to do to avoid a trasmit start lag (Force DNS method)
byte[] badr = ipAddress.getAddress();
ipAddress = InetAddress.getByAddress(InetAddress.getLocalHost().getHostName(), badr);

SessionAddress localAddress = new SessionAddress(InetAddress.getLocalHost(), someLocalPort);

rtpManager.initialize(localAddress);

SessionAddress remoteAddress = new SessionAddress(ipAddress, 8500);

rtpManager.addTarget(remoteAddress);

//This is not output datasource! This is input datasource!
DataSource dataInput = Manager.createDataSource(new MediaLocator("file:\\c:\\a.wav") );

ProcessorModel prm = new ProcessorModel(dataInput , new ContentDescriptor(ContentDescriptor.RAW_RTP), new AudioFormat(AudioFormat.ULAW_RTP, 8000, 8, 1));

Processor processor = Manager.createRealizedProcessor(prm);

//This is output datasource
DataSource dataOutput = processor.getDataOutput();

sendStream = rtpManager.createSendStream(dataOutput, 1);

sendStream.start();

mediaProcessor.start();

RE: JMF and JTAPI
Answer
5/21/12 8:23 AM as a reply to Sergei Gorbunov.
Hi,

Here I found some exception at runtime.
Exception is : java.lang.ArrayIndexOutOfBoundsException: 1
at sendStream = rtpManager.createSendStream(dataOutput, 1);

And I think here We can not pass 0 at the place of 1, because it is Stream index.



Please Help me.

Thanks & Best Regads
Vinay

RE: JMF and JTAPI
Answer
5/21/12 9:41 AM as a reply to javavinay88 (simulated).
You can pass 0.

RE: JMF and JTAPI
Answer
5/21/12 10:08 AM as a reply to Sergei Gorbunov.
Hi,


But when I passed 0(zero ) it also return exception at mediaProcessor.start();
And exception is java.lang.NullPointerException.





Thanks & Best Regards
Vinay

RE: JMF and JTAPI
Answer
5/21/12 10:50 AM as a reply to javavinay88 (simulated).
Hi Sergei,

We have changed our code as per your suggestion, now we are not getting any error but nothing is palying on my phone.
We are initiating call from CTI Port to normal phone and capturing the remote phone IP and port and trying to send audio stream on remote ip and port.

Are we doing anything wrong in our code or as concept wise?

Thanks & Regards,
Vinay

System.out.println("**************** Start JMF ********************** ");
Format[] FORMATS = new Format[]{new AudioFormat(AudioFormat.ULAW_RTP,8000,8,1)};
ContentDescriptor CONTENT_DESCRIPTOR = new ContentDescriptor(ContentDescriptor.RAW);
System.out.println(port+" ********* ipAddress ************ "+ip);

SendStream sendStream;
ip="192.168.4.120";
RTPManager rtpManager = RTPManager.newInstance();
i=1;
InetAddress ipAddress = InetAddress.getByName(ip);
i=2;
//This you need to do to avoid a trasmit start lag (Force DNS method)
byte[] badr = ipAddress.getAddress();
i=3;
ipAddress = InetAddress.getByAddress(InetAddress.getLocalHost().getHostName(), badr);
i=4;
SessionAddress localAddress = new SessionAddress(InetAddress.getLocalHost(), 8500);
i=5;
rtpManager.initialize(localAddress);
i=6;
SessionAddress remoteAddress = new SessionAddress(ipAddress, port);
i=7;
rtpManager.addTarget(remoteAddress);
i=8;
//This is not output datasource! This is input datasource!
DataSource dataInput = Manager.createDataSource(new MediaLocator("file:\\c:\\miles.wav") );
i=9;
ProcessorModel prm = new ProcessorModel(dataInput ,FORMATS, CONTENT_DESCRIPTOR);
i=10;
Processor processor = Manager.createRealizedProcessor(prm);
i=11;
//This is output datasource
DataSource dataOutput = processor.getDataOutput();
i=12;
sendStream = rtpManager.createSendStream(dataOutput, 0);
i=13;
sendStream.start();
i=14;
processor.start();
i=15;

RE: JMF and JTAPI
Answer
5/22/12 4:40 AM as a reply to javavinay88 (simulated).
Please, take a wareshark capture. If packets are not sent enable JMF logging and see what's happening there. If packets are sent than problem may be in phone (check latest firmware) or in JMF (have you read what i am wrote above about JMF packet size?).

RE: JMF and JTAPI
Answer
5/23/12 7:16 AM as a reply to Sergei Gorbunov.
Hi Sergei,


Thanks my Problem is solve.


Thanks & Best Regards
Vinay

RE: JMF and JTAPI
Answer
5/24/12 2:21 PM as a reply to javavinay88 (simulated).
Hi Sergei,

Here a new problem, I want to write an RTP stream to a file. But I get a Exception in the following code.

********************************************************************************************


public void update(ReceiveStreamEvent event)
{
SessionManager source = (SessionManager)event.getSource();
DataSink dataSink = null;
if (event instanceof NewReceiveStreamEvent)
{
ReceiveStream stream = null;

try
{
stream =((NewReceiveStreamEvent)event) .getReceiveStream();
Participant part = stream.getParticipant();
DataSource dsource = stream.getDataSource();
MediaLocator f = new MediaLocator("file://C:\\MyStream.wav");
dataSink= Manager.createDataSink(dsource, f);
dataSink.open();
dataSink.start();
} catch (Exception e)
{
System.err.println("newReceiveStreamEvent exception " + e.getMessage());
}
}
}




*******************************************************************************************


And Exception is - newReceiveStreamEvent exception Cannot find a DataSink for: com.sun.media.protocol.rtp.DataSource@1a7bf11




Your input will help me to proceed further.

Thanks in advance.

Thanks & Best Regards,
Vinay

RE: JMF and JTAPI
Answer
5/25/12 4:19 AM as a reply to javavinay88 (simulated).
Please, ask this question at JMF forums. This is not Cisco related question.

RE: JMF and JTAPI
Answer
5/15/13 2:03 PM as a reply to Sergei Gorbunov.
 
 


Hi,
I'm new with JTAPI and i need to place a call between my computer (ctiport) "2100" and a ciscophone "2010", i did that but the problem is when i pick up i can hear anything , what i am doing wrong


i really need help, i can't find any solution and i'm loosing a lot of time
and here's my code :
import .... ;
 
public class Makecall
{
      final int PORT_NUMBER = 8029;
      CiscoMediaTerminal terminal = null;
    
  
 
public Makecall(String[] args) throws Exception
{
            
            CiscoProvider provider=null;
            
                String hostname = "10.10.10.1";
String login = "mourad";
String passwd = "mourad";
String src = "2100";
String dst = "2010";
                             
  /* start up JTAPI */
JtapiPeer peer = JtapiPeerFactory.getJtapiPeer(null);
 
  /* connect to the provider */
String providerString = hostname;
providerString += ";login=" + login;
providerString += ";passwd=" + passwd;
provider = (CiscoProvider) peer.getProvider(providerString);
                           
                        /* wait for it to come into service */
final Condition inService = new Condition();
               
 
provider.addObserver(new ProviderObserver() {
 
                   public void providerChangedEvent (ProvEv [] eventList) {
if (eventList == null) return;
                                       for (int i=0; i <eventList.length; i++) {
                         if (eventList instanceof ProvInServiceEv)  {
                                           inService.set();
                                        }
                                      }
                                 }
            });
                inService.waitTrue();
 
/* get an object for the calling terminal */
 
Address srcAddr = provider.getAddress(src);
                Terminal srcTerm = srcAddr.getTerminals()[0];
                
                /*register terminal*/
 
              String terminalname = srcAddr.getTerminals()[0].getName();
              registerTerminal(provider,terminalname);
               
                
                  srcAddr.addCallObserver(new CallObserver() {
public void callChangedEvent (CallEv [] eventList) {
/* ignored */
}
});
                
                     DatagramSocket socket = new DatagramSocket(PORT_NUMBER, InetAddress.getLocalHost());
                 
                     
                   
                     /* create the call */
                  Call  call =  (CiscoCall) provider.createCall();
                  CallControlCall ccall = (CallControlCall)call;
    
                    Connection []c = ccall.connect(srcTerm, srcAddr, dst);
                 
                 
                    
                 System.out.println("run");
MappedByteBuffer fileContent = null;
                
                
             try
{
 
                         File file = new File ("telsonne.wav");
                        FileInputStream fin = new FileInputStream(file);
                        fileContent = fin.getChannel().map(MapMode.READ_ONLY, 0, file.length());
                          
}catch (FileNotFoundException e) {  
            System.out.println("file not found : " + e.getMessage());  
        }  
        catch (IOException eio) {  
            System.out.println("io exception " + eio.getMessage());  
        }  
    
byte [] buf = new byte[172];
 
buf[0] = (byte)0x80; //V=2 P(padding)=0 X(extension fields)=0 CC(CSRC count)=0
buf[1] = (byte)0; //M(marker)=0 Payload type = 0 (PCM ULaw)
Random random_generator = new Random();
int sequence_number = random_generator.nextInt(65536);
long timestamp = 1;
int sync_source = random_generator.nextInt();
buf[8] = (byte)(sync_source/16777216);
buf[9] = (byte)((sync_source/65536)%256);
buf[10] = (byte)((sync_source/256)%256);
buf[11] = (byte)(sync_source%256);
                long curTime1 = System.currentTimeMillis();
long curTime2 = System.currentTimeMillis();
                System.out.println(curTime2);
                
               
while (true)
try 
{       
                        buf[2] = (byte)(sequence_number/256);
buf[3] = (byte)(sequence_number%256);
buf[4] = (byte)(timestamp/16777216);
buf[5] = (byte)((timestamp/65536)%256);
buf[6] = (byte)((timestamp/256)%256);
buf[7] = (byte)(timestamp%256);
               
DatagramPacket packet = new DatagramPacket(buf, 172, InetAddress.getLocalHost(), PORT_NUMBER);
                       socket.send(packet);
                        
                        long ms2Sleep = curTime2 + 20 - System.currentTimeMillis();
                        curTime2 += 20;
System.out.println("Current Time:"+curTime2+" to sleep:"+ms2Sleep+" ms...");
                        
                        if (((curTime2 - curTime1)==60000)){
                            ccall.drop();
                            System.out.println("by 1");
                            System.exit(0);
                        }
         
               
if (ms2Sleep > 0)
Thread.sleep(ms2Sleep);
sequence_number = (sequence_number+1)&0xFFFF;
                        timestamp=(timestamp+160)&0xFFFFFFFF;
                        }
catch (Exception e){
System.out.println("Exception:"+e);
return;
}
                  
         
 }
 
 
         public static void main(String[] args) {
try {  
                       new Makecall(args);
                      
                       } catch (Exception e) {
e.printStackTrace();
  } finally {
System.exit(0);
}
}
        
        
        
           public void  registerTerminal ( Provider provider, String terminalName )  {
        try {
            terminal =  (CiscoMediaTerminal) provider.getTerminal ( terminalName );
             CiscoMediaCapability [] caps = new CiscoMediaCapability [1];
            caps[0] = (CiscoMediaCapability) CiscoMediaCapability.G711_64K_30_MILLISECONDS;
    
         
      terminal.register ( InetAddress.getLocalHost (), PORT_NUMBER, caps );
          terminal.addObserver(new TerminalObserver() {
                             public void terminalChangedEvent(TermEv[] termevs){
                                     /* ignored */
                        }
                  });
       terminal.addCallObserver(new CallObserver() {
                       public void callChangedEvent (CallEv [] eventList) {
                          /* ignored */
                          }
                   });
        } catch (ResourceUnavailableException ex1) {
            System.out.println("ResourceUnavailableException: " + ex1.getMessage());
        } catch (MethodNotSupportedException ex2) {
            System.out.println("MethodNotSupportedException: " + ex2.getMessage());
        } catch (UnknownHostException ex3) {
            System.out.println("UnknownHostException: " + ex3.getMessage());
        } catch (CiscoRegistrationException ex4) {
            System.out.println("CiscoRegistrationException: " + ex4.getMessage());
        } catch (InvalidArgumentException ex5) {
            System.out.println("InvalidArgumentException: " + ex5.getMessage());
        }
     
     
}
 
}