20

mjsip sip stack を使用してソフトフォン プロジェクトに取り組んでいます。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場合 null です。

その場合は、その理由を確認する必要があります。1 つの理由として次のことが考えられます。

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 の Web サイトから jmf.exe を入手できます。そして、その Api を使用して音声を送信できます。送信音声のコーディングも可能です。

于 2012-07-19T05:29:03.853 に答える