package com.onionnetworks.fec; import com.onionnetworks.util.Util; import com.onionnetworks.util.Buffer; /** * This class, along with FECMath, provides the implementation of the pure * Java 8 bit FEC codes. This is heavily dervied from Luigi Rizzos original * C implementation. See the file "LICENSE" along with this distribution for * additional copyright information. * * (c) Copyright 2001 Onion Networks * (c) Copyright 2000 OpenCola * * @author Justin F. Chapweske (justin@chapweske.com) */ public class PureCode extends FECCode { // Keeping this around because it amuses me. public static final int FEC_MAGIC = 0xFECC0DEC; protected static final FECMath fecMath = new FECMath(8); protected char[] encMatrix; //create a new encoder. This contains n,k and the encoding matrix. public PureCode(int k, int n) { this(k,n,fecMath.createEncodeMatrix(k,n)); } public PureCode(int k, int n, char[] encMatrix) { super(k,n); this.encMatrix = encMatrix; } /** * encode accepts as input pointers to n data packets of size sz, * and produces as output a packet pointed to by fec, computed * with index "index". */ protected void encode(byte[][] src, int[] srcOff, byte[][] repair, int[] repairOff, int[] index, int packetLength) { for (int i=0;i<repair.length;i++) { encode(src,srcOff,repair[i],repairOff[i],index[i],packetLength); } } protected void encode(byte[][] src, int[] srcOff, byte[] repair, int repairOff, int index, int packetLength) { // *remember* indices start at 0, k starts at 1. if (index < k) { // < k, systematic so direct copy. System.arraycopy(src[index],srcOff[index],repair,repairOff, packetLength); } else { // index >= k && index < n int pos = index*k; Util.bzero(repair,repairOff,packetLength); for (int i=0; i<k ; i++) { fecMath.addMul(repair,repairOff,src[i],srcOff[i], (byte) encMatrix[pos+i],packetLength); } } } protected void decode(byte[][] pkts, int[] pktsOff, int[] index, int packetLength, boolean shuffled) { // This may be the second time shuffle has been called, if so // this is ok because it will quickly determine that things are in // order. The previous shuffles may have been necessary to keep // another data structure in sync with the byte[]'s if (!shuffled) { shuffle(pkts, pktsOff, index, k); } char[] decMatrix = fecMath.createDecodeMatrix(encMatrix,index,k,n); // do the actual decoding.. byte[][] tmpPkts = new byte[k][]; for (int row=0; row<k; row++) { if (index[row] >= k) { tmpPkts[row] = new byte[packetLength]; for (int col=0 ; col<k ; col++) { fecMath.addMul(tmpPkts[row],0,pkts[col],pktsOff[col], (byte) decMatrix[row*k + col], packetLength); } } } // move pkts to their final destination for (int row=0;row < k;row++) { if (index[row] >= k) { // only copy those actually decoded. System.arraycopy(tmpPkts[row],0, pkts[row],pktsOff[row], packetLength); index[row] = row; } } } public String toString() { return new String("PureCode[k="+k+",n="+n+"]"); } }