Nagram/TMessagesProj/jni/libtgvoip3/video/cm256/README.md

155 lines
5.7 KiB
Markdown
Raw Normal View History

2020-03-30 12:00:09 +00:00
# cm256cc
Fast GF(256) Cauchy MDS Block Erasure Codec in C++
This is the rewrite in (as much as possible) clean C++ of [cm256](https://github.com/f4exb/cm256). In some contexts like Qt programs and plugins the original cm256 library does not work.
cm256cc performance is on par or even better than cm256. This is particularly true for armv7 architecture (Raspberry Pi 2 and 3) and is the most significant with Raspberry Pi 2.
cm256cc is a simple library for erasure codes. From given data it generates
redundant data that can be used to recover the originals.
Currently only g++ is supported, other versions of MSVC than Visual Studio 2013 may work. Optimizations for both SSE3 (x86_64) and Neon (armv7) are available.
The original data should be split up into equally-sized chunks. If one of these chunks
is erased, the redundant data can fill in the gap through decoding.
The erasure code is parameterized by three values (`OriginalCount`, `RecoveryCount`, `BlockBytes`). These are:
+ The number of blocks of original data (`OriginalCount`), which must be less than 256.
+ The number of blocks of redundant data (`RecoveryCount`), which must be no more than `256 - OriginalCount`.
For example, if a file is split into 3 equal pieces and sent over a network, `OriginalCount` is 3.
And if 2 additional redundant packets are generated, `RecoveryCount` is 2.
In this case up to 256 - 3 = 253 additional redundant packets can be generated.
##### Building: Quick Setup
This is a classical cmake project. Make sure cmake and g++ is installed in your system. create a `build` directory and cd into it. If you install the library in a custom location say `opt/install/cm256cc` use the following command line for cmake:
- `cmake -Wno-dev -DCMAKE_INSTALL_PREFIX=/opt/install/cm256cc ..`
Result:
- Library will be installed as `/opt/install/cm256cc/lib/libcm256cc.so`
- Include files will be installed in `/opt/install/cm256cc/include/cm256cc`
- Binary test programs will be installed in `/opt/install/cm256cc/bin`
##### Building: Use the library
Include the cm256cc library in your project and cm256.h header in your program. Have a look at example programs `cm256_test.cpp`, `transmit.cpp`and `receive.cpp` in the `unit_test` folder for usage. Consult the `cm256.h header` for details on the encoding / decoding method.
## Usage
Documentation is provided in the header file [cm256.h](https://github.com/catid/cm256/raw/master/cm256.h).
When your application starts up it should call `isInitialized()` to verify that the library is constructed properly:
~~~
#include "cm256.h"
CM256 cm256;
if (!cm256.isInitialized()) {
// library not initialized
exit(1);
}
~~~
To generate redundancy, use the `cm256_encode` function. To solve for the original data use the `cm256_decode` function.
Example usage:
~~~
bool ExampleFileUsage()
{
CM256 cm256;
if (!cm256.isInitialized()) {
// library not initialized
exit(1);
}
CM256::cm256_encoder_params params;
// Number of bytes per file block
params.BlockBytes = 4321;
// Number of blocks
params.OriginalCount = 33;
// Number of additional recovery blocks generated by encoder
params.RecoveryCount = 12;
// Size of the original file
static const int OriginalFileBytes = params.OriginalCount * params.BlockBytes;
// Allocate and fill the original file data
uint8_t* originalFileData = new uint8_t[OriginalFileBytes];
memset(originalFileData, 1, OriginalFileBytes);
// Pointers to data
CM256::cm256_block blocks[256];
for (int i = 0; i < params.OriginalCount; ++i)
{
blocks[i].Block = originalFileData + i * params.BlockBytes;
}
// Recovery data
uint8_t* recoveryBlocks = new uint8_t[params.RecoveryCount * params.BlockBytes];
// Generate recovery data
if (cm256.cm256_encode(params, blocks, recoveryBlocks))
{
exit(1);
}
// Initialize the indices
for (int i = 0; i < params.OriginalCount; ++i)
{
blocks[i].Index = CM256::cm256_get_original_block_index(params, i);
}
//// Simulate loss of data, subsituting a recovery block in its place ////
blocks[0].Block = recoveryBlocks; // First recovery block
blocks[0].Index = cm256_get_recovery_block_index(params, 0); // First recovery block index
//// Simulate loss of data, subsituting a recovery block in its place ////
if (cm256.cm256_decode(params, blocks))
{
exit(1);
}
// blocks[0].Index will now be 0.
delete[] originalFileData;
delete[] recoveryBlocks;
return true;
}
~~~
The example above is just one way to use the `cm256_decode` function.
This API was designed to be flexible enough for UDP/IP-based file transfer where
the blocks arrive out of order.
#### Comparisons with Other Libraries
The approach taken in CM256 is similar to the Intel Storage Acceleration Library (ISA-L) available here:
https://01.org/intel%C2%AE-storage-acceleration-library-open-source-version/downloads
ISA-L more aggressively optimizes the matrix multiplication operation, which is the most expensive step of encoding.
CM256 takes better advantage of the m=1 case and the first recovery symbol, which is also possible with the Vandermonde matrices supported by ISA-L.
ISA-L uses a O(N^3) Gaussian elimination solver for decoding. The CM256 decoder solves the linear system using a fast O(N^2) LDU-decomposition algorithm from "Pivoting and Backward Stability of Fast Algorithms for Solving Cauchy Linear Equations" (T. Boros, T. Kailath, V. Olshevsky), which was hand-optimized for memory accesses.
#### Credits
This software was written entirely by Christopher A. Taylor <mrcatid@gmail.com> and converted to clean C++ code by myself Edouard M. Griffiths <f4exb06@gmail.com>.