Java 未使用mjsip发送或接收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.

我正在使用mjsip堆栈进行一个软电话项目。Mjsip仅支持g711或PCMA/PCMU编解码器。我已将G729添加到我的项目中。当我构建项目时,它没有显示任何错误。但当手机连接后,通话就建立了,没有语音传输,实际上我的应用程序不会生成任何rtp数据包。日志中显示了一个错误,如

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