TEST(TestReedSolomonCodes, test_encode_decode)
{
    {
        kodo::rs_encoder<fifi::binary8>::factory encoder_factory(255, 1600);
        kodo::rs_decoder<fifi::binary8>::factory decoder_factory(255, 1600);

        uint32_t symbols = rand_symbols(255);
        uint32_t symbol_size = rand_symbol_size();

        encoder_factory.set_symbols(symbols);
        encoder_factory.set_symbol_size(symbol_size);

        decoder_factory.set_symbols(symbols);
        decoder_factory.set_symbol_size(symbol_size);

        auto encoder = encoder_factory.build();
        auto decoder = decoder_factory.build();

        // Encode/decode operations
        EXPECT_TRUE(encoder->payload_size() == decoder->payload_size());

        std::vector<uint8_t> payload(encoder->payload_size());
        std::vector<uint8_t> data_in = random_vector(encoder->block_size());

        encoder->set_symbols(sak::storage(data_in));

        uint32_t symbol_count = 0;
        while( !decoder->is_complete() )
        {
            encoder->encode( &payload[0] );
            decoder->decode( &payload[0] );
            ++symbol_count;
        }

        // A reed solomon code should be able to decode
        // with exactly k symbols
        EXPECT_EQ(symbol_count, symbols);

        std::vector<uint8_t> data_out(decoder->block_size(), '\0');
        decoder->copy_symbols(sak::storage(data_out));

        EXPECT_TRUE(std::equal(data_out.begin(),
                               data_out.end(),
                               data_in.begin()));

    }

}
TEST(TestReedSolomonCodes, test_construct)
{

    {
        kodo::rs_encoder<fifi::binary8>::factory encoder_factory(255, 1600);
        encoder_factory.set_symbols(128);
        encoder_factory.set_symbol_size(1600);

        auto encoder = encoder_factory.build();

        kodo::rs_decoder<fifi::binary8>::factory decoder_factory(255, 1600);
        decoder_factory.set_symbols(128);
        decoder_factory.set_symbol_size(1600);

        auto decoder = decoder_factory.build();
    }

}
Exemple #3
0
    static void test_decoder(uint32_t max_symbols, uint32_t max_symbol_size,
        codec code, field field)
    {
        decoder_factory decoder_factory(
            code,
            field,
            max_symbols,
            max_symbol_size);

        decoder decoder = decoder_factory.build();
        test_coder(decoder, max_symbols, max_symbol_size, code);

        // Decoder methods
        // Some codecs do not provide write_payload, i.e. recoding
        if (code == codec::seed || code == codec::sparse_seed ||
            code == codec::fulcrum || code == codec::reed_solomon)
        {
            EXPECT_FALSE(decoder.has_write_payload());
        }
        else
        {
            EXPECT_TRUE(decoder.has_write_payload());
        }

        EXPECT_GE(0U, decoder.symbols_uncoded());
        EXPECT_GE(0U, decoder.symbols_partially_decoded());

        if (code == codec::on_the_fly ||
            code == codec::sliding_window)
        {
            EXPECT_TRUE(decoder.has_partial_decoding_interface());
            EXPECT_FALSE(decoder.is_partially_complete());
            for (uint32_t i = 0; i < decoder.symbols(); ++i)
            {
                EXPECT_FALSE(decoder.is_symbol_pivot(i));
            }
        }
        else if (code == codec::full_vector ||
                 code == codec::perpetual)
        {
            EXPECT_FALSE(decoder.has_partial_decoding_interface());
        }
    }
Exemple #4
0
  int main()
  {
    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    uint32_t symbols = 42;
    uint32_t symbol_size = 100;

    typedef kodo::full_rlnc_encoder<fifi::binary8> rlnc_encoder;
    typedef kodo::full_rlnc_decoder<fifi::binary8> rlnc_decoder;

    // In the following we will make an encoder/decoder factory.
    // The factories are used to build actual encoders/decoders
    rlnc_encoder::factory encoder_factory(symbols, symbol_size);
    auto encoder = encoder_factory.build();

    rlnc_decoder::factory decoder_factory(symbols, symbol_size);
    auto  decoder = decoder_factory.build();

    std::vector<uint8_t> payload(encoder->payload_size());
    std::vector<uint8_t> data_in(encoder->block_size());

    // Just for fun - fill the data with random data
    for(auto &e: data_in)
        e = rand() % 256;

    // Assign the data buffer to the encoder so that we may start
    // to produce encoded symbols from it
    encoder->set_symbols(sak::storage(data_in));

    while( !decoder->is_complete() )
    {
        // Encode a packet into the payload buffer
        encoder->encode( &payload[0] );

        // Pass that packet to the decoder
        decoder->decode( &payload[0] );
    }
  }
TEST(TestTraceLinearBlockDecoder, print)
{
    typedef fifi::binary field_type;
    typedef kodo::full_rlnc_decoder<field_type, kodo::enable_trace>
        decoder_type;

    uint32_t symbols = 3;
    uint32_t symbol_size = 10;

    decoder_type::factory decoder_factory(symbols, symbol_size);

    auto decoder = decoder_factory.build();

    // Check that this code compiles
    {
        std::stringstream out;

        decoder->print_decoder_state(out);

        std::string result = "000 ?:  0 0 0 \n"
                             "001 ?:  0 0 0 \n"
                             "002 ?:  0 0 0 \n";

        EXPECT_EQ(result, out.str());
    }


    // Create a empty symbol and put it in
    std::vector<uint8_t> coefficients(
        decoder->coefficient_vector_size(), '\0');

    std::vector<uint8_t> symbol(
        decoder->symbol_size(), '\0');

    decoder->decode_symbol(&symbol[0], &coefficients[0]);

    {
        std::stringstream out;

        decoder->print_decoder_state(out);

        std::string result = "000 ?:  0 0 0 \n"
                             "001 ?:  0 0 0 \n"
                             "002 ?:  0 0 0 \n";

        EXPECT_EQ(result, out.str());
    }

    // Create a dummy symbol and put it in
    std::fill(coefficients.begin(), coefficients.end(), '\0');
    fifi::set_value<field_type>(&coefficients[0], 1, 1U);
    fifi::set_value<field_type>(&coefficients[0], 2, 1U);

    std::fill(symbol.begin(), symbol.end(), 'a');

    decoder->decode_symbol(&symbol[0], &coefficients[0]);

    {
        std::stringstream out;

        decoder->print_decoder_state(out);

        std::string result = "000 ?:  0 0 0 \n"
                             "001 C:  0 1 1 \n"
                             "002 ?:  0 0 0 \n";

        EXPECT_EQ(result, out.str());
    }

    std::fill(symbol.begin(), symbol.end(), 'b');


    decoder->decode_symbol(&symbol[0], 0U);

    {
        std::stringstream out;

        decoder->print_decoder_state(out);

        std::string result = "000 U:  1 0 0 \n"
                             "001 C:  0 1 1 \n"
                             "002 ?:  0 0 0 \n";

        EXPECT_EQ(result, out.str());
    }
}
int main(void)
{
    // Seed random number generator to produce different results every time
    srand((uint32_t)time(0));

    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    uint32_t max_symbols = 6;
    uint32_t max_symbol_size = 32;

    // Initilization of encoder and decoder
    kodocpp::encoder_factory encoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::encoder encoder = encoder_factory.build();

    kodocpp::decoder_factory decoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::decoder decoder = decoder_factory.build();

    // Allocate some storage for a "payload" the payload is what we would
    // eventually send over a network
    std::vector<uint8_t> payload(encoder.payload_size());

    // Allocate input and output data buffers
    std::vector<uint8_t> data_in(encoder.block_size());
    std::vector<uint8_t> data_out(decoder.block_size());

    // Fill the input buffer with random data
    std::generate(data_in.begin(), data_in.end(), rand);

    // Set the symbol storage for the encoder and decoder
    encoder.set_const_symbols(data_in.data(), encoder.block_size());
    decoder.set_mutable_symbols(data_out.data(), decoder.block_size());

    // Install the default trace function for encoder (writes to stdout)
    encoder.set_trace_stdout();

    // Install a custom trace function for the decoder
    auto callback = [](const std::string& zone, const std::string& data)
    {
        std::set<std::string> filters =
        {
            "decoder_state", "symbol_coefficients_before_read_symbol",
            "symbol_index_before_read_uncoded_symbol"
        };

        if (filters.count(zone))
        {
            std::cout << zone << ":" << std::endl;
            std::cout << data << std::endl;
        }
    };

    decoder.set_trace_callback(callback);

    while (!decoder.is_complete())
    {
        encoder.write_payload(payload.data());

        // Simulate a lossy channel where we are losing 50% of the packets
        if ((rand() % 2) == 0)
        {
            continue;
        }

        decoder.read_payload(payload.data());
    }

    // Check if we properly decoded the data
    if (std::equal(data_out.begin(), data_out.end(), data_in.begin()))
    {
        std::cout << "Data decoded correctly" << std::endl;
    }
    else
    {
        std::cout << "Unexpected failure to decode, "
                  << "please file a bug report :)" << std::endl;
    }

    return 0;
}
uint8_t *decode(uint32_t N, uint32_t max_symbols, uint32_t max_symbol_size, 
        kodocpp::field  field_size, ENCODED_DATA encoded_data_info) {

    kodocpp::decoder_factory decoder_factory(
        //kodocpp::codec::reed_solomon,
        kodocpp::codec::full_vector,
        field_size,
        max_symbols,
        max_symbol_size);



   //std::vector< std::vector < std::vector<uint8_t> > > *encoded_data  = encoded_data_info.vdata;
    
   std::vector< std::vector < std::vector<uint8_t> > > *encoded_data  
       = convert_from_C_to_vector(encoded_data_info);
     

    std::cout << "decode=======================" << std::endl;
    std::vector< uint8_t *> decoded_symbols;

    int num_blocks  = encoded_data_info.num_blocks;
    int data_size =0;


    for(int i=0; i < num_blocks; i++) {
   // std::cout << "decode=======================" << std::endl;
    //std::cout << "encoded_dat " << encoded_data_info.num_blocks << std::endl;
    //std::cout << "encoded_dat " << encoded_data_info.encoded_symbol_size << std::endl;

       kodocpp::decoder decoder = decoder_factory.build();
       std::vector<uint8_t> data_out(decoder.block_size());
       decoder.set_mutable_symbols(data_out.data(), decoder.block_size());

     //  std::cout << "=========== " << std::endl;
       for(int j=0; j < max_symbols; j++) {
         decoder.read_payload( (*encoded_data)[j][i].data());
       }

       uint8_t *decoded_symbol =  new uint8_t[max_symbol_size*max_symbols + 1];
  
       if( decoder.is_complete() ) {
         memcpy(decoded_symbol, data_out.data(), data_out.size());
       }
      decoded_symbol[max_symbol_size*max_symbols + 1]='\0';
      data_size += data_out.size();
      decoded_symbols.push_back(decoded_symbol);
    }

    uint8_t *decoded_data = (uint8_t *)malloc( sizeof(uint8_t)*(data_size + 1) ); 
    uint8_t *p = decoded_data;
    for(int i=0; i < decoded_symbols.size(); i++) {
        memcpy(p, decoded_symbols[i], strlen((char *)decoded_symbols[i]));
        p = p + strlen((char *)decoded_symbols[i]);
        free( decoded_symbols[i]);
   }
   decoded_data[data_size] = '\0';
   decoded_symbols.clear();

   return decoded_data;

}
Exemple #8
0
int main()
{

    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    uint32_t max_symbols = 42;
    uint32_t max_symbol_size = 64;

    std::string encode_filename = "encode-file.bin";

    // Create a test file for encoding.
    std::ofstream encode_file;
    encode_file.open (encode_filename, std::ios::binary);

    uint32_t file_size = 50000;
    std::vector<char> encode_data(file_size);
    std::vector<char> decode_data;

    // Just write some bytes to the file
    for(uint32_t i = 0; i < file_size; ++i)
    {
        encode_data[i] = rand() % 255;
    }
    encode_file.write(&encode_data[0], file_size);
    encode_file.close();

    // Select the encoding and decoding algorithms
    typedef kodo::full_rlnc_encoder<fifi::binary>
        encoder_t;

    typedef kodo::full_rlnc_decoder<fifi::binary>
        decoder_t;

    // Now for the encoder we use a file_encoder with the chosen
    // encoding algorithm
    typedef kodo::file_encoder<encoder_t>
        file_encoder_t;

    // For decoding we use an object_decoder with the chosen
    // decoding algorithm
    typedef kodo::object_decoder<decoder_t>
        object_decoder_t;

    // Create the encoder factory - builds the individual encoders used
    file_encoder_t::factory encoder_factory(max_symbols, max_symbol_size);

    // Create the actual file encoder using the encoder factory and
    // the filename of the file to be encoded
    file_encoder_t file_encoder(encoder_factory, encode_filename);

    // Create the decoder factory - build the individual decoders used
    object_decoder_t::factory decoder_factory(max_symbols, max_symbol_size);

    // Create the object decoder using the decoder factory and the
    // size of the file to be decoded
    object_decoder_t object_decoder(decoder_factory, file_size);

    // Now in the following loop we go through all the encoders
    // needed to encode the entire file. We the build the corresponding
    // decoder and decode the chunk immediately. In practice where
    // encoders and decoders are on different devices e.g. connected
    // over a network, we would have to pass also the encoder and decoder
    // index between the source and sink to allow the correct data would
    // passed from encoder to corresponding decoder.
    for(uint32_t i = 0; i < file_encoder.encoders(); ++i)
    {
        auto encoder = file_encoder.build(i);
        auto decoder = object_decoder.build(i);

        // Set the encoder non-systematic
        if(kodo::has_systematic_encoder<encoder_t>::value)
            kodo::set_systematic_off(encoder);

        std::vector<uint8_t> payload(encoder->payload_size());

        while( !decoder->is_complete() )
        {
            // Encode a packet into the payload buffer
            encoder->encode( &payload[0] );

            // In practice send the payload over a network, save it to
            // a file etc. Then when needed build and pass it to the decoder

            // Pass that packet to the decoder
            decoder->decode( &payload[0] );
        }

        std::vector<uint8_t> data_out(decoder->block_size());
        decoder->copy_symbols(sak::storage(data_out));
        data_out.resize(decoder->bytes_used());

        decode_data.insert(decode_data.end(),
                           data_out.begin(),
                           data_out.end());
    }

    // Check we properly decoded the data
    if (std::equal(decode_data.begin(),
                   decode_data.end(), encode_data.begin()))
    {
        std::cout << "Data decoded correctly" << std::endl;
    }
    else
    {
        std::cout << "Unexpected failure to decode "
                  << "please file a bug report :)" << std::endl;
    }
}
int main()
{
    //! [2]
    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    uint32_t max_symbols = 40;
    uint32_t max_symbol_size = 64;

    uint32_t object_size = 6400;
    //! [3]

    //! [4]
    using storage_encoder = kodo::object::storage_encoder<
        kodo::shallow_full_rlnc_encoder<fifi::binary>,
        kodo::fixed_partitioning_scheme>;

    using storage_decoder = kodo::object::storage_decoder<
        kodo::shallow_full_rlnc_decoder<fifi::binary>,
        kodo::fixed_partitioning_scheme>;
    //! [5]

    storage_encoder::factory encoder_factory(max_symbols, max_symbol_size);
    storage_decoder::factory decoder_factory(max_symbols, max_symbol_size);

    std::vector<uint8_t> data_out(object_size, '\0');
    std::vector<uint8_t> data_in(object_size, 'x');

    encoder_factory.set_storage(sak::storage(data_in));
    decoder_factory.set_storage(sak::storage(data_out));

    auto object_encoder = encoder_factory.build();
    auto object_decoder = decoder_factory.build();

    std::cout << "Object size = " << object_size << std::endl;
    std::cout << "Encoder blocks = " << object_encoder->blocks() << std::endl;
    std::cout << "Decoder blocks = " << object_decoder->blocks() << std::endl;

    //! [6]
    for (uint32_t i = 0; i < object_encoder->blocks(); ++i)
    {
        std::cout << "Block = " << i << " symbols = "
                  << object_encoder->symbols(i) << " symbol size = "
                  << object_encoder->symbol_size(i) << std::endl;
    }
    //! [7]

    for (uint32_t i = 0; i < object_encoder->blocks(); ++i)
    {
        auto e = object_encoder->build(i);
        auto d = object_decoder->build(i);

        std::vector<uint8_t> payload(e->payload_size());

        while (!d->is_complete())
        {
            e->encode( payload.data() );

            // Here we would send and receive the payload over a
            // network. Lets throw away some packet to simulate.
            if (rand() % 2)
            {
                continue;
            }

            d->decode( payload.data() );
        }
    }

    // Check we properly decoded the data
    if (data_in == data_out)
    {
        std::cout << "Data decoded correctly" << std::endl;
    }
    else
    {
        std::cout << "Unexpected failure to decode "
                  << "please file a bug report :)" << std::endl;
    }
}
Exemple #10
0
int main()
{
    // Seed the random number generator to produce different data every time
    srand((uint32_t)time(0));

    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    uint32_t max_symbols = 16;
    uint32_t max_symbol_size = 1400;

    //! [0]
    // In the following we will make an encoder/decoder factory.
    // The factories are used to build actual encoders/decoders
    kodocpp::encoder_factory encoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::encoder encoder = encoder_factory.build();

    kodocpp::decoder_factory decoder_factory(
        kodocpp::codec::full_vector,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::decoder decoder1 = decoder_factory.build();
    kodocpp::decoder decoder2 = decoder_factory.build();
    //! [1]

    std::vector<uint8_t> payload(encoder.payload_size());
    std::vector<uint8_t> data_in(encoder.block_size());
    // Just for fun - fill the data 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_const_symbols(data_in.data(), encoder.block_size());
    // Create a buffer which will contain the decoded data, and we assign
    // that buffer to the decoder
    std::vector<uint8_t> data_out1(decoder1.block_size());
    std::vector<uint8_t> data_out2(decoder2.block_size());
    decoder1.set_mutable_symbols(data_out1.data(), decoder1.block_size());
    decoder2.set_mutable_symbols(data_out2.data(), decoder2.block_size());

    uint32_t encoded_count = 0;
    uint32_t dropped_count = 0;

    // We switch any systematic operations off so the encoder produces
    // coded symbols from the beginning
    if (encoder.is_systematic_on())
        encoder.set_systematic_off();

    //! [2]
    while (!decoder2.is_complete())
    {
        // Encode a packet into the payload buffer
        encoder.write_payload(payload.data());

        ++encoded_count;

        if (rand() % 2)
        {
            ++dropped_count;
        }
        else
        {
            // Pass that packet to the decoder1
            decoder1.read_payload(payload.data());
        }

        // Create a recoded packet from decoder1
        decoder1.write_payload(payload.data());

        if (rand() % 2)
        {
            ++dropped_count;
        }
        else
        {
            // Pass the recoded packet to decoder two
            decoder2.read_payload(payload.data());
        }
    }
    //! [3]
    std::cout << "Encoded count = " << encoded_count << std::endl;
    std::cout << "Dropped count = " << dropped_count << std::endl;

    // Check if we properly decoded the data
    if (data_in == data_out2)
    {
        std::cout << "Data decoded correctly" << std::endl;
    }

    return 0;
}
Exemple #11
0
int main()
{
    // Seed the random number generator to produce different data every time
    srand((uint32_t)time(0));

    // Set the number of symbols and the symbol size
    uint32_t max_symbols = 10;
    uint32_t max_symbol_size = 100;

    // Create encoder/decoder factories that we will use to build the actual
    // encoder and decoder
    kodocpp::encoder_factory encoder_factory(
        kodocpp::codec::sparse_seed,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::encoder encoder = encoder_factory.build();

    kodocpp::decoder_factory decoder_factory(
        kodocpp::codec::sparse_seed,
        kodocpp::field::binary8,
        max_symbols,
        max_symbol_size);

    kodocpp::decoder decoder = decoder_factory.build();

    // The coding vector density on the encoder can be set with set_density().
    // Note: the density can be adjusted at any time. This feature can be used
    // to adapt to changing network conditions.
    std::cout << "The density defaults to: " << encoder.density() << std::endl;
    encoder.set_density(0.4);
    std::cout << "The density was set to: " << encoder.density() << std::endl;
    // A low density setting can lead to a large number of redundant symbols.
    // In practice, the value should be tuned to the specific scenario.

    // Allocate some storage for a "payload" the payload is what we would
    // eventually send over a network
    std::vector<uint8_t> payload(encoder.payload_size());

    // Allocate input and output data buffers
    std::vector<uint8_t> data_in(encoder.block_size());
    std::vector<uint8_t> data_out(decoder.block_size());

    // Fill the input buffer with random data
    std::generate(data_in.begin(), data_in.end(), rand);

    // Set the symbol storage for the encoder and decoder
    encoder.set_const_symbols(data_in.data(), encoder.block_size());
    decoder.set_mutable_symbols(data_out.data(), decoder.block_size());

    // Install a custom trace function for the decoder
    auto callback = [](const std::string& zone, const std::string& data)
    {
        std::set<std::string> filters =
            {
                "decoder_state", "symbol_coefficients_before_read_symbol"
            };

        if (filters.count(zone))
        {
            std::cout << zone << ":" << std::endl;
            std::cout << data << std::endl;
        }
    };
    decoder.set_trace_callback(callback);

    uint32_t lost_payloads = 0;
    uint32_t received_payloads = 0;

    while (!decoder.is_complete())
    {
        // The encoder will use a certain amount of bytes of the payload buffer
        uint32_t bytes_used = encoder.write_payload(payload.data());
        std::cout << "Payload generated by encoder, bytes used = "
                  << bytes_used << std::endl;

        // Simulate a channel with a 50% loss rate
        if ((rand() % 2) == 0)
        {
            lost_payloads++;
            continue;
        }

        // Pass the generated packet to the decoder
        received_payloads++;
        decoder.read_payload(payload.data());
        std::cout << "Payload processed by decoder, current rank = "
                  << decoder.rank() << std::endl << std::endl;
    }

    std::cout << "Number of lost payloads: " << lost_payloads << std::endl;
    std::cout << "Number of received payloads: " << received_payloads
              << std::endl;

    // Check if we properly decoded the data
    if (data_in == data_out)
    {
        std::cout << "Data decoded correctly" << std::endl;
    }
    else
    {
        std::cout << "Unexpected failure to decode, "
                  << "please file a bug report :)" << std::endl;
    }

    return 0;
}
/// @example use_cached_symbol_decoder.cpp
///
/// This example shows how to use the cached symbol decoder to "extract"
/// the symbol coding coefficients and the encoded symbol data from an
/// incoming symbol.
int main()
{
    // The finite field we will use in the example. You can try
    // with other fields by specifying e.g. fifi::binary8 for the
    // extension field 2^8
    typedef fifi::binary finite_field;

    // Set the number of symbols (i.e. the generation size in RLNC
    // terminology) and the size of a symbol in bytes
    uint32_t symbols = 8;
    uint32_t symbol_size = 160;

    // Typdefs for the encoder/decoder type we wish to use
    typedef kodo::full_rlnc_encoder<finite_field> rlnc_encoder;
    typedef kodo::full_rlnc_decoder<finite_field> rlnc_decoder;

    typedef kodo::symbol_info_decoder<finite_field> rlnc_info_decoder;

    // In the following we will make an encoder/decoder factory.
    // The factories are used to build actual encoders/decoders.
    // Each stack we use have their own factories.
    rlnc_encoder::factory encoder_factory(symbols, symbol_size);
    auto encoder = encoder_factory.build();

    rlnc_decoder::factory decoder_factory(symbols, symbol_size);
    auto decoder = decoder_factory.build();

    rlnc_info_decoder::factory info_decoder_factory(symbols, symbol_size);
    auto info_decoder = info_decoder_factory.build();

    // Allocate some storage for a "payload" the payload is what we would
    // eventually send over a network
    std::vector<uint8_t> payload(encoder->payload_size());

    // Allocate some data to encode. In this case we make a buffer
    // with the same size as the encoder's block size (the max.
    // amount a single encoder can encode)
    std::vector<uint8_t> data_in(encoder->block_size());

    // Just for fun - fill the data with random data
    for(auto &e: data_in)
        e = rand() % 256;

    // Assign the data buffer to the encoder so that we may start
    // to produce encoded symbols from it
    encoder->set_symbols(sak::storage(data_in));

    while( !decoder->is_complete())
    {
        // Encode a packet into the payload buffer
        encoder->encode( &payload[0] );

        // Here we "simulate" a packet loss of approximately 50%
        // by dropping half of the encoded packets.
        // When running this example you will notice that the initial
        // symbols are received systematically (i.e. uncoded). After
        // sending all symbols once uncoded, the encoder will switch
        // to full coding, in which case you will see the full encoding
        // vectors being sent and received.
        if((rand() % 2) == 0)
            continue;

        // Pass the encoded packet to the info decoder. After this
        // information about the coded symbol can be fetched using the
        // cached_symbol_decoder API
        info_decoder->decode( &payload[0] );

        if(!info_decoder->cached_symbol_coded())
        {
            // The symbol was uncoded so we may ask the cache which of the
            // original symbols we have received.

            std::cout << "Symbol was uncoded, index = "
                      << info_decoder->cached_symbol_index() << std::endl;

            // Now we pass the data directly into our actual decoder. This is
            // done using the "Codec API" directly, and not through the "Payload
            // API" as we would typically do.
            decoder->decode_symbol( info_decoder->cached_symbol_data(),
                                    info_decoder->cached_symbol_index());

        }
        else
        {
            // The symbol was coded so we may ask the cache to return
            // the coding coefficients used to create the encoded symbol.

            std::cout << "Symbol was coded, encoding vector = ";

            const uint8_t* c = info_decoder->cached_symbol_coefficients();

            // We loop through the coefficient buffer and print the coefficients
            for(uint32_t i = 0; i < info_decoder->symbols(); ++i)
            {
                std::cout << (uint32_t) fifi::get_value<finite_field>(c, i)
                          << " ";
            }

            std::cout << std::endl;

            // Pass that packet to the decoder, as with the uncoded symbols
            // above we pass it directly to the "Codec API"
            decoder->decode_symbol(info_decoder->cached_symbol_data(),
                                   info_decoder->cached_symbol_coefficients());

        }
    }

    // The decoder is complete, now copy the symbols from the decoder
    std::vector<uint8_t> data_out(decoder->block_size());
    decoder->copy_symbols(sak::storage(data_out));

    // Check we properly decoded the data
    if (std::equal(data_out.begin(), data_out.end(), data_in.begin()))
    {
        std::cout << "Data decoded correctly" << std::endl;
    }
    else
    {
        std::cout << "Unexpected failure to decode "
                  << "please file a bug report :)" << std::endl;
    }
}
Exemple #13
0
// Tests that encoding and decoding a file withe the file encoder
// works.
TEST(TestFileEncoder, test_file_encoder)
{

    {
        std::string encode_filename = "encode-file";
        std::string decode_filename = "decode-file";

        // Write a test file
        std::ofstream encode_file;
        encode_file.open (encode_filename, std::ios::binary);

        uint32_t size = 500;
        for(uint32_t i = 0; i < size; ++i)
        {
            char c = rand() % 255;
            encode_file.write(&c, 1);
        }

        encode_file.close();

        typedef kodo::full_rlnc_encoder<fifi::binary>
            encoder_t;

        typedef kodo::full_rlnc_decoder<fifi::binary>
            decoder_t;

        typedef kodo::file_encoder<encoder_t>
            file_encoder_t;

        typedef kodo::object_decoder<decoder_t>
            object_decoder_t;

        uint32_t max_symbols = 10;
        uint32_t max_symbol_size = 10;

        file_encoder_t::factory encoder_factory(
            max_symbols, max_symbol_size);

        file_encoder_t file_encoder(encoder_factory, encode_filename);

        object_decoder_t::factory decoder_factory(
            max_symbols, max_symbol_size);

        object_decoder_t object_decoder(decoder_factory, size);

        EXPECT_EQ(object_decoder.decoders(), file_encoder.encoders());

        // Open the decode file
        std::ofstream decode_file;
        decode_file.open (decode_filename, std::ios::binary);

        for(uint32_t i = 0; i < file_encoder.encoders(); ++i)
        {
            auto encoder = file_encoder.build(i);
            auto decoder = object_decoder.build(i);

            EXPECT_EQ(encoder->symbols(), decoder->symbols());
            EXPECT_EQ(encoder->symbol_size(), decoder->symbol_size());
            EXPECT_EQ(encoder->bytes_used(), decoder->bytes_used());

            // Set the encoder non-systematic
            if(kodo::is_systematic_encoder(encoder))
                kodo::set_systematic_off(encoder);

            std::vector<uint8_t> payload(encoder->payload_size());

            while( !decoder->is_complete() )
            {
                // Encode a packet into the payload buffer
                encoder->encode( &payload[0] );

                // Pass that packet to the decoder
                decoder->decode( &payload[0] );
            }

            std::vector<uint8_t> data_out(decoder->block_size());
            decoder->copy_symbols(sak::storage(data_out));

            decode_file.write(
                reinterpret_cast<char*>(&data_out[0]), decoder->bytes_used());

        }

        decode_file.close();

    }

}