我使用JMF为使用JAIN-SIP的应用程序发送和接收音频,下面是我的代码:
import com.sun.media.rtp.RTPSessionMgr;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.media.*;
import javax.media.format.AudioFormat;
import javax.media.format.UnsupportedFormatException;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
import javax.media.rtp.InvalidSessionAddressException;
import javax.media.rtp.ReceiveStream;
import javax.media.rtp.ReceiveStreamListener;
import javax.media.rtp.SendStream;
import javax.media.rtp.SessionAddress;
import javax.media.rtp.event.NewReceiveStreamEvent;
import javax.media.rtp.event.ReceiveStreamEvent;
import java.net.*;
import javax.media.control.TrackControl;
import javax.media.rtp.*;
import com.sun.media.rtp.*;
import javax.media.rtp.RTPManager;
/**
*
* @author dexter
*/
public class Transmitter extends Thread implements ReceiveStreamListener {
static Processor mp;
static DataSink ds;
String ip,port;
RTPManager rtp;
SendStream ss;
ReceiveStream rs;
DataSource rds,ods,source;
Player player;
SessionAddress remoteaddr;
public void run()
{
try {
Format[] formats= new Format[]{new AudioFormat(AudioFormat.ULAW_RTP)};
ContentDescriptor cd= new ContentDescriptor(ContentDescriptor.RAW_RTP);
Vector devices= CaptureDeviceManager.getDeviceList(new
AudioFormat("linear",8000,16,2));
System.out.println("devices="+devices);
CaptureDeviceInfo di=(CaptureDeviceInfo) devices.firstElement();
System.out.println("device info="+di);
MediaLocator ml= di.getLocator();
System.out.println("locator="+ml);
try {
source = javax.media.Manager.createDataSource(ml);
}
catch (Exception e) {
// Try JavaSound Locator as a last resort
try {
source= javax.media.Manager.createDataSource(new MediaLocator("javasound://"));
}
catch (Exception ee) {
System.err.println("Couldn't create DataSource");
}
}
mp=Manager.createRealizedProcessor(new ProcessorModel(source,formats,cd));
mp.start();
rtp=RTPManager.newInstance();
// rtp.addReceiveStreamListener((ReceiveStreamListener) this);
SessionAddress localaddr= new SessionAddress(InetAddress.getByName(Phone.ip),Integer.parseInt(SipLayer.caller_port));
remoteaddr= new SessionAddress(InetAddress.getByName(ip),new Integer(port));
rtp.initialize(localaddr);
rtp.addReceiveStreamListener(this);
rtp.addTarget(remoteaddr);
ss=rtp.createSendStream(mp.getDataOutput(),0);
// mp.start();
ss.start();
} catch (UnsupportedFormatException ex) {
Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
} catch (InvalidSessionAddressException ex) {
Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
} catch (CannotRealizeException ex) {
Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoProcessorException ex) {
Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
}
}
public Transmitter(String callee_ip,String callee_port)
{
ip=callee_ip;
port= callee_port;
}
public void update(ReceiveStreamEvent rse) {
if(rse instanceof NewReceiveStreamEvent)
{
try {
rs = rse.getReceiveStream();
rds = rs.getDataSource();
player = Manager.createPlayer(rds);
player.start();
} catch (IOException ex) {
Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
} catch (NoPlayerException ex) {
Logger.getLogger(Transmitter.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public void stop_media()
{
try{
player.stop();
player.deallocate();
player.close();
ss.stop();
// necessary for sending rtcp bye
mp.stop();
mp.close();
mp.deallocate();
ss.close();
//
rtp.removeTarget(remoteaddr," disconnected");
rtp.dispose();
}catch(Exception e){
}
}
}
问题是:当我创建一个连接从我的应用程序(i。(我打电话)没有问题,我可以发送和接收音频。但当我接到电话时,我能听到对方的声音,但对方听不见听到我。在wireshark中,目标端口不可达。请建议这个问题的解决方案是什么,为什么会出现这个问题。
无论如何,我已经解决了这个问题,我认为这是很多人的问题,所以请不要删除它。出现"端口不可达"的原因很简单:您分配的端口可能已被使用,或者您可能忽略了RTP需要偶数端口来发送数据,而RTCP需要奇数端口。并且RTCP由JMF自动处理。因此,只需找到一个未使用的偶数UDP端口并使用它发送RTP。另外,如果无法接收任何数据包(SIP或RTP),则禁用防火墙
public static int findFreePort() {
DatagramSocket socket = null;
int port=1;
try {
while(port%2!=0)
{
socket = new DatagramSocket(0);
socket.setReuseAddress(true);
port = socket.getLocalPort();
socket.close();
}
return port;
} catch (IOException e) {
} finally {
if (socket != null) {
socket.close();
}
}
throw new IllegalStateException("Could not find a free UDP port to start");
}