src/jlibrtp/RtcpPktRTPFB.java
changeset 13 e684f11070d5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jlibrtp/RtcpPktRTPFB.java	Sat Mar 14 22:15:41 2009 +0100
@@ -0,0 +1,154 @@
+/**
+ * Java RTP Library (jlibrtp)
+ * Copyright (C) 2006 Arne Kepp
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+package jlibrtp;
+
+/**
+ * RTCP packets for RTP Feedback Messages 
+ * 
+ * In line with RFC 4585, this packet currently only supports NACKs
+ * 
+ * @author Arne Kepp
+ */
+public class RtcpPktRTPFB extends RtcpPkt {
+	/** If this packet was for a different SSRC */
+	protected boolean notRelevant = false;
+	/** SSRC we are sending feeback to */
+	protected long ssrcMediaSource = -1;
+	/** RTP sequence numbers of lost packets */
+	protected int PID[];
+	/** bitmask of following lost packets, shared index with PID */
+	protected int BLP[];
+	
+	/**
+	 * Constructor for RTP Feedback Message
+	 * 
+	 * @param ssrcPacketSender SSRC of sender, taken from RTPSession
+	 * @param ssrcMediaSource SSRC of recipient of this message
+	 * @param FMT the Feedback Message Subtype
+	 * @param PID RTP sequence numbers of lost packets
+	 * @param BLP bitmask of following lost packets, shared index with PID 
+	 */
+	protected RtcpPktRTPFB(long ssrcPacketSender, long ssrcMediaSource, int FMT, int[] PID, int[] BLP) {
+		super.packetType = 205; //RTPFB
+		super.itemCount = FMT; 
+		this.PID = PID;
+		this.BLP = BLP;
+	}
+	
+	/**
+	 * Constructor that parses a raw packet to retrieve information
+	 * 
+	 * @param aRawPkt the raw packet to be parsed
+	 * @param start the start of the packet, in bytes
+	 * @param rtpSession the session on which the callback interface resides
+	 */
+	protected RtcpPktRTPFB(byte[] aRawPkt, int start, RTPSession rtpSession) {		
+		if(RTPSession.rtpDebugLevel > 8) {
+			System.out.println("  -> RtcpPktRTPFB(byte[], int start)");
+		}
+		
+		rawPkt = aRawPkt;
+
+		if(! super.parseHeaders(start) || packetType != 205 || super.length < 2) {
+			if(RTPSession.rtpDebugLevel > 2) {
+				System.out.println(" <-> RtcpPktRTPFB.parseHeaders() etc. problem");
+			}
+			super.problem = -205;
+		} else {
+			//FMT = super.itemCount;
+			
+			ssrcMediaSource = StaticProcs.bytesToUIntLong(aRawPkt,8+start);
+			
+			if(ssrcMediaSource == rtpSession.ssrc) {
+				super.ssrc = StaticProcs.bytesToUIntLong(aRawPkt,4+start);
+				int loopStop = super.length - 2;
+				PID = new int[loopStop];
+				BLP = new int[loopStop];
+				int curStart = 12;
+
+				// Loop over Feedback Control Information (FCI) fields
+				for(int i=0; i< loopStop; i++) {
+					PID[i] = StaticProcs.bytesToUIntInt(aRawPkt, curStart);
+					BLP[i] = StaticProcs.bytesToUIntInt(aRawPkt, curStart + 2);
+					curStart += 4;
+				}
+
+				rtpSession.rtcpAVPFIntf.RTPFBPktReceived(
+						super.ssrc, super.itemCount, PID, BLP);
+			}
+		}
+		
+
+		
+		if(RTPSession.rtpDebugLevel > 8) {
+			System.out.println("  <- RtcpPktRTPFB()");
+		}
+	}
+	
+	/**
+	 * Encode the packet into a byte[], saved in .rawPkt
+	 * 
+	 * CompRtcpPkt will call this automatically
+	 */
+	protected void encode() {
+		super.rawPkt = new byte[12 + this.PID.length*4];
+		
+		byte[] someBytes = StaticProcs.uIntLongToByteWord(super.ssrc);
+		System.arraycopy(someBytes, 0, super.rawPkt, 4, 4);
+		someBytes = StaticProcs.uIntLongToByteWord(this.ssrcMediaSource);
+		System.arraycopy(someBytes, 0, super.rawPkt, 8, 4);
+		
+		// Loop over Feedback Control Information (FCI) fields
+		int curStart = 12;
+		for(int i=0; i < this.PID.length; i++ ) {
+			someBytes = StaticProcs.uIntIntToByteWord(PID[i]);
+			super.rawPkt[curStart++] = someBytes[0];
+			super.rawPkt[curStart++] = someBytes[1];
+			someBytes = StaticProcs.uIntIntToByteWord(BLP[i]);
+			super.rawPkt[curStart++] = someBytes[0];
+			super.rawPkt[curStart++] = someBytes[1];
+		}
+		writeHeaders();
+	}
+	
+	/** 
+	 * Get the FMT (Feedback Message Type)
+	 * @return value stored in .itemcount, same field
+	 */
+	protected int getFMT() {
+		return this.itemCount;
+	}
+	
+	/**
+	 * Debug purposes only
+	 */
+	protected void debugPrint() {
+		System.out.println("->RtcpPktRTPFB.debugPrint() ");
+		System.out.println("  ssrcPacketSender: " + super.ssrc + "  ssrcMediaSource: " + ssrcMediaSource);
+		
+		if(this.PID != null && this.PID.length < 1) {
+			System.out.println("  No Feedback Control Information (FCI) fields");
+		}
+		
+		for(int i=0; i < this.PID.length; i++ ) {
+			System.out.println("  FCI -> PID: " + PID[i] + "  BLP: " + BLP[i]);
+		}
+		System.out.println("<-RtcpPktRTPFB.debugPrint() ");
+	}
+}