src/jlibrtp/RtcpPktRTPFB.java
changeset 823 2036ebfaccda
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jlibrtp/RtcpPktRTPFB.java	Fri Nov 20 19:29:42 2009 +0100
@@ -0,0 +1,165 @@
+/**
+ * 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() ");
+	}
+}