/* / Copyright (C) 2009 Risto Känsäkoski- Sesca ISW Ltd / / This file is part of SIP-Applet (www.sesca.com, www.purplescout.com) / / This program is free software; you can redistribute it and/or / modify it under the terms of the GNU General Public License / as published by the Free Software Foundation; either version 2 / of the License, or (at your option) any later version. / / This program is distributed in the hope that it will be useful, / but WITHOUT ANY WARRANTY; without even the implied warranty of / MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the / GNU General Public License for more details. / / You should have received a copy of the GNU General Public License / along with this program; if not, write to the Free Software / Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package com.sesca.audio; import java.net.DatagramSocket; import java.net.SocketException; import com.sesca.misc.Logger; import local.net.RtpPacket; import local.net.RtpSocket; public class RtpReceiver extends Thread implements AudioReceiver { AudioReceiverListener listener=null; /** Whether working in debug mode. */ //private static final boolean DEBUG=true; public static boolean DEBUG=false; /** Size of the read buffer */ public static final int BUFFER_SIZE=32768; //public static final int BUFFER_SIZE=512; /** Maximum blocking time, spent waiting for reading new bytes [milliseconds] */ public static final int SO_TIMEOUT=200; /** The RtpSocket */ RtpSocket rtp_socket=null; /** Whether the socket has been created here */ boolean socket_is_local=false; /** Whether it is running */ boolean running=false; long lastSequenceNumber=0; long lastTimeStamp=0; /** Constructs a RtpStreamReceiver. * @param output_stream the stream sink * @param local_port the local receiver port */ public RtpReceiver(int local_port) { try { DatagramSocket socket=new DatagramSocket(local_port); socket_is_local=true; init(socket); } catch (Exception e) { e.printStackTrace(); } } /** Constructs a RtpStreamReceiver. * @param output_stream the stream sink * @param socket the local receiver DatagramSocket */ public RtpReceiver(DatagramSocket socket) { init(socket); } /** Inits the RtpStreamReceiver */ private void init(DatagramSocket socket) { if (socket!=null) rtp_socket=new RtpSocket(socket); // try { // //socket.setReceiveBufferSize(800); //// System.out.println("*************************************** RTP buffer size *******************"); //// System.out.println(socket.getReceiveBufferSize()); // // } catch (SocketException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } } /** Whether is running */ public boolean isRunning() { return running; } /** Stops running */ public void halt() { Logger.warning("RptReceiver.halt: halt requested"); running=false; } /** Runs it in a new Thread. */ public void run() { if (rtp_socket==null) { Logger.error("RTP socket=null"); return; } //else byte[] buffer=new byte[BUFFER_SIZE]; RtpPacket rtp_packet=new RtpPacket(buffer,0); running=true; try { rtp_socket.getDatagramSocket().setSoTimeout(SO_TIMEOUT); while (running) { try { // read a block of data from the rtp socket Logger.hysteria("RtpReceiver.run"); rtp_socket.receive(rtp_packet); Logger.hysteria("RtpReceiver.run: got something from network"); Logger.hysteria("RtpReceiver.run: listenter="+listener.getClass()); long sn = rtp_packet.getSequenceNumber(); long ts = rtp_packet.getTimestamp(); if (lastSequenceNumber>sn)Logger.debug("Incorrect packet order... "+lastSequenceNumber+"->"+sn+" ("+lastTimeStamp+"->"+ts+")" ); if (sn-lastSequenceNumber>1)Logger.debug("Packet loss..? "+lastSequenceNumber+"->"+sn+" ("+lastTimeStamp+"->"+ts+")"); lastSequenceNumber=sn; lastTimeStamp=ts; if (rtp_packet==null)Logger.error("rtp_packet=null"); //else Logger.debug("rpt_packet!=null"); if (this.listener==null)Logger.error("listener=null"); //else Logger.debug("listener!=null"); if (this.listener!= null && running) { byte[] payload=rtp_packet.getPayload(); int ptype=rtp_packet.getPayloadType(); Logger.hysteria("RtpReceiver.run: Received packet."); this.listener.onIncomingReceivedFrame(payload,ptype); } else if (this.listener==null) Logger.error("AudioReceiverListener = null"); } catch (java.io.InterruptedIOException e) { } } } catch (Exception e) { Logger.info("RtpReceiver.run encountered an exception and was stopped"); running=false; } // close RtpSocket and local DatagramSocket DatagramSocket socket=rtp_socket.getDatagramSocket(); rtp_socket.close(); if (socket_is_local && socket!=null) socket.close(); // free all rtp_socket=null; } public void onReceivedFrame(byte[] b) { // TODO Auto-generated method stub } public void close() { // TODO Auto-generated method stub Logger.info("RtpReceiver.close: Closing rtp socket"); if (rtp_socket != null) rtp_socket.close(); else Logger.debug("rtp_socket is null!"); } public void init(AudioReceiverListener listener) { this.listener=listener; // TODO Auto-generated method stub } public void go() { // TODO Auto-generated method stub start(); } }