20

我正在使用 mjsip sip 堆栈开发一个软件电话项目。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 );
}

第 171 行是:output_stream.write(codedBuffer,offset,length);

如果您有兴趣,这里是完整的项目源代码。

4

2 回答 2

2

正如@gnat 在评论中所说 - 很可能output_stream是空的。

如果是这种情况,您应该检查原因。一个原因可能是:

private void init( SIPCodec sipCodec, OutputStream output_stream, DatagramSocket socket )

使用 null 参数调用,并且它会覆盖之前正确设置的值。

您可以通过将以下内容作为 init 的第一行来记录调用特定函数的“谁”:

System.out.println("My function is called from: "
+ Thread.currentThread().getStackTrace()[2].getClassName() + "."
+ Thread.currentThread().getStackTrace()[2].getMethodName());
于 2012-07-02T18:25:42.200 回答
0

使用 RTP Java 媒体框架传输语音非常好用。从 oracle 的网站你可以得到 jmf.exe。您可以使用该 API 传输语音。传输语音的编码也是可用的。

于 2012-07-19T05:29:03.853 回答