src/jlibrtp/RTCPSession.java
author Da Risk <darisk972@gmail.com>
Tue, 14 Apr 2009 16:56:20 +0200
changeset 105 c6e4728ac9f7
parent 13 e684f11070d5
permissions -rw-r--r--
Passage sous cupcake :) Peu de modification de code, il faut juste creer des fichier aidl pour les classes parcelables. Sinon les fichier de build.xml ont ete completement modifiés, j'ai remplacé par les nouveaux. (il doit y avoir un manque de precision dans le fichier build.properties)
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