src/jlibrtp/RTCPSession.java
author nikita@nikita-rack
Tue, 07 Apr 2009 20:12:30 +0200
changeset 82 ff92a9c95c78
parent 13 e684f11070d5
permissions -rw-r--r--
merge avec beem-ui
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     1
/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     2
 * Java RTP Library (jlibrtp)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     3
 * Copyright (C) 2006 Arne Kepp
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     4
 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     5
 * This library is free software; you can redistribute it and/or
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     6
 * modify it under the terms of the GNU Lesser General Public
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     7
 * License as published by the Free Software Foundation; either
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     8
 * version 2.1 of the License, or (at your option) any later version.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
     9
 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    10
 * This library is distributed in the hope that it will be useful,
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    13
 * Lesser General Public License for more details.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    14
 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    15
 * You should have received a copy of the GNU Lesser General Public
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    16
 * License along with this library; if not, write to the Free Software
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    18
 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    19
package jlibrtp;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    20
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    21
import java.util.Enumeration;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    22
import java.net.DatagramSocket;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    23
import java.net.InetAddress;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    24
import java.net.MulticastSocket;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    25
import java.util.LinkedList;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    26
import java.util.Hashtable;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    27
import java.util.ListIterator;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    28
import java.util.Arrays;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    29
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    30
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    31
/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    32
 * This class acts as an organizer for most of the information
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    33
 * and functions pertaining to RTCP packet generation and reception 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    34
 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    35
 * @author Arne Kepp
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    36
 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    37
 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    38
public class RTCPSession {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    39
	/** Parent session */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    40
	protected RTPSession rtpSession = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    41
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    42
	/** Unicast socket */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    43
	protected DatagramSocket rtcpSock = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    44
	/** Multicast socket */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    45
	protected MulticastSocket rtcpMCSock = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    46
	/** Multicast group */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    47
	protected InetAddress mcGroup = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    48
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    49
	/** RTCP Receiver thread */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    50
	protected RTCPReceiverThread recvThrd = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    51
	/** RTCP Sender thread */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    52
	protected RTCPSenderThread senderThrd = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    53
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    54
	/** Previous time a delay was calculated */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    55
	protected long prevTime = System.currentTimeMillis();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    56
	/** Delay between RTCP transmissions, in ms. Initialized in start() */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    57
	protected int nextDelay = -1; //
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    58
	/** The average compound RTCP packet size, in octets, including UDP and IP headers */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    59
	protected int avgPktSize = 200; //
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    60
	/** Pessimistic case estimate of the current number of senders */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    61
	protected int senderCount = 1;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    62
	/** Whether next RTCP packet can be sent early */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    63
	protected boolean fbAllowEarly = false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    64
	/** Feedback queue , index is SSRC of target */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    65
	protected Hashtable<Long, LinkedList<RtcpPkt>> fbQueue = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    66
	/** APP queue , index is SSRC of target */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    67
	protected Hashtable<Long, LinkedList<RtcpPktAPP>> appQueue = null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    68
	/** Are we just starting up? */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    69
	protected boolean initial = true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    70
	/** Is there a feedback packet waiting? SSRC of destination */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    71
	protected long fbWaiting = -1;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    72
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    73
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    74
	 * Constructor for unicast sessions
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    75
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    76
	 * @param parent RTPSession that started this
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    77
	 * @param rtcpSocket the socket to use for listening and sending
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    78
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    79
	protected RTCPSession(RTPSession parent, DatagramSocket rtcpSocket) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    80
		this.rtcpSock = rtcpSocket;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    81
		rtpSession = parent;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    82
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    83
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    84
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    85
	 * Constructor for multicast sessions
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    86
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    87
	 * @param parent parent RTPSession
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    88
	 * @param rtcpSocket parent RTPSession that started this
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    89
	 * @param multicastGroup multicast group to bind the socket to
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    90
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    91
	protected RTCPSession(RTPSession parent, MulticastSocket rtcpSocket, InetAddress multicastGroup) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    92
		mcGroup = multicastGroup;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    93
		this.rtcpSock = rtcpSocket;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    94
		rtpSession = parent;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    95
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    96
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    97
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    98
	 * Starts the session, calculates delays and fires up the threads.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
    99
	 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   100
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   101
	protected void start() {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   102
		//nextDelay = 2500 + rtpSession.random.nextInt(1000) - 500;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   103
		this.calculateDelay();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   104
		recvThrd = new RTCPReceiverThread(this, this.rtpSession);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   105
		senderThrd = new RTCPSenderThread(this, this.rtpSession);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   106
		recvThrd.start();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   107
		senderThrd.start();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   108
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   109
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   110
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   111
	 * Send bye packets, handled by RTCP Sender thread
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   112
	 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   113
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   114
	protected void sendByes() {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   115
		senderThrd.sendByes();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   116
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   117
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   118
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   119
	 * Calculate the delay before the next RTCP packet can be sent
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   120
	 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   121
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   122
	protected void calculateDelay() {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   123
		switch(rtpSession.rtcpMode) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   124
		case 0: calculateRegularDelay(); break;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   125
		default:
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   126
			System.out.println("RTCPSession.calculateDelay() unknown .mode");
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   127
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   128
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   129
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   130
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   131
	 * Calculates a delay value in accordance with RFC 3550
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   132
	 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   133
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   134
	protected void calculateRegularDelay() {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   135
		long curTime = System.currentTimeMillis();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   136
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   137
		if(rtpSession.bandwidth != 0 && ! this.initial && rtpSession.partDb.ssrcTable.size() > 4) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   138
			// RTPs mechanisms for RTCP scalability
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   139
			int rand = rtpSession.random.nextInt(10000) - 5000; //between -500 and +500
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   140
			double randDouble =  ((double) 1000 + rand)/1000.0;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   141
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   142
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   143
			Enumeration<Participant> enu = rtpSession.partDb.getParticipants();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   144
			while(enu.hasMoreElements()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   145
				Participant part = enu.nextElement();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   146
				if(part.lastRtpPkt > this.prevTime)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   147
					senderCount++;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   148
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   149
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   150
			double bw;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   151
			if(rtpSession.rtcpBandwidth > -1) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   152
				bw = rtpSession.rtcpBandwidth;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   153
			}else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   154
				bw = rtpSession.bandwidth*0.05;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   155
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   156
			if(senderCount*2 > rtpSession.partDb.ssrcTable.size()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   157
				if(rtpSession.lastTimestamp > this.prevTime) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   158
					//We're a sender
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   159
					double numerator = ((double) this.avgPktSize)*((double) senderCount);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   160
					double denominator = 0.25*bw;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   161
					this.nextDelay = (int) Math.round((numerator/denominator)*randDouble);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   162
				} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   163
					//We're a receiver
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   164
					double numerator = ((double) this.avgPktSize)*((double) rtpSession.partDb.ssrcTable.size());
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   165
					double denominator = 0.75*bw;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   166
					this.nextDelay = (int) Math.round((numerator/denominator)*randDouble);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   167
				}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   168
			} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   169
				double numerator = ((double) this.avgPktSize)*((double) rtpSession.partDb.ssrcTable.size());;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   170
				double denominator = bw;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   171
				this.nextDelay = (int) Math.round(1000.0*(numerator/denominator)) * (1000 + rand);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   172
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   173
		} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   174
			// Not enough data to scale, use random values
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   175
			int rand = rtpSession.random.nextInt(1000) - 500; //between -500 and +500
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   176
			if(this.initial) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   177
				// 2.5 to 3.5 seconds, randomly
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   178
				this.nextDelay = 3000 + rand;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   179
				this.initial = false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   180
			} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   181
				// 4.5 to 5.5 seconds, randomly
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   182
				this.nextDelay = 5500 + rand;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   183
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   184
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   185
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   186
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   187
		// preflight check
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   188
		if(this.nextDelay < 1000) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   189
			int rand = rtpSession.random.nextInt(1000) - 500; //between -500 and +500
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   190
			System.out.println("RTCPSession.calculateDelay() nextDelay was too short (" 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   191
					+this.nextDelay+"ms), setting to "+(this.nextDelay = 2000 + rand));
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   192
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   193
		this.prevTime = curTime;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   194
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   195
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   196
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   197
	 * Update the average packet size
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   198
	 * @param length of latest packet
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   199
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   200
	synchronized protected void updateAvgPacket(int length) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   201
		double tempAvg = (double) this.avgPktSize;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   202
		tempAvg = (15*tempAvg + ((double) length))/16;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   203
		this.avgPktSize = (int) tempAvg;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   204
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   205
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   206
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   207
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   208
	 * Adds an RTCP APP (application) packet to the queue
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   209
	 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   210
	 * @param targetSsrc the SSRC of the recipient
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   211
	 * @param aPkt 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   212
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   213
	synchronized protected void addToAppQueue(long targetSsrc, RtcpPktAPP aPkt) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   214
		aPkt.time = System.currentTimeMillis();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   215
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   216
		if(this.appQueue == null)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   217
			this.appQueue = new Hashtable<Long, LinkedList<RtcpPktAPP>>();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   218
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   219
		LinkedList<RtcpPktAPP> ll = this.appQueue.get(targetSsrc);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   220
		if(ll == null) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   221
			// No list, create and add
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   222
			ll = new LinkedList<RtcpPktAPP>();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   223
			this.appQueue.put(targetSsrc, ll);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   224
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   225
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   226
		ll.add(aPkt);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   227
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   228
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   229
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   230
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   231
	 * Adds an RTCP APP (application) packet to the queue
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   232
	 *
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   233
	 * @param targetSsrc the SSRC of the recipient
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   234
	 * @return array of RTCP Application packets 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   235
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   236
	synchronized protected RtcpPktAPP[] getFromAppQueue(long targetSsrc) {		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   237
		if(this.appQueue == null)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   238
			return null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   239
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   240
		LinkedList<RtcpPktAPP> ll = this.appQueue.get(targetSsrc);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   241
		if(ll == null || ll.isEmpty()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   242
			return null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   243
		} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   244
			RtcpPktAPP[] ret = new RtcpPktAPP[ll.size()];
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   245
			ListIterator<RtcpPktAPP> li = ll.listIterator();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   246
			int i = 0;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   247
			while(li.hasNext()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   248
				ret[i] = li.next();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   249
				i++;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   250
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   251
			return ret;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   252
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   253
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   254
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   255
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   256
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   257
	 * Cleans the TCP APP (application) packet queues of any packets that are
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   258
	 * too old, defined as 60 seconds since insertion.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   259
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   260
	 * @param ssrc The SSRC of the user who has left, negative value -> general cleanup
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   261
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   262
	synchronized protected void cleanAppQueue(long ssrc) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   263
		if(this.appQueue == null)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   264
			return;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   265
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   266
		if(ssrc > 0) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   267
			this.appQueue.remove(ssrc);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   268
		} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   269
			Enumeration<LinkedList<RtcpPktAPP>> enu = this.appQueue.elements();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   270
			long curTime = System.currentTimeMillis();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   271
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   272
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   273
			while(enu.hasMoreElements()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   274
				ListIterator<RtcpPktAPP> li = enu.nextElement().listIterator();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   275
				while(li.hasNext()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   276
					RtcpPkt aPkt = li.next();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   277
					//Remove after 60 seconds
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   278
					if(curTime - aPkt.time > 60000) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   279
						li.remove();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   280
					}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   281
				}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   282
			}	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   283
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   284
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   285
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   286
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   287
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   288
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   289
	 * Check the feedback queue for similar packets and adds
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   290
	 * the new packet if it is not redundant
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   291
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   292
	 * @param aPkt
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   293
	 * @return 0 if the packet was added, 1 if it was dropped
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   294
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   295
	synchronized protected int addToFbQueue(long targetSsrc, RtcpPkt aPkt) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   296
		if(this.fbQueue == null)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   297
			this.fbQueue = new Hashtable<Long, LinkedList<RtcpPkt>>();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   298
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   299
		LinkedList<RtcpPkt> ll = this.fbQueue.get(targetSsrc);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   300
		if(ll == null) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   301
			// No list, create and add
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   302
			ll = new LinkedList<RtcpPkt>();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   303
			ll.add(aPkt);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   304
			this.fbQueue.put(targetSsrc, ll);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   305
		} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   306
			// Check for matching packets, else add to end
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   307
			ListIterator<RtcpPkt> li = ll.listIterator();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   308
			while(li.hasNext()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   309
				RtcpPkt tmp = li.next();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   310
				if(equivalent(tmp, aPkt))
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   311
					return -1;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   312
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   313
			ll.addLast(aPkt);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   314
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   315
		return 0;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   316
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   317
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   318
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   319
	 * Checks whether there are ny feedback packets waiting
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   320
	 * to be sent.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   321
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   322
	 * @param ssrc of the participant we are notifying
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   323
	 * @return all relevant feedback packets, or null
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   324
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   325
	synchronized protected RtcpPkt[] getFromFbQueue(long ssrc) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   326
		if(this.fbQueue == null)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   327
			return null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   328
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   329
		LinkedList<RtcpPkt> ll = this.fbQueue.get(ssrc);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   330
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   331
		if(ll == null)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   332
			return null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   333
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   334
		ListIterator<RtcpPkt> li = ll.listIterator();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   335
		if(li.hasNext()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   336
			long curTime = System.currentTimeMillis();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   337
			long maxDelay = curTime - rtpSession.fbMaxDelay;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   338
			long keepDelay =  curTime - 2000;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   339
			int count = 0;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   340
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   341
			//TODO below the indeces should be collected instead of looping twice
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   342
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   343
			// Clean out what we dont want and count what we want
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   344
			while(li.hasNext()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   345
				RtcpPkt aPkt = li.next();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   346
				if(aPkt.received) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   347
					//This is a packet received, we keep these for
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   348
					// 2000ms to avoid redundant feedback
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   349
					if(aPkt.time < keepDelay)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   350
						li.remove();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   351
				} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   352
					//This is a packet we havent sent yet
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   353
					if(aPkt.time < maxDelay) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   354
						li.remove();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   355
					} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   356
						count++;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   357
					}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   358
				}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   359
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   360
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   361
			// Gather what we want to return
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   362
			if(count != 0) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   363
				li = ll.listIterator();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   364
				RtcpPkt[] ret = new RtcpPkt[count];
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   365
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   366
				while(count > 0) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   367
					RtcpPkt aPkt = li.next();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   368
					if(! aPkt.received) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   369
						ret[ret.length - count] = aPkt; 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   370
						count--;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   371
					}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   372
				}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   373
				return ret;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   374
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   375
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   376
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   377
		return null;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   378
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   379
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   380
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   381
	 * Cleans the feeback queue of any packets that have expired,
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   382
	 * ie feedback packet that are no longer relevant.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   383
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   384
	 * @param ssrc The SSRC of the user who has left, negative value -> general cleanup
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   385
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   386
	synchronized protected void cleanFbQueue(long ssrc) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   387
		if(this.fbQueue == null)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   388
			return;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   389
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   390
		if(ssrc > 0) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   391
			this.fbQueue.remove(ssrc);
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   392
		} else { 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   393
			Enumeration<LinkedList<RtcpPkt>> enu = this.fbQueue.elements();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   394
			long curTime = System.currentTimeMillis();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   395
			long maxDelay = curTime - rtpSession.fbMaxDelay;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   396
			long keepDelay =  curTime - 2000;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   397
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   398
			while(enu.hasMoreElements()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   399
				ListIterator<RtcpPkt> li = enu.nextElement().listIterator();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   400
				while(li.hasNext()) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   401
					RtcpPkt aPkt = li.next();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   402
					if(aPkt.received) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   403
						//This is a packet received, we keep these for
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   404
						// 2000ms to avoid redundant feedback
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   405
						if(aPkt.time < keepDelay)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   406
							li.remove();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   407
					} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   408
						//This is a packet we havent sent yet
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   409
						if(aPkt.time < maxDelay)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   410
							li.remove();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   411
					}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   412
				}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   413
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   414
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   415
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   416
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   417
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   418
	 * Check whether the conditions are satisfied to send a feedbkac packet immediately.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   419
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   420
	 * @return true if they are, false otherwise
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   421
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   422
	protected boolean fbSendImmediately() {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   423
		if(rtpSession.partDb.ssrcTable.size() > this.rtpSession.fbEarlyThreshold 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   424
				&& rtpSession.partDb.receivers.size() > this.rtpSession.fbEarlyThreshold)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   425
			return false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   426
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   427
		return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   428
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   429
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   430
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   431
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   432
	 * Check whether the conditions are satisfied to send a feedbkac packet immediately.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   433
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   434
	 * @return true if they are, false otherwise
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   435
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   436
	protected boolean fbSendEarly() {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   437
		if(rtpSession.partDb.ssrcTable.size() > this.rtpSession.fbRegularThreshold 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   438
				&& rtpSession.partDb.receivers.size() > this.rtpSession.fbRegularThreshold)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   439
			return false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   440
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   441
		return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   442
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   443
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   444
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   445
	 * Wake the sender thread because of this ssrc
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   446
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   447
	 * @param ssrc that has feedback waiting.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   448
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   449
	protected void wakeSenderThread(long ssrc) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   450
		this.fbWaiting = ssrc;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   451
		this.senderThrd.interrupt();
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   452
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   453
		// Give it a chance to catch up
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   454
		try { Thread.sleep(0,1); } catch (Exception e){ };
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   455
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   456
	
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   457
	/**
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   458
	 * Compares two packets to check whether they are equivalent feedback messages,
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   459
	 * to avoid sending the same feedback to a host twice.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   460
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   461
	 * Expect false negatives, but not false positives.
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   462
	 * 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   463
	 * @param one packet
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   464
	 * @param two packet
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   465
	 * @return true if they are equivalent, false otherwise 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   466
	 */
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   467
	private boolean equivalent(RtcpPkt one, RtcpPkt two) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   468
		// Cheap checks
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   469
		if(one.packetType != two.packetType)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   470
			return false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   471
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   472
		if(one.itemCount != two.itemCount)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   473
			return false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   474
		
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   475
		if(one.packetType == 205) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   476
			// RTP Feedback, i.e. a NACK
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   477
			RtcpPktRTPFB pktone = (RtcpPktRTPFB) one;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   478
			RtcpPktRTPFB pkttwo = (RtcpPktRTPFB) two;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   479
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   480
			if(pktone.ssrcMediaSource != pkttwo.ssrcMediaSource)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   481
				return false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   482
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   483
			if(Arrays.equals(pktone.BLP,pkttwo.BLP) 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   484
					&& Arrays.equals(pktone.BLP,pkttwo.BLP))
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   485
				return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   486
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   487
			return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   488
		} else if(one.packetType == 206) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   489
			RtcpPktPSFB pktone = (RtcpPktPSFB) one;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   490
			RtcpPktPSFB pkttwo = (RtcpPktPSFB) two;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   491
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   492
			if(pktone.ssrcMediaSource != pkttwo.ssrcMediaSource)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   493
				return false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   494
			
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   495
			switch(one.itemCount) {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   496
			case 1: // Picture Loss Indication 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   497
				return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   498
				
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   499
			case 2: // Slice Loss Indication
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   500
				// This will not work if the slice loss indicators are in different order
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   501
				if(pktone.sliFirst.length == pkttwo.sliFirst.length
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   502
						&& Arrays.equals(pktone.sliFirst, pkttwo.sliFirst) 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   503
						&& Arrays.equals(pktone.sliNumber, pkttwo.sliNumber)
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   504
						&& Arrays.equals(pktone.sliPictureId, pkttwo.sliPictureId))
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   505
					return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   506
				break;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   507
			case 3: // Reference Picture Selection Indication 
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   508
				if(Arrays.equals(pktone.rpsiBitString, pkttwo.rpsiBitString))
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   509
					return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   510
				break;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   511
			case 15: // Application Layer Feedback Messages
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   512
				// This will not work if the padding scheme is different
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   513
				if(pktone.sliFirst.length == pkttwo.sliFirst.length
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   514
						&& Arrays.equals(pktone.alfBitString, pkttwo.alfBitString))
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   515
					return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   516
				break;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   517
			default:
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   518
				
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   519
			}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   520
			return true;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   521
		} else {
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   522
			System.out.println("!!!! RTCPSession.equivalentPackets() encountered unexpected packet type!");
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   523
		}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   524
		return false;
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   525
	}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   526
}
e684f11070d5 ajout de jlibrtp
nikita@nikita-rack
parents:
diff changeset
   527