/// <summary> /// Static constructor: Create the encoding Vandermonde matrix /// </summary> static RS_Fec() { // To increase runtime encoding performance, we create a large static Vandermonde encoding matrix ahead of time // that can be shared // maxChecksumPackets will be the max number of Columns of the encoding static matrix // maxDataPackets will be the max number of Rows of the encoding static matrix // Creation of the Vandermonde Matrix over GF16 with the following // (2^column)^row // As an example, a 5 x 3 Vandermonde Matrix over GF4 (5 data packets, 3 checksum packets) // would give the following: // // 1^0 2^0 4^0 // 1^1 2^1 4^1 // 1^2 2^2 4^2 // 1^3 2^3 4^3 // 1^4 2^4 4^4 // // Which gives: // // 1 1 1 // 1 2 4 // 1 4 16 // 1 8 64 // 1 16 256 enc = FEC_Matrix.CreateVandermondeMatrix(MaxChecksumPackets, MaxDataPackets); }
/// <summary> /// Invert the matrix by using Gauss-Jordan using GF16 operations /// </summary> /// <remarks> /// The inversion is done by adding the identity matrix to the right /// and using Gauss-Jordan algorithm (elementary /// operations on rows) until we get the identity matrix /// on the left. Then we strip the identity on the left /// in order to get the reverted matrix. /// </remarks> /// <param name="mtxIn_GF16">The matrix to invert</param> /// <returns>The inverted matrix</returns> public static GF16[,] Invert(GF16[,] mtxIn_GF16) { // Add the ID to the right to be able to apply Gauss-Jordan to revert the matrix GF16[,] mtxWithID_GF16 = FEC_Matrix.AddIdentityRight(mtxIn_GF16); // Apply Gauss Jordan algo to revert the matrix GF16[,] mtxInvert_GF16 = FEC_Matrix.GaussJordan(mtxWithID_GF16); // Remove the ID on the left GF16[,] mtxInvertStripped_GF16 = FEC_Matrix.StripIdentity(mtxInvert_GF16); // Return the inverted matrix return(mtxInvertStripped_GF16); }
// write the data into the provided RtpPacket's BufferChunks in the recovery[] /// <summary> /// Decode and insert in place the recovered packet(s) lost in the data BufferChunk array /// </summary> /// <param name="data">Array of BufferChunk that represents the data received including /// checksum (with a null entrie for each packet lost)</param> /// <param name="checksum">Number of checksum used to encode</param> /// <param name="recovery">Array of BufferChunk to store the recovered data packets</param> public void Decode(BufferChunk[] data, int checksum, BufferChunk[] recovery) { // TODO: We should first validate that #null entries in data BufferChunk // array is equal to recovery.Length and is also equal to checksum // Generate a decoding matrix from the BufferChunk array of packet received GF16[,] mtxDecode = FEC_BufferChunk.DecodingMatrixGeneration(data, checksum); // Invert the decoding matrix // TODO: To optimize we could generate the invert matrix only with the // row needed for decoding missing packets instead of the full inverted matrix GF16[,] mtxDecodeInverted = FEC_Matrix.Invert(mtxDecode); // Decode by multiplying the received data BufferChunk array // with the inverted decoding matrix. The operations are done over // GF16 (Galois Field 16 bits) FEC_BufferChunk.DecodeRS(checksum, data, mtxDecodeInverted, recovery); }