Java 未使用mjsip发送或接收RTP数据包
我正在使用mjsip堆栈进行一个软电话项目。Mjsip仅支持g711或PCMA/PCMU编解码器。我已将G729添加到我的项目中。当我构建项目时,它没有显示任何错误。但当手机连接后,通话就建立了,没有语音传输,实际上我的应用程序不会生成任何rtp数据包。日志中显示了一个错误,如Java 未使用mjsip发送或接收RTP数据包,java,nullpointerexception,sip,rtp,mjsip,Java,Nullpointerexception,Sip,Rtp,Mjsip,我正在使用mjsip堆栈进行一个软电话项目。Mjsip仅支持g711或PCMA/PCMU编解码器。我已将G729添加到我的项目中。当我构建项目时,它没有显示任何错误。但当手机连接后,通话就建立了,没有语音传输,实际上我的应用程序不会生成任何rtp数据包。日志中显示了一个错误,如 java.lang.NullPointerException RtpStreamReceiver - run -> Terminated. at local.media.RtpStreamReceiver.
java.lang.NullPointerException
RtpStreamReceiver - run -> Terminated.
at local.media.RtpStreamReceiver.run(RtpStreamReceiver.java:171)
我没能找到这个错误
这是我的RtpStreamReceiver.java类
package local.media;
import local.net.RtpPacket;
import local.net.RtpSocket;
import java.io.*;
import java.net.DatagramSocket;
import org.flamma.codec.SIPCodec;
/** RtpStreamReceiver is a generic stream receiver.
* It receives packets from RTP and writes them into an OutputStream.
*/
public class RtpStreamReceiver extends Thread {
public static int RTP_HEADER_SIZE = 12;
private long start = System.currentTimeMillis();
public static final int SO_TIMEOUT = 200; // Maximum blocking time, spent waiting for reading new bytes [milliseconds]
private SIPCodec sipCodec = null; // Sip codec to be used on audio session
private RtpSocket rtp_socket = null;
private boolean socketIsLocal = false; // Whether the socket has been created here
private boolean running = false;
private int timeStamp = 0;
private int frameCounter = 0;
private OutputStream output_stream;
public RtpStreamReceiver( SIPCodec sipCodec, OutputStream output_stream, int local_port )
{
try {
DatagramSocket socket = new DatagramSocket( local_port );
socketIsLocal = true;
init( sipCodec, output_stream, socket );
start = System.currentTimeMillis();
}
catch ( Exception e ) {
e.printStackTrace();
}
}
public RtpStreamReceiver( SIPCodec sipCodec, OutputStream output_stream, DatagramSocket socket )
{
init( sipCodec, output_stream, socket );
}
/** Inits the RtpStreamReceiver */
private void init( SIPCodec sipCodec, OutputStream output_stream, DatagramSocket socket )
{
this.sipCodec = sipCodec;
this.output_stream = output_stream;
if ( socket != null ) {
rtp_socket = new RtpSocket( socket );
}
}
/** Whether is running */
public boolean isRunning()
{
return running;
}
/** Stops running */
public void halt()
{
running = false;
}
/** Runs it in a new Thread. */
public void run()
{
if ( rtp_socket == null )
{
println( "run", "RTP socket is null." );
return;
}
byte[] codedBuffer = new byte[ sipCodec.getIncomingEncodedFrameSize() ];
byte[] internalBuffer = new byte[sipCodec.getIncomingEncodedFrameSize() + RTP_HEADER_SIZE ];
RtpPacket rtpPacket = new RtpPacket( internalBuffer, 0 );
running = true;
try {
rtp_socket.getDatagramSocket().setSoTimeout( SO_TIMEOUT );
float[] decodingBuffer = new float[ sipCodec.getIncomingDecodedFrameSize() ];
int packetCount = 0;
println( "run",
"internalBuffer.length = " + internalBuffer.length
+ ", codedBuffer.length = " + codedBuffer.length
+ ", decodingBuffer.length = " + decodingBuffer.length + "." );
while ( running ) {
try {
rtp_socket.receive( rtpPacket );
frameCounter++;
if ( running ) {
byte[] packetBuffer = rtpPacket.getPacket();
int offset = rtpPacket.getHeaderLength();
int length = rtpPacket.getPayloadLength();
int payloadType = rtpPacket.getPayloadType();
if(payloadType < 20)
{
System.arraycopy(packetBuffer, offset, codedBuffer, 0, sipCodec.getIncomingEncodedFrameSize());
timeStamp = (int)(System.currentTimeMillis() - start);
output_stream.write(codedBuffer,offset,length);
}
}
}
catch ( java.io.InterruptedIOException e ) {
}
}
}
catch ( Exception e ) {
running = false;
e.printStackTrace();
}
// Close RtpSocket and local DatagramSocket.
DatagramSocket socket = rtp_socket.getDatagramSocket();
rtp_socket.close();
if ( socketIsLocal && socket != null ) {
socket.close();
}
// Free all.
rtp_socket = null;
println( "run", "Terminated." );
}
/** Debug output */
private static void println( String method, String message ) {
System.out.println( "RtpStreamReceiver - " + method + " -> " + message );
}
package local.media;
导入local.net.RtpPacket;
导入local.net.RtpSocket;
导入java.io.*;
导入java.net.DatagramSocket;
导入org.flamma.codec.SIPCodec;
/**RtpStreamReceiver是一种通用的流接收器。
*它从RTP接收数据包并将其写入输出流。
*/
公共类RtpStreamReceiver扩展线程{
公共静态int RTP_头_大小=12;
private long start=System.currentTimeMillis();
public static final int SO_TIMEOUT=200;//等待读取新字节的最大阻塞时间[毫秒]
私有SIPCodec SIPCodec=null;//要在音频会话上使用的Sip编解码器
专用RtpSocket rtp_套接字=null;
private boolean socketIsLocal=false;//是否已在此处创建套接字
私有布尔运行=false;
私有int时间戳=0;
私有整数帧计数器=0;
私有输出流输出流;
公共RTP流接收器(SIPCodec SIPCodec、OutputStream output_stream、int local_端口)
{
试一试{
DatagramSocket套接字=新DatagramSocket(本地_端口);
socketIsLocal=真;
init(sipCodec、输出流、套接字);
start=System.currentTimeMillis();
}
捕获(例外e){
e、 printStackTrace();
}
}
公共RTP流接收器(SIPCodec SIPCodec、OutputStream输出流、DatagramSocket套接字)
{
init(sipCodec、输出流、套接字);
}
/**初始化RTPStream接收器*/
私有void init(SIPCodec SIPCodec、OutputStream output_stream、DatagramSocket套接字)
{
this.sipCodec=sipCodec;
this.output_stream=输出_stream;
if(套接字!=null){
rtp_插座=新的rtp插座(插座);
}
}
/**是否正在运行*/
公共布尔值正在运行()
{
返回运行;
}
/**停止运行*/
公众假期暂停
{
运行=错误;
}
/**在新线程中运行它*/
公开募捐
{
如果(rtp_套接字==null)
{
println(“运行”,“RTP套接字为空”);
返回;
}
byte[]codedBuffer=新字节[sipCodec.getIncomingEncodedFrameSize()];
byte[]internalBuffer=新字节[sipCodec.getIncomingEncodedFrameSize()+RTP_头_大小];
RtpPacket RtpPacket=新的RtpPacket(内部缓冲区,0);
运行=真;
试一试{
rtp_socket.getDatagramSocket().setSoTimeout(SO_超时);
float[]decodingBuffer=新的float[sipCodec.getIncomingDecodedFrameSize()];
int packetCount=0;
println(“运行”,
“internalBuffer.length=“+internalBuffer.length
+“,codedBuffer.length=“+codedBuffer.length
+“,decodingBuffer.length=“+decodingBuffer.length+”);
(跑步时){
试一试{
rtp_插座接收(rtpPacket);
帧计数器++;
如果(正在运行){
字节[]packetBuffer=rtpPacket.getPacket();
int offset=rtpPacket.getHeaderLength();
int length=rtpPacket.getPayloadLength();
int payloadType=rtpPacket.getPayloadType();
如果(有效载荷类型<20)
{
System.arraycopy(packetBuffer,offset,codedBuffer,0,sipCodec.getIncomingEncodedFrameSize());
时间戳=(int)(System.currentTimeMillis()-start);
输出_stream.write(codedBuffer、偏移量、长度);
}
}
}
catch(java.io.InterruptedIOException e){
}
}
}
捕获(例外e){
运行=错误;
e、 printStackTrace();
}
//关闭RtpSocket和本地DatagramSocket。
DatagramSocket socket=rtp_socket.getDatagramSocket();
rtp_socket.close();
if(socketIsLocal&&socket!=null){
socket.close();
}
//全部免费。
rtp_套接字=空;
println(“运行”、“终止”);
}
/**调试输出*/
私有静态void println(字符串方法、字符串消息){
System.out.println(“RtpStreamReceiver-”+方法+“->”+消息);
}
第171行是:output\u stream.write(codedBuffer,offset,length);
如果您感兴趣,请查看完整的项目源。正如@gnat在评论中所说的-最有可能的是
输出流
为空
如果是这种情况,您应该检查原因。原因之一可能是:
private void init(SIPCodec SIPCodec、OutputStream output\u stream、DatagramSocket套接字)
使用null参数调用,并且它覆盖以前正确设置的值
通过将以下内容作为init的第一行,可以记录调用特定函数的“who”:
System.out.println("My function is called from: "
+ Thread.currentThread().getStackTrace()[2].getClassName() + "."
+ Thread.currentThread().getStackTrace()[2].getMethodName());
对于使用RTP Java媒体框架传输语音,非常好用。从oracle网站上,你可以获得jmf.exe。你可以使用该Api传输语音。传输语音的涂层也可用。最有可能的NPE是由于
output\u stream
线程运行时,RtpStreamReceiver
为空。我会使用println
以了解情况是否如此。s