/*
 *
 * RTP MANAGER
 * Copyright 2011-2012 KWANGHAESOFT LTD.
 * Creator: JGK
 * PUBLISH DATE: Dec. 2011
 * ............................................
 * Compact Type :Checked - no related
 * Date:2012 04 27
 * ............................................
 *
 */
package cm.sip.hns;

import android.content.Context;
import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import milsip.stack.sip.RFC2833;
import milsip.stack.sip.RTPCore;
import milsip.stack.sip.SIPG711;
import milsip.stack.sip.SIPStack;

public class RTPManager {

    String TAG = "RTPManager";

    protected static DatagramSocket theSocket = null;
    protected static DatagramSocket switchedSocket = null;
    protected static DatagramPacket dp = null;
    protected static byte[] lineardata = new byte[320];
    public RTPCore rtpCore = null;
    public RFC2833 rfc2833 = null;
    public boolean bDisableVoice = false;

    Thread receiveThread = null;
    Thread sendThread = null;
    Timer RTPSENDTimer = null;

    public RTPManager(Context context, int mediaType) {
        //parent		=(TccInterface)context;
        rtpCore = new RTPCore(3000, mediaType);
        //callManager	= cm;
        rfc2833 = new RFC2833();
        //cm.registRTPManager(this,mediaType);
        theSocket = null;
        RTPSENDTimer = null;
    }//RTPManager()

    public void receiveAudio() {
        try {
            if (receiveThread != null) receiveThread.interrupt();
        } catch (Exception e) {
            Log.e(TAG, "[Exception] receiveAudio()");
        }

        try {
            Runnable runner = new Runnable() {
                DatagramSocket runningSocket = null;

                public void run() {
                    try {
                        theSocket = new DatagramSocket(rtpCore.RTP_PORT);
                        theSocket.setReuseAddress(true);
                        dp = new DatagramPacket(rtpCore.buffer, rtpCore.buffer.length);
                    } catch (SocketException e) {
                        SIPStack.exceptionCountAtCurrentCall++;
                        return;
                    } catch (NullPointerException e) {
                        SIPStack.exceptionCountAtCurrentCall++;
                        return;
                    }

                    rtpCore.running = true;
                    runningSocket = theSocket;
                    switchedSocket = theSocket;
                    while (rtpCore.running && runningSocket != null) {
                        if (receiveThread == null) break;
                        if (receiveThread.isInterrupted()) break;
                        try {
                            dp.setData(rtpCore.buffer);
                            dp.setLength(SIPStack.RTP_AUDIO_SIZE);

                            runningSocket.receive(dp);
                            if (0 != RTPParser(dp)) {
                                continue;
                            }

                            if (SIPController.sipSound != null && SIPController.sipSound.flowIndicator == SIPStack.SIP_MEDIAFLOW_SENDONLY) {
                                SIPController.sipSound.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
                            }

                            rtpCore.rtpArrivalTime = new Date();
                            //Log.i("AR",dp.getLength()+" bytes");
                        } catch (SocketException se) {
                            SIPStack.exceptionCountAtCurrentCall++;
                            //break;
                        } catch (Exception e) {
                            SIPStack.exceptionCountAtCurrentCall++;
                            //break;
                        }
                    } //while

                    Log.i(TAG, "RTP RECV Thread terminated.");

                    if (SIPStack.SIP_CALLHANDLE_DEBUG)
                        Log.i(TAG, "RTP RECV Thread terminated.");

                    if (runningSocket != null) {
                        if (runningSocket == theSocket) theSocket = null;
                        runningSocket.close();
                        runningSocket = null;
                    }
                    rtpCore.running = false;
                    receiveThread = null;
                }
            };

            receiveThread = new Thread(runner);
            //receiveThread.setPriority(10);
            receiveThread.start();
        } catch (Exception e) {
            receiveThread = null;
            rtpCore.running = false;
            System.err.println("Exception: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }
    }

    public void startSendAudioThread() {
        //if(sendThread!=null) return;
		/*
		try
		{
			if(sendThread!=null) sendThread.interrupt();
		}catch(Exception e){}
		*/

        try {
            Runnable runner = new Runnable() {

                public void run() {
                    rtpCore.running = true;

                    while (rtpCore.running) {
                        if (sendThread == null) break;
                        if (sendThread.isInterrupted()) break;
                        try {
                            if (SIPController.sipSound == null) break;
                            if (SIPSound.bActive == false) break;

                            boolean bValid = false;
                            int encpacketsize = 0;

                            try {
                                encpacketsize = SIPSound.BULK_SIZE;
                                bValid = SIPController.sipSound.getBulkdata(rtpCore.rtpPacketBuffer, encpacketsize, 12);
                            } catch (Exception e) {
                                System.err.println("I/O problems: " + e);
                                SIPStack.exceptionCountAtCurrentCall++;
                                //break;
                                bValid = false;
                            }

                            try {
                                if (bValid) {
                                    if (rtpCore.remoteMediaIp != null && rtpCore.remoteMediaIp.length() > 0 && rtpCore.remoteMediaPort > 0) {
                                        //Log.i("AS",encpacketsize+" bytes");
                                        rtpWriteEnc(encpacketsize, rtpCore.remotePayloadType, rtpCore.remoteMediaIp, rtpCore.remoteMediaPort);
                                    }
                                }
                            } catch (Exception e) {
                                //System.err.println("I/O problems: " + e);
                                SIPStack.exceptionCountAtCurrentCall++;
                            }
                            Thread.sleep(SIPSound.PTIME);
                            //System.out.println("PTIME:"+SIPSound.PTIME);
                        } catch (Exception e) {
                            SIPStack.exceptionCountAtCurrentCall++;
                            //break;
                        }
                    }   //while
                    Log.i(TAG, "RTP SEND Thread terminated.");
                    sendThread = null;
                }
            };

            sendThread = new Thread(runner);
            //sendThread.setPriority(10);
            sendThread.start();
        } catch (Exception e) {
            sendThread = null;
            System.err.println("Exception: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }
    }

    //
    public int RTPParser(DatagramPacket dp) {

        if (SIPController.sipSound != null && SIPController.sipSound.bActive) {
            if (rtpCore.parseRTPHeader() == false) return 0;

            if (rtpCore.PARSEpayload == SIPStack.SIP_CODEC_G711U) {
                if (SIPController.sipSound.playStarted) {
                    rtpCore.packetSize = dp.getLength() - 12;
                    if (SIPG711.decodeULawExt(rtpCore.buffer, 12, rtpCore.packetSize, rtpCore.pcmLinearBuffer)) {
                        SIPController.sipSound.playAudio(rtpCore.pcmLinearBuffer, rtpCore.packetSize * 2);
                    }
                }
            } else if (rtpCore.PARSEpayload == SIPStack.SIP_CODEC_G711A) {
                if (SIPController.sipSound.playStarted) {
                    rtpCore.packetSize = dp.getLength() - 12;
                    if (SIPG711.decodeALawExt(rtpCore.buffer, 12, rtpCore.packetSize, rtpCore.pcmLinearBuffer)) {
                        SIPController.sipSound.playAudio(rtpCore.pcmLinearBuffer, rtpCore.packetSize * 2);
                    }
                }
            } else if (rtpCore.PARSEpayload == RFC2833.payloadType) {
                if (rtpCore.parseRFC2833() == false) return 0;
                if (rtpCore.bDtmfDetected && rtpCore.detectedDtmf == rtpCore.PARSERFCdtmf && rtpCore.PARSERFCedge == 1) {
                    //if(parent!=null) parent.notifyDtmf(rtpCore.detectedDtmf);
                    //Log.i("RTP","DTMF DETECTED : event"+dtmf+" edge:"+edge+" volume:"+volume+" duration:"+duration);
                    rtpCore.detectedDtmf = 0;
                    rtpCore.bDtmfDetected = false;
                } else if (rtpCore.PARSERFCedge != 1 && rtpCore.bDtmfDetected == false) {
                    rtpCore.bDtmfDetected = true;
                    rtpCore.detectedDtmf = rtpCore.PARSERFCdtmf;
                }
            }
        }
        return 0;
    }

    public void rtpWrite(short[] data, int datasize, int codec, String ip, int port) {
        int packetsize = 0;
        boolean bSend = false;
        if (codec == SIPStack.SIP_CODEC_G711U) {
            packetsize = SIPG711.encode2ULaw(data, datasize, rtpCore.rtpPacketBuffer, 12);
        } else if (codec == SIPStack.SIP_CODEC_G711A) {
            packetsize = SIPG711.encode2ALaw(data, datasize, rtpCore.rtpPacketBuffer, 12);
            return;
        }

        if (rtpCore.rtpPacketBuffer != null && packetsize > 0) {
            bSend = rtpCore.encodeRtpHeader(codec);
        }

        if (bSend) {
            rtpCore.RTPsequence++;
            rtpCore.RTPtimestamp += 160;
            SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, packetsize);
        }
        return;
    }

    public void rtpWriteExt(byte[] data, int datasize, int codec, String ip, int port) {
        int packetsize = 0;
        boolean bSend = false;
        //DTMF PROCESSING
        if (rfc2833.bActive) {
            byte[] rfcdata = rfc2833.constructDtmfPacket(160);
            if (rfcdata != null && rfcdata.length == 4) {
                rtpCore.rtpPacketBuffer[12] = rfcdata[0];
                rtpCore.rtpPacketBuffer[13] = rfcdata[1];
                rtpCore.rtpPacketBuffer[14] = rfcdata[2];
                rtpCore.rtpPacketBuffer[15] = rfcdata[3];

                if (rfc2833.bEnd) rtpCore.RTPmark = 1;
                else rtpCore.RTPmark = 0;

                bSend = rtpCore.encodeRtpHeader(RFC2833.payloadType);

                if (rfc2833.bStart) {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                } else if (rfc2833.bEnd) {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                    rtpCore.RTPtimestamp += rfc2833.exceedDuration;
                    rfc2833.resetDtmf();
                } else {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                }
            }
            return;
        }

        try {
            if (codec == SIPStack.SIP_CODEC_G711U) {
                packetsize = SIPG711.encode2ULawExt(data, datasize, rtpCore.rtpPacketBuffer, 12);
            } else if (codec == SIPStack.SIP_CODEC_G711A) {
                packetsize = SIPG711.encode2ALawExt(data, datasize, rtpCore.rtpPacketBuffer, 12);
            } else {
                return;
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }

        try {
            if (rtpCore.rtpPacketBuffer != null && packetsize > 0) {
                bSend = rtpCore.encodeRtpHeader(codec);
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }

        try {
            if (bSend && ip != null && ip.length() > 0 && port > 0) {
                rtpCore.RTPsequence++;
                rtpCore.RTPtimestamp += 160;
                SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, packetsize);
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }
        return;
    }

    public void rtpWriteEnc(byte[] data, int datasize, int codec, String ip, int port) {
        int packetsize = 0;
        boolean bSend = false;
        //DTMF PROCESSING
        if (rfc2833.bActive) {
            byte[] rfcdata = rfc2833.constructDtmfPacket(160);
            if (rfcdata != null && rfcdata.length == 4) {
                rtpCore.rtpPacketBuffer[12] = rfcdata[0];
                rtpCore.rtpPacketBuffer[13] = rfcdata[1];
                rtpCore.rtpPacketBuffer[14] = rfcdata[2];
                rtpCore.rtpPacketBuffer[15] = rfcdata[3];

                if (rfc2833.bEnd) rtpCore.RTPmark = 1;
                else rtpCore.RTPmark = 0;

                bSend = rtpCore.encodeRtpHeader(RFC2833.payloadType);

                if (rfc2833.bStart) {
                    if (bSend = true) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                } else if (rfc2833.bEnd) {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                    rtpCore.RTPtimestamp += rfc2833.exceedDuration;
                    rfc2833.resetDtmf();
                } else {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                }
            }
            return;
        }

        try {
            System.arraycopy(data, 0, rtpCore.rtpPacketBuffer, 12, datasize);
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }

        try {
            if (rtpCore.rtpPacketBuffer != null && packetsize > 0) {
                bSend = rtpCore.encodeRtpHeader(codec);
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }

        try {
            if (bSend && ip != null && ip.length() > 0 && port > 0) {
                rtpCore.RTPsequence++;
                rtpCore.RTPtimestamp += 160;
                SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, packetsize);
            }

        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }
        return;
    }

    public void rtpWriteEnc(int datasize, int codec, String ip, int port) {
        int packetsize = 0;
        boolean bSend = false;
        //DTMF PROCESSING
        if (rfc2833.bActive) {
            byte[] rfcdata = rfc2833.constructDtmfPacket(160);

            if (rfcdata != null && rfcdata.length == 4) {
                rtpCore.rtpPacketBuffer[12] = rfcdata[0];
                rtpCore.rtpPacketBuffer[13] = rfcdata[1];
                rtpCore.rtpPacketBuffer[14] = rfcdata[2];
                rtpCore.rtpPacketBuffer[15] = rfcdata[3];

                if (rfc2833.bEnd) rtpCore.RTPmark = 1;
                else rtpCore.RTPmark = 0;

                bSend = rtpCore.encodeRtpHeader(RFC2833.payloadType);

                if (rfc2833.bStart) {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                } else if (rfc2833.bEnd) {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                    rtpCore.RTPtimestamp += rfc2833.exceedDuration;
                    rfc2833.resetDtmf();
                } else {
                    if (bSend) {
                        rtpCore.RTPsequence++;
                        SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, 16);
                    }
                }
            }
            return;
        }

        try {
            packetsize = datasize + 12;
            if (rtpCore.rtpPacketBuffer != null && packetsize > 0) {
                bSend = rtpCore.encodeRtpHeader(SIPStack.SIP_CODEC_G711U);
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }

        try {
            if (bSend && ip != null && ip.length() > 0 && port > 0) {
                rtpCore.RTPsequence++;
                rtpCore.RTPtimestamp += 160;
                SendRTPPacket(ip, port, rtpCore.rtpPacketBuffer, packetsize);
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }
        return;
    }

    public void rtpWriteBulk(byte[] data, int datasize) {
        int packetsize = 0;
        boolean bSend = false;

        try {
            packetsize = datasize + 12;
            if (rtpCore.rtpBulkBuffer != null && packetsize > 0) {
                bSend = rtpCore.encodeRtpHeader(rtpCore.remotePayloadType);
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }

        try {
            if (bSend && rtpCore.remoteMediaIp != null && rtpCore.remoteMediaIp.length() > 0 && rtpCore.remoteMediaPort > 0) {
                rtpCore.RTPsequence++;
                rtpCore.RTPtimestamp += datasize;
                int sent = SendRTPPacket(rtpCore.remoteMediaIp, rtpCore.remoteMediaPort, rtpCore.rtpBulkBuffer, packetsize);
            }
        } catch (Exception e) {
            System.err.println("I/O problems: " + e);
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }
        return;
    }

    public int getBytesToInt(byte[] bytes) {
        int newValue = 0;
        newValue |= (((int) bytes[0]) << 24) & 0xFF000000;
        newValue |= (((int) bytes[1]) << 16) & 0xFF0000;
        newValue |= (((int) bytes[2]) << 8) & 0xFF00;
        newValue |= (((int) bytes[3])) & 0xFF;
        return newValue;
    }

    public byte[] getIntToBytes(int iValue) {
        byte[] newbytes = new byte[4];
        newbytes[0] = (byte) (iValue >> 24);
        newbytes[1] = (byte) ((iValue << 8) >> 24);
        newbytes[2] = (byte) ((iValue << 16) >> 24);
        newbytes[3] = (byte) ((iValue << 24) >> 24);
        return newbytes;
    }

    public int SendRTPPacket(String sIp, int iPort, byte[] data, int dataSize) {
        int sent = 0;
        if (sIp == null || sIp.length() <= 0) return 0;
        if (data == null || dataSize <= 0) return 0;
        if (iPort <= 0) return 0;
        if (theSocket == null || rtpCore.running == false) return 0;

        try {
            InetAddress ia = InetAddress.getByName(sIp);
            if (ia != null) {
                DatagramPacket dp = new DatagramPacket(data, dataSize, ia, iPort);
                if (dp != null) {
                    theSocket.send(dp);
                }
            }
            sent = dataSize;
        } catch (UnknownHostException uhe) {
            System.err.println(uhe);
            SIPStack.exceptionCountAtCurrentCall++;
        } catch (IOException ie) {
            System.err.println(ie);
            SIPStack.exceptionCountAtCurrentCall++;
        }
        return sent;
    }

    public boolean RTPEnd() {
        Log.w(TAG, "[RTPEnd] ========== START ==========");
        if (bDisableVoice) {
            Log.e(TAG, "[RTPEnd] bDisableVoice [" + bDisableVoice + "]");
            bDisableVoice = false;
        }

        if (SIPController.sipSound != null)
            SIPController.sipSound.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
        try {
            if (SIPController.sipSound != null) SIPController.sipSound.closeAudioDevice();
            if (rtpCore.bActive == false) return false;

            rtpCore.bActive = false;

            if (RTPSENDTimer != null) {
                RTPSENDTimer.cancel();
                RTPSENDTimer = null;
            }

            if (this.receiveThread != null) {
                receiveThread.interrupt();
                rtpCore.running = false;
                receiveThread = null;
            }

            if (theSocket != null) {
                theSocket.close();
                theSocket = null;
            }

            if (SIPController.sipSound != null) SIPController.sipSound.closeAudioDevice();

        } catch (Exception e) {
            SIPStack.exceptionCountAtCurrentCall++;
        }
        SIPStack.freeAudioRtpPort(rtpCore.RTP_PORT);
        return true;
    }

    public void RTPInit(int port) {
        Log.w(TAG, "[RTPInit] ========== START ========== port [" + port + "]");
        if (bDisableVoice) {
            Log.e(TAG, "[RTPInit] bDisableVoice [" + bDisableVoice + "]");
            return;
        }

        if (rtpCore == null) {
            Log.i(TAG, "[RTPInit] RTPInit failed. rtpCore is null.");
            return;
        } else rtpCore.init();

        if (SIPController.sipSound != null)
            SIPController.sipSound.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;

        if (SIPController.sipSound == null) {
            SIPController.initSound();
        }

        if (SIPController.sipSound == null) return;

        try {
            if (SIPController.sipSound.playStarted == false) {
                SIPController.sipSound.prepareAudioTrack();
            }

            if (SIPController.sipSound.recorderStarted == false) {
                SIPController.sipSound.captureAudio();
            } else {
                SIPController.sipSound.closeCaptureDevice();
                SIPController.sipSound.captureAudio();
            }
        } catch (Exception e) {
            SIPStack.exceptionCountAtCurrentCall++;
            return;
        }

        if (rtpCore.running == false) {
            rtpCore.setRTPPort(port);
            this.receiveAudio();
        }

        rtpCore.bActive = true;

        if (SIPStack.bUseSendTimer) {
            if (RTPSENDTimer != null) RTPSENDTimer.cancel();
            RTPSENDTimer = new Timer();
            RTPSENDTimer.scheduleAtFixedRate(new BULKSENDTimerTask(), 0, SIPController.sipSound.PTIME);
        } else {
            this.startSendAudioThread();
        }
        return;
    }

    public void RTPLoopSet(boolean bSet) {
        rtpCore.bRTPparsing = false;
        rtpCore.bRTPlooping = bSet;
        return;
    }

    public void RTPParseSet(boolean bSet) {
        rtpCore.bRTPlooping = false;
        rtpCore.bRTPparsing = bSet;
        return;
    }

    public boolean invokeRFC2833(int digit) {
        if (rfc2833 == null) return false;
        if (digit < 0 || digit > 11) return false;
        rfc2833.setDtmf(digit, 4, 0, 960);
        return true;
    }

    public void setRemoteMediaInfo(int payloadtype, String mediaIp, int mediaPort) {
        rtpCore.setRemoteMediaInfo(payloadtype, mediaIp, mediaPort);
        if (rtpCore.mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
            SIPSound.remotePayloadType = rtpCore.remotePayloadType;
        }
        return;
    }

    public int getkRtpArrivalMilliseconds() {
        // milli seconds
        Date currentTime = new Date();
        return (int) (currentTime.getTime() - rtpCore.rtpArrivalTime.getTime());
    }

    public int getkRtpArrivalSeconds() {
        // milli seconds
        Date currentTime = new Date();
        return (int) (currentTime.getTime() - rtpCore.rtpArrivalTime.getTime()) / 1000;
    }

    public String getVideomediadescription() {
        return rtpCore.getVideomediadescription();
    }

    class SENDTimerTask extends TimerTask {

        public void run() {
            if (RTPSENDTimer == null || rtpCore.bActive == false) return;
            if (SIPController.sipSound == null) return;
            if (SIPController.sipSound.bActive == false) return;
            boolean bValid = false;
            int encpacketsize = 0;
            try {
                if (rtpCore.remotePayloadType == SIPStack.SIP_CODEC_G711U) {
                    encpacketsize = 160;
                } else if (rtpCore.remotePayloadType == SIPStack.SIP_CODEC_G711A) {
                    encpacketsize = 160;
                }
                bValid = SIPController.sipSound.getEncodeddata(rtpCore.rtpPacketBuffer, encpacketsize, 12);
            } catch (Exception e) {
                System.err.println("I/O problems: " + e);
                SIPStack.exceptionCountAtCurrentCall++;
                return;
            }

            try {
                if (bValid) {
                    if (rtpCore.remoteMediaIp != null && rtpCore.remoteMediaIp.length() > 0 && rtpCore.remoteMediaPort > 0) {
                        rtpWriteEnc(encpacketsize, rtpCore.remotePayloadType, rtpCore.remoteMediaIp, rtpCore.remoteMediaPort);
                    }
                }
            } catch (Exception e) {
                System.err.println("I/O problems: " + e);
                SIPStack.exceptionCountAtCurrentCall++;
            }
        }
    }

    class BULKSENDTimerTask extends TimerTask {

        public void run() {
            if (RTPSENDTimer == null || rtpCore.bActive == false) return;
            if (SIPController.sipSound == null) return;
            if (SIPController.sipSound.bActive == false) return;
            boolean bValid = false;

            int encpacketsize = 0;

            try {
                encpacketsize = SIPSound.BULK_SIZE;
                bValid = SIPController.sipSound.getBulkdata(rtpCore.rtpPacketBuffer, encpacketsize, 12);
            } catch (Exception e) {
                System.err.println("I/O problems: " + e);
                SIPStack.exceptionCountAtCurrentCall++;
                return;
            }

            try {
                if (bValid) {
                    if (rtpCore.remoteMediaIp != null && rtpCore.remoteMediaIp.length() > 0 && rtpCore.remoteMediaPort > 0) {
                        rtpWriteEnc(encpacketsize, rtpCore.remotePayloadType, rtpCore.remoteMediaIp, rtpCore.remoteMediaPort);
                    }
                }
            } catch (Exception e) {
                System.err.println("I/O problems: " + e);
                SIPStack.exceptionCountAtCurrentCall++;
            }
        }
    }
}//class RTPManager