Warning: This is an old version. The latest stable version is Version 10.0.0.
In this example shows how to use the API of otacast
to implement encoding
and decoding.
The example will walk through the basic functionality of class encoder and class decoder, and discuss how to use them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | #include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <otacast/decoder.hpp>
#include <otacast/encoder.hpp>
#include <otacast/to_string.hpp>
#include <otacast/version.hpp>
int main()
{
// Create the encoder/decoder objects with a specific finite field
otacast::encoder encoder;
otacast::decoder decoder;
otacast::finite_field field = otacast::finite_field::binary8;
std::size_t block_bytes = 1024 * 1000; // 1 MB
std::size_t symbol_bytes = 1500; // 1.5 kB
std::size_t width = 5;
encoder.configure(field, block_bytes, symbol_bytes, width);
decoder.configure(field, block_bytes, symbol_bytes, width);
// Allocate some data to decode
std::vector<uint8_t> data_in(encoder.block_bytes());
// For the example - fill data_in with random data
std::generate(data_in.begin(), data_in.end(), rand);
// Assign the data buffer to the encoder so that we may start
// to produce encoded symbols from it
encoder.set_symbols_storage(data_in.data());
// Define a data buffer where the symbols should be decoded
std::vector<uint8_t> data_out(decoder.block_bytes());
decoder.set_symbols_storage(data_out.data());
// Initiate a zero-vector for the offset
std::vector<uint8_t> symbol(encoder.symbol_bytes());
// The seed can be anything, here it's basically a packet sequence number.
// Will be used to count transmissions as well
uint64_t transmissions = 0;
// Set up some packet loss
auto loss_probability = 10;
while (!decoder.can_complete_decoding())
{
// Generate an encoded packet using the number of transmissions as seed
auto offset = encoder.encode(symbol.data(), transmissions);
// We see if the packet is lost
if (rand() % 100 < loss_probability)
{
std::cout << " - lost" << std::endl;
}
else
{
// Get the current rank before decoding
auto old_rank = decoder.rank();
// Decode the encoded packet using the number of transmissions as
// seed
decoder.decode(symbol.data(), transmissions, offset);
// If decoder rank is unchanged, the packet was useless (linearly
// dependent)
if (decoder.rank() == old_rank)
{
std::cout << "Packet linearly dependant" << std::endl;
}
}
transmissions++;
}
// The decoder is ready for the final decoding
decoder.complete_decoding();
// Count the percentage of succesful decoding attempts
auto decode_percent = (block_bytes / symbol_bytes) * 100 / transmissions;
// Check if everything went as it should
if (data_in == data_out)
{
std::cout << "Decoding finished successfully!" << std::endl;
std::cout << "% of Succesful decoding attempts: " << decode_percent
<< "%" << std::endl;
}
else
{
std::cout << "Something went wrong!" << std::endl;
}
return 0;
}
|