Example #1
0
inline void run_test_basic_api(int32_t encoder_type, int32_t decoder_type,
                               int32_t finite_field, uint32_t symbols,
                               uint32_t symbol_size)
{
    kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(
        encoder_type, finite_field, symbols, symbol_size);

    kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(
        decoder_type, finite_field, symbols, symbol_size);

    kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory);
    kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory);

    EXPECT_EQ(symbols, kodoc_factory_max_symbols(encoder_factory));
    EXPECT_EQ(symbol_size, kodoc_factory_max_symbol_size(encoder_factory));
    EXPECT_EQ(symbols, kodoc_symbols(encoder));
    EXPECT_EQ(symbol_size, kodoc_symbol_size(encoder));

    EXPECT_EQ(symbols, kodoc_factory_max_symbols(decoder_factory));
    EXPECT_EQ(symbol_size, kodoc_factory_max_symbol_size(decoder_factory));
    EXPECT_EQ(symbols, kodoc_symbols(decoder));
    EXPECT_EQ(symbol_size, kodoc_symbol_size(decoder));

    EXPECT_EQ(symbols * symbol_size, kodoc_block_size(encoder));
    EXPECT_EQ(symbols * symbol_size, kodoc_block_size(decoder));

    EXPECT_TRUE(kodoc_factory_max_payload_size(encoder_factory) >=
                kodoc_payload_size(encoder));

    EXPECT_TRUE(kodoc_factory_max_payload_size(decoder_factory) >=
                kodoc_payload_size(decoder));

    EXPECT_EQ(kodoc_factory_max_payload_size(encoder_factory),
              kodoc_factory_max_payload_size(decoder_factory));

    if (encoder_type == kodoc_sparse_full_vector ||
        encoder_type == kodoc_sparse_seed)
    {
        // Set the coding vector density on the encoder
        kodoc_set_density(encoder, 0.2);
        EXPECT_EQ(0.2, kodoc_density(encoder));
    }

    uint32_t payload_size = kodoc_payload_size(encoder);
    uint8_t* payload = (uint8_t*) malloc(payload_size);

    uint8_t** input_symbols = NULL;
    uint8_t** output_symbols = NULL;

    // Allocate symbols in non-contiguous buffers
    input_symbols = (uint8_t**) malloc(symbols * sizeof(uint8_t*));
    output_symbols = (uint8_t**) malloc(symbols * sizeof(uint8_t*));

    for (uint32_t i = 0; i < symbols; ++i)
    {
        // Create the individual symbols for the encoder
        input_symbols[i] = (uint8_t*) malloc(symbol_size);

        // Randomize input data
        for (uint32_t j = 0; j < symbol_size; ++j)
            input_symbols[i][j] = rand() % 256;

        // Store the symbol pointer in the encoder
        kodoc_set_const_symbol(encoder, i, input_symbols[i], symbol_size);

        // Create the output symbol buffers for the decoder
        output_symbols[i] = (uint8_t*) malloc(symbol_size);

        // Specify the output buffers used for decoding
        kodoc_set_mutable_symbol(decoder, i, output_symbols[i], symbol_size);
    }

    if (kodoc_has_symbol_decoding_status_updater_interface(decoder))
    {
        EXPECT_FALSE(kodoc_is_status_updater_enabled(decoder));
        kodoc_set_status_updater_on(decoder);
        EXPECT_TRUE(kodoc_is_status_updater_enabled(decoder));
        kodoc_set_status_updater_off(decoder);
        EXPECT_FALSE(kodoc_is_status_updater_enabled(decoder));
    }
    else
    {
        EXPECT_TRUE(
            decoder_type == kodoc_fulcrum ||
            decoder_type == kodoc_reed_solomon
        );
    }

    EXPECT_TRUE(kodoc_is_complete(decoder) == 0);

    while (!kodoc_is_complete(decoder))
    {
        kodoc_write_payload(encoder, payload);
        kodoc_read_payload(decoder, payload);
    }

    EXPECT_TRUE(kodoc_is_complete(decoder) != 0);
    EXPECT_EQ(symbols, kodoc_rank(decoder));
    EXPECT_EQ(symbols, kodoc_symbols_uncoded(decoder));
    EXPECT_EQ(0U, kodoc_symbols_partially_decoded(decoder));
    EXPECT_EQ(0U, kodoc_symbols_missing(decoder));

    assert(input_symbols);
    assert(output_symbols);
    // Compare the input and output symbols one-by-one
    for (uint32_t i = 0; i < symbols; ++i)
    {
        EXPECT_EQ(memcmp(input_symbols[i], output_symbols[i], symbol_size), 0);

        free(input_symbols[i]);
        free(output_symbols[i]);
    }

    free(input_symbols);
    free(output_symbols);

    free(payload);

    kodoc_delete_coder(encoder);
    kodoc_delete_coder(decoder);

    kodoc_delete_factory(encoder_factory);
    kodoc_delete_factory(decoder_factory);
}
Example #2
0
int main()
{
    // Seed the random number generator to produce different data every time
    srand(time(NULL));

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

    // Here we select the codec we wish to use
    int32_t codec = kodoc_sparse_seed;

    // Here we select the finite field to use.
    // For the sparse seed codec, we can choose kodoc_binary, kodoc_binary4 or
    // kodoc_binary8 (kodoc_binary is recommended for high performance)
    int32_t finite_field = kodoc_binary8;

    kodoc_factory_t encoder_factory =
        kodoc_new_encoder_factory(codec, finite_field,
                                 max_symbols, max_symbol_size);

    kodoc_factory_t decoder_factory =
        kodoc_new_decoder_factory(codec, finite_field,
                                 max_symbols, max_symbol_size);

    kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory);
    kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory);

    // The coding vector density on the encoder is set with
    // kodoc_set_density().
    // Note: the density can be adjusted at any time. This feature can be used
    // to adapt to changing network conditions.
    printf("The density defaults to: %0.2f\n", kodoc_density(encoder));
    kodoc_set_density(encoder, 0.4);
    printf("The density was set to: %0.2f\n", kodoc_density(encoder));
    // 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.
    uint32_t bytes_used;
    uint32_t payload_size = kodoc_payload_size(encoder);
    uint8_t* payload = (uint8_t*) malloc(payload_size);

    // Allocate input and output data buffers
    uint32_t block_size = kodoc_block_size(encoder);
    uint8_t* data_in = (uint8_t*) malloc(block_size);
    uint8_t* data_out = (uint8_t*) malloc(block_size);

    // Fill the input buffer with random data
    uint32_t i = 0;
    for(; i < block_size; ++i)
        data_in[i] = rand() % 256;

    // Assign the data buffers to the encoder and decoder
    kodoc_set_const_symbols(encoder, data_in, block_size);
    kodoc_set_mutable_symbols(decoder, data_out, block_size);

    // Install a custom trace function for the decoder
    kodoc_set_trace_callback(decoder, trace_callback, NULL);

    uint32_t lost_payloads = 0;
    uint32_t received_payloads = 0;
    while (!kodoc_is_complete(decoder))
    {
        // The encoder will use a certain amount of bytes of the payload buffer
        bytes_used = kodoc_write_payload(encoder, payload);
        printf("Payload generated by encoder, bytes used = %d\n", bytes_used);

        // Simulate a channel with a 50% loss rate
        if (rand() % 2)
        {
            lost_payloads++;
            printf("Symbol lost on channel\n\n");
            continue;
        }

        // Pass the generated packet to the decoder
        received_payloads++;
        kodoc_read_payload(decoder, payload);
        printf("Payload processed by decoder, current rank = %d\n\n",
               kodoc_rank(decoder));
    }

    printf("Number of lost payloads: %d\n", lost_payloads);
    printf("Number of received payloads: %d\n", received_payloads);

    // Check that we properly decoded the data
    if (memcmp(data_in, data_out, block_size) == 0)
    {
        printf("Data decoded correctly\n");
    }
    else
    {
        printf("Unexpected failure to decode, please file a bug report :)\n");
    }

    // Free the allocated buffers and the kodo objects
    free(data_in);
    free(data_out);
    free(payload);

    kodoc_delete_coder(encoder);
    kodoc_delete_coder(decoder);

    kodoc_delete_factory(encoder_factory);
    kodoc_delete_factory(decoder_factory);

    return 0;
}