src/jlibrtp/RtcpPktRR.java
changeset 823 2036ebfaccda
equal deleted inserted replaced
536:537ddd8aa407 823:2036ebfaccda
       
     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
       
    48 	 *            the participants on which to generate reports
       
    49 	 * @param ssrc
       
    50 	 *            the SSRC of the sender, from the RTPSession
       
    51 	 */
       
    52 	protected RtcpPktRR(Participant[] reportees, long ssrc) {
       
    53 		super.packetType = 201;
       
    54 		// Fetch all the right stuff from the database
       
    55 		super.ssrc = ssrc;
       
    56 		this.reportees = reportees;
       
    57 	}
       
    58 
       
    59 	/**
       
    60 	 * 
       
    61 	 * 
       
    62 	 * If rcount < 0 we assume we have to parse the entire packet, otherwise
       
    63 	 * we'll just parse the receiver report blocks (ie. the data came from a
       
    64 	 * Sender Report packet)
       
    65 	 * 
       
    66 	 * @param aRawPkt
       
    67 	 *            the byte[] with the report(s)
       
    68 	 * @param start
       
    69 	 *            where in the raw packet to start reading
       
    70 	 * @param rrCount
       
    71 	 *            the number of receiver reports, -1 if this does not come from
       
    72 	 *            an SR
       
    73 	 */
       
    74 	protected RtcpPktRR(byte[] aRawPkt, int start, int rrCount) {
       
    75 		// System.out.println("RtcpPktRR: " + rrCount + "  start: " + start);
       
    76 		super.rawPkt = aRawPkt;
       
    77 
       
    78 		if (rrCount < 0
       
    79 				&& (!super.parseHeaders(start) || packetType != 201 || super.length < 1)) {
       
    80 			if (RTPSession.rtpDebugLevel > 2) {
       
    81 				System.out
       
    82 						.println(" <-> RtcpPktRR.parseHeaders() etc. problem: "
       
    83 								+ (!super.parseHeaders(start)) + " "
       
    84 								+ packetType + " " + super.length);
       
    85 			}
       
    86 			super.problem = -201;
       
    87 		}
       
    88 
       
    89 		int base;
       
    90 		if (rrCount > 0) {
       
    91 			base = start + 28;
       
    92 		} else {
       
    93 			base = start + 8;
       
    94 			rrCount = super.itemCount;
       
    95 			super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt, start + 4);
       
    96 		}
       
    97 
       
    98 		if (rrCount > 0) {
       
    99 			reporteeSsrc = new long[rrCount];
       
   100 			lossFraction = new int[rrCount];
       
   101 			lostPktCount = new int[rrCount];
       
   102 			extHighSeqRecv = new long[rrCount];
       
   103 			interArvJitter = new long[rrCount];
       
   104 			timeStampLSR = new long[rrCount];
       
   105 			delaySR = new long[rrCount];
       
   106 
       
   107 			for (int i = 0; i < rrCount; i++) {
       
   108 				int pos = base + i * 24;
       
   109 				reporteeSsrc[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos);
       
   110 				lossFraction[i] = (int) aRawPkt[pos + 4];
       
   111 				aRawPkt[pos + 4] = (byte) 0;
       
   112 				lostPktCount[i] = (int) StaticProcs.bytesToUIntLong(aRawPkt,
       
   113 						pos + 4);
       
   114 				extHighSeqRecv[i] = StaticProcs.bytesToUIntLong(aRawPkt,
       
   115 						pos + 8);
       
   116 				interArvJitter[i] = StaticProcs.bytesToUIntLong(aRawPkt,
       
   117 						pos + 12);
       
   118 				timeStampLSR[i] = StaticProcs
       
   119 						.bytesToUIntLong(aRawPkt, pos + 16);
       
   120 				delaySR[i] = StaticProcs.bytesToUIntLong(aRawPkt, pos + 20);
       
   121 			}
       
   122 		}
       
   123 	}
       
   124 
       
   125 	/**
       
   126 	 * Encode the packet into a byte[], saved in .rawPkt
       
   127 	 * 
       
   128 	 * CompRtcpPkt will call this automatically
       
   129 	 */
       
   130 	protected void encode() {
       
   131 		if (RTPSession.rtpDebugLevel > 9) {
       
   132 			System.out.println("  -> RtcpPktRR.encode()");
       
   133 		}
       
   134 
       
   135 		byte[] rRs = null;
       
   136 		// Gather up the actual receiver reports
       
   137 		if (this.reportees != null) {
       
   138 			rRs = this.encodeRR();
       
   139 			super.rawPkt = new byte[rRs.length + 8];
       
   140 			System.arraycopy(rRs, 0, super.rawPkt, 8, rRs.length);
       
   141 			super.itemCount = reportees.length;
       
   142 		} else {
       
   143 			super.rawPkt = new byte[8];
       
   144 			super.itemCount = 0;
       
   145 		}
       
   146 
       
   147 		// Write the common header
       
   148 		super.writeHeaders();
       
   149 
       
   150 		// Add our SSRC (as sender)
       
   151 		StaticProcs.uIntLongToByteWord(super.ssrc, super.rawPkt, 4);
       
   152 
       
   153 		if (RTPSession.rtpDebugLevel > 9) {
       
   154 			System.out.println("  <- RtcpPktRR.encode()");
       
   155 		}
       
   156 
       
   157 	}
       
   158 
       
   159 	/**
       
   160 	 * Encodes the individual Receiver Report blocks,
       
   161 	 * 
       
   162 	 * so they can be used either in RR packets or appended to SR
       
   163 	 * 
       
   164 	 * @return the encoded packets
       
   165 	 */
       
   166 	protected byte[] encodeRR() {
       
   167 		if (RTPSession.rtpDebugLevel > 10) {
       
   168 			System.out.println("   -> RtcpPktRR.encodeRR()");
       
   169 		}
       
   170 		// assuming we will always create complete reports:
       
   171 		byte[] ret = new byte[24 * reportees.length];
       
   172 
       
   173 		// Write SR stuff
       
   174 		for (int i = 0; i < reportees.length; i++) {
       
   175 			int offset = 24 * i;
       
   176 			StaticProcs.uIntLongToByteWord(reportees[i].ssrc, ret, offset);
       
   177 
       
   178 			// Cumulative number of packets lost
       
   179 			StaticProcs.uIntLongToByteWord(reportees[i]
       
   180 					.getLostPktCount(), ret, 4 + offset);
       
   181 
       
   182 			// Write Cumulative number of packets lost and loss fraction to
       
   183 			// packet:
       
   184 			System.arraycopy(reportees[i].getFractionLost(), 0, ret, 4 + offset, 1);
       
   185 
       
   186 			// Extended highest sequence received
       
   187 			StaticProcs.uIntLongToByteWord(reportees[i]
       
   188 					.getExtHighSeqRecv(), ret, 8 + offset);
       
   189 
       
   190 			// Interarrival jitter
       
   191 			if (reportees[i].interArrivalJitter >= 0) {
       
   192 				StaticProcs
       
   193 						.uIntLongToByteWord((long) reportees[i].interArrivalJitter, ret, 12 + offset);
       
   194 			} else {
       
   195 				StaticProcs.uIntLongToByteWord(0, ret, 12 + offset);
       
   196 			}
       
   197 
       
   198 			// Timestamp last sender report received
       
   199 			StaticProcs
       
   200 					.uIntLongToByteWord(reportees[i].timeStampLSR, ret, 16 + offset);
       
   201 
       
   202 			// Delay since last sender report received, in terms of 1/655536 s =
       
   203 			// 0.02 ms
       
   204 			if (reportees[i].timeReceivedLSR > 0) {
       
   205 				StaticProcs.uIntLongToByteWord(reportees[i]
       
   206 						.delaySinceLastSR(), ret, 20 + offset);
       
   207 			} else {
       
   208 				StaticProcs.uIntLongToByteWord(0,ret, 20 + offset);
       
   209 			}
       
   210 		}
       
   211 		if (RTPSession.rtpDebugLevel > 10) {
       
   212 			System.out.println("   <- RtcpPktRR.encodeRR()");
       
   213 		}
       
   214 		return ret;
       
   215 	}
       
   216 
       
   217 	/**
       
   218 	 * Debug purposes only
       
   219 	 */
       
   220 	public void debugPrint() {
       
   221 		System.out.println("RtcpPktRR.debugPrint() ");
       
   222 		if (reportees != null) {
       
   223 			for (int i = 0; i < reportees.length; i++) {
       
   224 				Participant part = reportees[i];
       
   225 				System.out.println("     part.ssrc: " + part.ssrc
       
   226 						+ "  part.cname: " + part.cname);
       
   227 			}
       
   228 		} else {
       
   229 			for (int i = 0; i < reporteeSsrc.length; i++) {
       
   230 				System.out.println("     reporteeSSRC: " + reporteeSsrc[i]
       
   231 						+ "  timeStampLSR: " + timeStampLSR[i]);
       
   232 			}
       
   233 		}
       
   234 	}
       
   235 }