Пример #1
0
inline void test_decoder_symbol_status_api(int32_t decoder_type)
{
    uint32_t symbols = 4;
    uint32_t symbol_size = 40;
    kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(
        decoder_type, kodoc_binary8, symbols, symbol_size);

    kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory);

    std::vector<uint8_t> data_out(kodoc_block_size(decoder), '\0');
    kodoc_set_mutable_symbols(decoder, data_out.data(), data_out.size());

    std::vector<uint8_t> symbol(kodoc_symbol_size(decoder));
    std::vector<uint8_t> coefficients(kodoc_coefficient_vector_size(decoder));

    coefficients = {1, 0, 0, 0};
    kodoc_read_symbol(decoder, symbol.data(), coefficients.data());

    EXPECT_EQ(0U, kodoc_symbols_uncoded(decoder));

    kodoc_update_symbol_status(decoder);

    EXPECT_EQ(1U, kodoc_symbols_uncoded(decoder));

    kodoc_set_status_updater_on(decoder);

    coefficients = {0, 1, 0, 0};
    kodoc_read_symbol(decoder, symbol.data(), coefficients.data());

    EXPECT_EQ(2U, kodoc_symbols_uncoded(decoder));

    kodoc_set_status_updater_off(decoder);

    kodoc_delete_coder(decoder);
    kodoc_delete_factory(decoder_factory);
}
Пример #2
0
static void test_decoder(uint32_t symbols, uint32_t symbol_size,
                         int32_t codec, int32_t finite_field)
{
    kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(
        codec, finite_field, symbols, symbol_size);

    kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory);

    // Coder methods
    test_coder(decoder, symbols, symbol_size, codec);

    // Decoder methods
    // Some codecs do not provide write_payload, i.e. recoding
    if (codec == kodoc_seed || codec == kodoc_sparse_seed ||
        codec == kodoc_fulcrum || codec == kodoc_reed_solomon)
    {
        EXPECT_TRUE(kodoc_has_write_payload(decoder) == 0);
    }
    else
    {
        EXPECT_TRUE(kodoc_has_write_payload(decoder) != 0);
    }

    EXPECT_EQ(0U, kodoc_symbols_uncoded(decoder));
    EXPECT_EQ(0U, kodoc_symbols_partially_decoded(decoder));

    if (codec == kodoc_on_the_fly ||
        codec == kodoc_sliding_window)
    {
        EXPECT_TRUE(kodoc_has_partial_decoding_interface(decoder) != 0);
    }
    else if (codec == kodoc_full_vector)
    {
        EXPECT_TRUE(kodoc_has_partial_decoding_interface(decoder) == 0);
    }

    kodoc_delete_coder(decoder);
    kodoc_delete_factory(decoder_factory);
}
Пример #3
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);
}
Пример #4
0
int main()
{
    // Seed random number generator to produce different results every time
    srand(time(NULL));

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

    int32_t codec = kodoc_full_vector;
    int32_t finite_field = kodoc_binary8;

    // In the following we will make an encoder/decoder factory.
    // The factories are used to build actual encoders/decoder
    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);

    // If we wanted to build an encoder or decoder with a smaller number of
    // symbols or a different symbol size, then this can be adjusted using the
    // following functions:
    //      kodoc_factory_set_symbols(...)
    //      kodoc_factory_set_symbol_size(...)
    // We cannot exceed the maximum values which was used when building
    // the factory.
    kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory);
    kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory);

    // Allocate some storage for a "payload" the payload is what we would
    // eventually send over a network
    uint32_t payload_size = kodoc_payload_size(encoder);
    uint8_t* payload = (uint8_t*) malloc(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)
    uint32_t block_size = kodoc_block_size(encoder);
    uint8_t* data_in = (uint8_t*) malloc(block_size);

    // Just for fun - fill the data with random data
    uint32_t i = 0;
    for (; i < block_size; ++i)
    {
        data_in[i] = rand() % 256;
    }

    kodoc_set_const_symbols(encoder, data_in, block_size);

    uint8_t* data_out = (uint8_t*) malloc(block_size);
    kodoc_set_mutable_symbols(decoder, data_out, block_size);

    printf("Starting encoding / decoding\n");
    while (!kodoc_is_complete(decoder))
    {
        // If the chosen codec stack supports systematic coding
        if (kodoc_has_systematic_interface(encoder))
        {
            // With 50% probability toggle systematic
            if ((rand() % 2) == 0)
            {
                if (kodoc_is_systematic_on(encoder))
                {
                    printf("Turning systematic OFF\n");
                    kodoc_set_systematic_off(encoder);
                }
                else
                {
                    printf("Turn systematic ON\n");
                    kodoc_set_systematic_on(encoder);
                }
            }
        }

        // Encode a packet into the payload buffer
        kodoc_write_payload(encoder, payload);

        if ((rand() % 2) == 0)
        {
            printf("Drop packet\n");
            continue;
        }

        // Pass that packet to the decoder
        kodoc_read_payload(decoder, payload);

        printf("Rank of decoder %d\n", kodoc_rank(decoder));

        // Symbols that were received in the systematic phase correspond
        // to the original source symbols and are therefore marked as
        // decoded
        printf("Symbols decoded %d\n", kodoc_symbols_uncoded(decoder));
    }

    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(data_in);
    free(payload);

    kodoc_delete_coder(encoder);
    kodoc_delete_coder(decoder);

    kodoc_delete_factory(encoder_factory);
    kodoc_delete_factory(decoder_factory);

    return 0;
}
Пример #5
0
int main()
{
    // Seed random number generator to produce different results every time
    srand(time(NULL));

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

    int32_t codec = kodoc_sliding_window;
    int32_t finite_field = kodoc_binary8;

    // In the following we will make an encoder/decoder factory.
    // The factories are used to build actual encoders/decoders
    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);

    // If we wanted to build an encoder or decoder with a smaller number of
    // symbols or a different symbol size, then this can be adjusted using the
    // following functions:
    //      kodoc_factory_set_symbols(...)
    //      kodoc_factory_set_symbol_size(...)
    // We cannot exceed the maximum values which was used when building
    // the factory.
    kodoc_coder_t encoder = kodoc_factory_build_coder(encoder_factory);
    kodoc_coder_t decoder = kodoc_factory_build_coder(decoder_factory);

    // Allocate some storage for a "payload" the payload is what we would
    // eventually send over a network
    uint32_t payload_size = kodoc_payload_size(encoder);
    uint8_t* payload = (uint8_t*) malloc(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)
    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);
    kodoc_set_mutable_symbols(decoder, data_out, block_size);

    uint8_t feedback_size = (uint8_t) kodoc_feedback_size(encoder);
    uint8_t* feedback = (uint8_t*) malloc(feedback_size);

    uint32_t i = 0;

    //Just for fun - fill data_in with random data
    for (; i < block_size; ++i)
    {
        data_in[i] = rand() % 256;
    }

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

    while (!kodoc_is_complete(decoder))
    {
        // Insert a new symbol until the encoder is full
        if (kodoc_rank(encoder) < max_symbols)
        {
            uint32_t rank = kodoc_rank(encoder);
            uint8_t* symbol = data_in + (rank * max_symbol_size);
            kodoc_set_const_symbol(encoder, rank, symbol, max_symbol_size);
            printf("Symbol %d added to the encoder\n", rank);
        }

        // Only send packets if the encoder has more data than the decoder
        if (kodoc_rank(encoder) == kodoc_rank(decoder))
        {
            continue;
        }

        // Write an encoded packet into the payload buffer
        kodoc_write_payload(encoder, payload);
        printf("Encoded packet generated\n");

        // Here we simulate that we are losing 50% of the packets
        if (rand() % 2)
        {
            printf("Packet dropped on channel\n\n");
            continue;
        }

        printf("Decoder received packet\n");

        // Packet got through - pass that packet to the decoder
        kodoc_read_payload(decoder, payload);

        printf("Encoder rank = %d\n", kodoc_rank(encoder));
        printf("Decoder rank = %d\n", kodoc_rank(decoder));

        printf("Decoder uncoded = %d\n", kodoc_symbols_uncoded(decoder));
        printf("Decoder partially decoded = %d\n",
               kodoc_symbols_partially_decoded(decoder));

        // Transmit the feedback
        kodoc_write_feedback(decoder, feedback);

        // Note that the feedback packets can also be lost in a real network,
        // but here we deliver all of them for the sake of simplicity
        printf("Received feedback from decoder\n\n");
        kodoc_read_feedback(encoder, feedback);
    }

    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(data_in);
    free(data_out);
    free(payload);
    free(feedback);

    kodoc_delete_coder(encoder);
    kodoc_delete_coder(decoder);

    kodoc_delete_factory(encoder_factory);
    kodoc_delete_factory(decoder_factory);

    return 0;
}
Пример #6
0
void test_on_the_fly(uint32_t max_symbols, uint32_t max_symbol_size,
                     int32_t finite_field)
{
    kodoc_factory_t encoder_factory = kodoc_new_encoder_factory(
                                          kodoc_on_the_fly, finite_field, max_symbols, max_symbol_size);

    kodoc_factory_t decoder_factory = kodoc_new_decoder_factory(
                                          kodoc_on_the_fly, 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);

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

    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);

    for (uint32_t i = 0; i < block_size; ++i)
        data_in[i] = rand() % 256;

    kodoc_set_mutable_symbols(decoder, data_out, block_size);

    EXPECT_TRUE(kodoc_is_complete(decoder) == 0);

    while (!kodoc_is_complete(decoder))
    {
        EXPECT_GE(kodoc_rank(encoder), kodoc_rank(decoder));

        // The rank of an encoder indicates how many symbols have been added,
        // i.e. how many symbols are available for encoding
        uint32_t encoder_rank = kodoc_rank(encoder);

        // Randomly choose to add a new symbol (with 50% probability)
        // if the encoder rank is less than the maximum number of symbols
        if ((rand() % 2) && encoder_rank < kodoc_symbols(encoder))
        {
            // Calculate the offset to the next symbol to insert
            uint8_t* symbol = data_in + (encoder_rank * symbol_size);
            kodoc_set_const_symbol(encoder, encoder_rank, symbol, symbol_size);
        }
        // Generate an encoded packet
        kodoc_write_payload(encoder, payload);

        // Simulate that 50% of the packets are lost
        if (rand() % 2) continue;

        // Packet got through - pass that packet to the decoder
        kodoc_read_payload(decoder, payload);

        // Check the decoder rank and symbol counters
        EXPECT_GE(kodoc_rank(encoder), kodoc_rank(decoder));
        EXPECT_GE(kodoc_rank(decoder), kodoc_symbols_uncoded(decoder));
        EXPECT_GE(kodoc_rank(decoder), kodoc_symbols_partially_decoded(decoder));
        EXPECT_EQ(kodoc_symbols(decoder) - kodoc_rank(decoder),
                  kodoc_symbols_missing(decoder));

        // Check the decoder whether it is partially complete
        // The decoder has to support the partial decoding tracker
        if (kodoc_has_partial_decoding_interface(decoder) &&
                kodoc_is_partially_complete(decoder))
        {
            for (uint32_t i = 0; i < kodoc_symbols(decoder); ++i)
            {
                // Go through all symbols that are already decoded
                if (kodoc_is_symbol_uncoded(decoder, i))
                {
                    // All uncoded symbols must have a pivot
                    EXPECT_TRUE(kodoc_is_symbol_pivot(decoder, i) != 0);
                    // The uncoded symbols cannot be missing
                    EXPECT_TRUE(kodoc_is_symbol_missing(decoder, i) == 0);
                    // The uncoded symbols cannot be partially decoded
                    EXPECT_TRUE(
                        kodoc_is_symbol_partially_decoded(decoder, i) == 0);

                    uint8_t* original = data_in + i * symbol_size;
                    uint8_t* target = data_out + i * symbol_size;

                    // verify the decoded symbol against the original data
                    EXPECT_EQ(memcmp(original, target, symbol_size), 0);
                }
            }
        }
    }

    EXPECT_EQ(memcmp(data_in, data_out, block_size), 0);

    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);
}