RTP потоковая передача в SIP
Я новичок в SIP и RTP оба. Мне удалось создать вызов SIP, но у меня все еще нет голоса для сеанса.
Я понимаю, что мне нужно создать поток RTP и отправлять пакеты. Но я не могу решить, с чего начать. Я нашел библиотеки JMf (jar), но не могу понять, как их использовать. Также я хочу воспроизвести аудио человеку, которому я звоню во время транзакции.
Должен ли я начать сеанс RTP внутри SIP INVITE или мне нужно создать сеанс RTP после ответа на вызов отдельно? Я не могу найти ответы на свой вопрос.
Также я хотел бы знать, как мне создать сеанс RTP, и я делаю простое программирование на Java, я нашел учебник по JMf, но с установкой. Я хочу знать, если это возможно с помощью простого программирования Java. У меня есть файл jmf-2.1.1e.jar. Я хотел бы знать, как его использовать.
public SoundSenderDemo(boolean isLocal, int RTPsocket) {
DatagramSocket rtpSocket = null;
DatagramSocket rtcpSocket = null;
int socket = RTPsocket;
try {
rtpSocket = new DatagramSocket(socket);
rtcpSocket = new DatagramSocket(socket+1);
} catch (Exception e) {
System.out.println("RTPSession failed to obtain port");
}
rtpSession = new RTPSession(rtpSocket, rtcpSocket);
rtpSession.RTPSessionRegister(this,null, null);
Participant p = new Participant("sip:username@password",socket,(socket + 1));
// rtpSession.addParticipant(p);
System.out.println("CNAME: " + rtpSession.CNAME());
System.out.println("RTPSession: " + rtpSession.toString());
System.out.println("Participant: " + rtpSession.getParticipants());
System.out.println("unicast Receivers: " + rtpSession.getUnicastReceivers());
this.local = isLocal;
}
public void run() {
if(RTPSession.rtpDebugLevel > 1) {
System.out.println("-> Run()");
}
File soundFile = new File(filename);
if (!soundFile.exists()) {
System.err.println("Wave file not found: " + filename);
return;
}
AudioInputStream audioInputStream = null;
try {
audioInputStream = AudioSystem.getAudioInputStream(soundFile);
} catch (UnsupportedAudioFileException e1) {
e1.printStackTrace();
return;
} catch (IOException e1) {
e1.printStackTrace();
return;
}
//AudioFormat format = audioInputStream.getFormat();
AudioFormat.Encoding encoding = new AudioFormat.Encoding("PCM_SIGNED");
AudioFormat format = new AudioFormat(encoding,((float) 8000.0), 16, 1, 2, ((float) 8000.0) ,false);
System.out.println(format.toString());
if(! this.local) {
// To time the output correctly, we also play at the input:
auline = null;
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
try {
auline = (SourceDataLine) AudioSystem.getLine(info);
auline.open(format);
} catch (LineUnavailableException e) {
e.printStackTrace();
return;
} catch (Exception e) {
e.printStackTrace();
return;
}
if (auline.isControlSupported(FloatControl.Type.PAN)) {
FloatControl pan = (FloatControl) auline
.getControl(FloatControl.Type.PAN);
if (this.curPosition == Position.RIGHT)
pan.setValue(1.0f);
else if (this.curPosition == Position.LEFT)
pan.setValue(-1.0f);
}
auline.start();
}
int nBytesRead = 0;
byte[] abData = new byte[EXTERNAL_BUFFER_SIZE];
long start = System.currentTimeMillis();
try {
while (nBytesRead != -1 && pktCount < 200) {
nBytesRead = audioInputStream.read(abData, 0, abData.length);
if (nBytesRead >= 0) {
rtpSession.sendData(abData);
//if(!this.local) {
auline.write(abData, 0, abData.length);
//dataCount += abData.length;
//if(pktCount % 10 == 0) {
// System.out.println("pktCount:" + pktCount + " dataCount:" + dataCount);
//
// long test = 0;
// for(int i=0; i<abData.length; i++) {
// test += abData[i];
// }
// System.out.println(Long.toString(test));
//}
pktCount++;
//if(pktCount == 100) {
// System.out.println("Time!!!!!!!!! " + Long.toString(System.currentTimeMillis()));
//}
//System.out.println("yep");
}
if(pktCount == 100) {
Enumeration<Participant> iter = this.rtpSession.getParticipants();
//System.out.println("iter " + iter.hasMoreElements());
Participant p = null;
while(iter.hasMoreElements()) {
p = iter.nextElement();
String name = "name";
byte[] nameBytes = name.getBytes();
String data= "abcd";
byte[] dataBytes = data.getBytes();
int ret = rtpSession.sendRTCPAppPacket(p.getSSRC(), 0, nameBytes, dataBytes);
System.out.println("!!!!!!!!!!!! ADDED APPLICATION SPECIFIC " + ret);
continue;
}
if(p == null)
System.out.println("No participant with SSRC available :(");
}
}
} catch (IOException e) {
e.printStackTrace();
return;
}
System.out.println("Time: " + (System.currentTimeMillis() - start)/1000 + " s");
try { Thread.sleep(200);} catch(Exception e) {}
this.rtpSession.endSession();
try { Thread.sleep(2000);} catch(Exception e) {}
if(RTPSession.rtpDebugLevel > 1) {
System.out.println("<- Run()");
}
}
При отправке ACK
dialog.sendAck(ackRequest);
// System.out.println(ackRequest.toString());
logger.debug(ackRequest.toString());
aDemo = new SoundSenderDemo(false, RTPsocket);
RTPstart();
public void RTPstart(){
// Start RTP Session
String file = "C:/universAAL/workspaces/SIPfinaltest withRTP/SIPfinaltest/JSIP/garfield_converted.wav";
// SoundSenderDemo aDemo = new SoundSenderDemo(false);
aDemo.filename = args[0];
aDemo.run();
System.out.println("pktCount: " + aDemo.pktCount);
}
Также в приглашении я установил:
String sdpData = "v=0\n" +
"o=user1 795808818 480847547 IN IP4 "+localIP+"\n" +
"s=-\n" +
"c=IN IP4 "+localIP+"\n" +
"t=0 0\n" +
"m=audio 8000 RTP/AVP 0 8 101\n" +
"a=rtpmap:0 PCMU/8000\n" +
"a=rtpmap:8 PCMA/8000\n" +
"a=rtpmap:101 telephone-event/8000\n" +
"a=sendrecv";
byte[] contents = sdpData.getBytes();
Это ответ:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.99.134.149:5060;branch=z9hG4bK-333831-44ef6fc075d847c6420a0f95b2022345;received=10.99.134.149;rport=5060
From: <sip:top160_167@10.99.64.2>;tag=-1209613008
To: <sip:86940140@10.99.64.2>;tag=as12f64e9a
Call-ID: 5ac297147c47e8e20cc148dda4f350cf@10.99.134.149
CSeq: 5 INVITE
Server: Asterisk PBX 10.5.1
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH
Supported: replaces,timer
Contact: <sip:86940140@10.99.64.2:5060>
Content-Type: application/sdp
Content-Length: 255
v=0
o=root 532626251 532626252 IN IP4 10.99.64.2
s=Asterisk PBX 10.5.1
c=IN IP4 10.99.64.2
t=0 0
m=audio 7758 RTP/AVP 8 101
a=rtpmap:8 PCMA/8000
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-16
a=silenceSupp:off - - - -
a=ptime:20
a=sendrecv
1 ответ
Если вы заинтересованы в установлении сессии sip / rtp с помощью простого программирования Java, проверьте http://peers.sourceforge.net/. Взгляните на страницу документации.
JMF устарел. В Интернете есть много стеков Java RTP, просто Google "стек Java Java RTP".
Когда подходящее время, чтобы начать сеанс rtp? Зависит от того, что иногда вы можете запустить его только тогда, когда получите ответ 200 OK, иногда вам нужно создать его раньше, когда ответ получен 183.
Вы также можете создать сеанс rtp при отправке приглашения, а затем обновить его правильной информацией при получении (удаленный IP-адрес, порт, кодек).