src/jlibrtp/RtcpPktRR.java
changeset 214 2bf440c54ca5
parent 213 9bdff6cbd120
child 215 5db64229be69
equal deleted inserted replaced
213:9bdff6cbd120 214:2bf440c54ca5
     1 /**
       
     2  * Java RTP Library (jlibrtp)
       
     3  * Copyright (C) 2006 Arne Kepp
       
     4  * 
       
     5  * This library is free software; you can redistribute it and/or
       
     6  * modify it under the terms of the GNU Lesser General Public
       
     7  * License as published by the Free Software Foundation; either
       
     8  * version 2.1 of the License, or (at your option) any later version.
       
     9  *
       
    10  * This library is distributed in the hope that it will be useful,
       
    11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13  * Lesser General Public License for more details.
       
    14  * 
       
    15  * You should have received a copy of the GNU Lesser General Public
       
    16  * License along with this library; if not, write to the Free Software
       
    17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
       
    18  */
       
    19 package jlibrtp;
       
    20 
       
    21 /**
       
    22  * RTCP packets for Receiver Reports 
       
    23  * 
       
    24  * @author Arne Kepp
       
    25  */
       
    26 public class RtcpPktRR extends RtcpPkt {
       
    27 	/** Array of participants to send Receiver Reports to */
       
    28 	protected Participant[] reportees = null;
       
    29 	/** SSRC of participants the reports are for */
       
    30 	protected long[] reporteeSsrc = null;// -1; //32 bits
       
    31 	/** Fraction (over 256) of packets lost */
       
    32 	protected int[] lossFraction = null;//-1; //8 bits
       
    33 	/** Number of lost packets */
       
    34 	protected int[] lostPktCount = null;//-1; //24 bits
       
    35 	/** Extended highest sequence received */
       
    36 	protected long[] extHighSeqRecv = null;//-1; //32 bits
       
    37 	/** Interarrival jitter*/
       
    38 	protected long[] interArvJitter = null;//-1; //32 bits
       
    39 	/** Middle 32 bits of NTP when last SR was received */
       
    40 	protected long[] timeStampLSR = null;//-1; //32 bits
       
    41 	/** Delay on last SRC */
       
    42 	protected long[] delaySR = null;//-1; //32 bits
       
    43 	
       
    44 	/**
       
    45 	 * Constructor for a packet with receiver reports
       
    46 	 * 
       
    47 	 * @param reportees the participants on which to generate reports
       
    48 	 * @param ssrc the SSRC of the sender, from the RTPSession
       
    49 	 */
       
    50 	protected RtcpPktRR(Participant[] reportees, long ssrc) {
       
    51 		super.packetType = 201;
       
    52 		// Fetch all the right stuff from the database
       
    53 		super.ssrc = ssrc;
       
    54 		this.reportees = reportees;
       
    55 	}
       
    56 
       
    57 
       
    58 	/**
       
    59 	 * 
       
    60 	 * 
       
    61 	 * If rcount < 0 we assume we have to parse the entire packet,
       
    62 	 * otherwise we'll just parse the receiver report blocks
       
    63 	 * (ie. the data came from a Sender Report packet)
       
    64 	 * 
       
    65 	 * @param aRawPkt the byte[] with the report(s)
       
    66 	 * @param start where in the raw packet to start reading
       
    67 	 * @param rrCount the number of receiver reports, -1 if this does not come from an SR
       
    68 	 */
       
    69 	protected RtcpPktRR(byte[] aRawPkt, int start, int rrCount) {
       
    70 		//System.out.println("RtcpPktRR: " + rrCount + "  start: " + start);
       
    71 		super.rawPkt = aRawPkt;
       
    72 		
       
    73 		if(rrCount < 0 && (!super.parseHeaders(start) || packetType != 201 || super.length < 1)) {
       
    74 			if(RTPSession.rtpDebugLevel > 2) {
       
    75 				System.out.println(" <-> RtcpPktRR.parseHeaders() etc. problem: "+(!super.parseHeaders(start))+" "+packetType+" "+super.length);
       
    76 			}
       
    77 			super.problem = -201;
       
    78 		}
       
    79 		
       
    80 		int base;
       
    81 		if(rrCount > 0) {
       
    82 			base = start + 28;
       
    83 		} else {
       
    84 			base = start + 8;
       
    85 			rrCount = super.itemCount;
       
    86 			super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt, start + 4);
       
    87 		}
       
    88 		
       
    89 		if(rrCount > 0) {
       
    90 			reporteeSsrc = new long[rrCount];
       
    91 			lossFraction = new int[rrCount];
       
    92 			lostPktCount = new int[rrCount];
       
    93 			extHighSeqRecv = new long[rrCount];
       
    94 			interArvJitter = new long[rrCount];
       
    95 			timeStampLSR = new long[rrCount];
       
    96 			delaySR = new long[rrCount];
       
    97 
       
    98 			for(int i=0; i<rrCount; i++ ) {
       
    99 				int pos = base + i*24;
       
   100 				reporteeSsrc[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos);
       
   101 				lossFraction[i] = (int) aRawPkt[pos + 4];
       
   102 				aRawPkt[pos + 4] = (byte) 0;
       
   103 				lostPktCount[i] = (int) StaticProcs.bytesToUIntLong(aRawPkt, pos + 4);
       
   104 				extHighSeqRecv[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 8);
       
   105 				interArvJitter[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 12);
       
   106 				timeStampLSR[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 16);
       
   107 				delaySR[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 20);
       
   108 			}
       
   109 		}
       
   110 	}
       
   111 	
       
   112 	/**
       
   113 	 * Encode the packet into a byte[], saved in .rawPkt
       
   114 	 * 
       
   115 	 * CompRtcpPkt will call this automatically
       
   116 	 */
       
   117 	protected void encode() {
       
   118 		if(RTPSession.rtpDebugLevel > 9) {
       
   119 			System.out.println("  -> RtcpPktRR.encode()");
       
   120 		}
       
   121 		
       
   122 		byte[] rRs = null;
       
   123 		//Gather up the actual receiver reports
       
   124 		if(this.reportees != null) {
       
   125 			rRs = this.encodeRR();
       
   126 			super.rawPkt = new byte[rRs.length + 8];
       
   127 			System.arraycopy(rRs, 0, super.rawPkt, 8, rRs.length);
       
   128 			super.itemCount = reportees.length;
       
   129 		} else {
       
   130 			super.rawPkt = new byte[8];
       
   131 			super.itemCount = 0;	
       
   132 		}
       
   133 		
       
   134 		//Write the common header
       
   135 		super.writeHeaders();
       
   136 		
       
   137 		//Add our SSRC (as sender)
       
   138 		byte[] someBytes;
       
   139 		someBytes = StaticProcs.uIntLongToByteWord(super.ssrc);
       
   140 		System.arraycopy(someBytes, 0, super.rawPkt, 4, 4);
       
   141 		
       
   142 		if(RTPSession.rtpDebugLevel > 9) {
       
   143 			System.out.println("  <- RtcpPktRR.encode()");
       
   144 		}
       
   145 		
       
   146 	}
       
   147 	
       
   148 	/**
       
   149 	 * Encodes the individual Receiver Report blocks, 
       
   150 	 * 
       
   151 	 * so they can be used either in RR packets or appended to SR
       
   152 	 * 
       
   153 	 * @return the encoded packets
       
   154 	 */
       
   155 	protected byte[] encodeRR() {
       
   156 		if(RTPSession.rtpDebugLevel > 10) {
       
   157 			System.out.println("   -> RtcpPktRR.encodeRR()");
       
   158 		}
       
   159 		//assuming we will always create complete reports:
       
   160 		byte[] ret = new byte[24*reportees.length];
       
   161 		
       
   162 		//Write SR stuff
       
   163 		for(int i = 0; i<reportees.length; i++) {
       
   164 			int offset = 24*i;
       
   165 			byte[] someBytes = StaticProcs.uIntLongToByteWord(reportees[i].ssrc);
       
   166 			System.arraycopy(someBytes, 0, ret, offset, 4);
       
   167 			
       
   168 			//Cumulative number of packets lost
       
   169 			someBytes = StaticProcs.uIntLongToByteWord(reportees[i].getLostPktCount());
       
   170 		
       
   171 			someBytes[0] = (byte) reportees[i].getFractionLost();
       
   172 		
       
   173 			//Write Cumulative number of packets lost and loss fraction to packet:
       
   174 			System.arraycopy(someBytes, 0, ret, 4 + offset, 4);
       
   175 		
       
   176 			// Extended highest sequence received
       
   177 			someBytes = StaticProcs.uIntLongToByteWord(reportees[i].getExtHighSeqRecv());
       
   178 			System.arraycopy(someBytes, 0, ret, 8 + offset, 4);
       
   179 		
       
   180 			// Interarrival jitter
       
   181 			if(reportees[i].interArrivalJitter >= 0) {
       
   182 				someBytes = StaticProcs.uIntLongToByteWord((long)reportees[i].interArrivalJitter);
       
   183 			} else { 
       
   184 				someBytes = StaticProcs.uIntLongToByteWord((long) 0); 
       
   185 			}
       
   186 			System.arraycopy(someBytes, 0, ret, 12 + offset, 4);
       
   187 		
       
   188 			// Timestamp last sender report received
       
   189 			someBytes = StaticProcs.uIntLongToByteWord(reportees[i].timeStampLSR);
       
   190 			System.arraycopy(someBytes, 0, ret, 16 + offset, 4);
       
   191 		
       
   192 			// Delay since last sender report received, in terms of 1/655536 s = 0.02 ms
       
   193 			if(reportees[i].timeReceivedLSR > 0) {
       
   194 				someBytes = StaticProcs.uIntLongToByteWord(reportees[i].delaySinceLastSR());
       
   195 			} else {
       
   196 				someBytes = StaticProcs.uIntLongToByteWord(0);
       
   197 			}
       
   198 			System.arraycopy(someBytes, 0, ret, 20 + offset, 4);
       
   199 		}
       
   200 		if(RTPSession.rtpDebugLevel > 10) {
       
   201 			System.out.println("   <- RtcpPktRR.encodeRR()");
       
   202 		}
       
   203 		return ret;
       
   204 	}
       
   205 	
       
   206 	/**
       
   207 	 * Debug purposes only
       
   208 	 */
       
   209 	public void debugPrint() {
       
   210 		System.out.println("RtcpPktRR.debugPrint() ");
       
   211 		if(reportees != null) {
       
   212 			for(int i= 0; i<reportees.length; i++) {
       
   213 				Participant part = reportees[i];
       
   214 				System.out.println("     part.ssrc: " + part.ssrc + "  part.cname: " + part.cname);
       
   215 			}
       
   216 		} else {
       
   217 			for(int i=0;i<reporteeSsrc.length; i++) {
       
   218 				System.out.println("     reporteeSSRC: " + reporteeSsrc[i] + "  timeStampLSR: " + timeStampLSR[i]);
       
   219 			}
       
   220 		}
       
   221 	}
       
   222 }