# Encode Decode On-the-fly¶

This example shows how to to perform on-the-fly encoding. The encoder can start to generate encoded packets from a block before all symbols are specified. This can be useful when the symbols are produced on-the-fly.

The complete example code is shown below.

  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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 // Copyright Steinwurf ApS 2018. // Distributed under the "STEINWURF EVALUATION LICENSE 1.0". // See accompanying file LICENSE.rst or // http://www.steinwurf.com/licensing #include #include #include #include #include #include #include /// @example encode_decode_on_the_fly.c /// /// This example shows how to use a storage aware encoder which will /// allow you to encode from a block before all symbols have been /// specified. This can be useful in cases where the symbols that /// should be encoded are produced on-the-fly. The decoder will also /// allow you to detect whether the symbols have been partially decoded. 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 uint32_t symbols = 10; uint32_t symbol_size = 100; // Here we select the finite field to use. // Some common choices are: krlnc_binary, krlnc_binary4, krlnc_binary8 int32_t finite_field = krlnc_binary8; krlnc_encoder_factory_t encoder_factory = krlnc_new_encoder_factory( finite_field, symbols, symbol_size); krlnc_decoder_factory_t decoder_factory = krlnc_new_decoder_factory( finite_field, symbols, symbol_size); krlnc_encoder_t encoder = krlnc_encoder_factory_build(encoder_factory); krlnc_decoder_t decoder = krlnc_decoder_factory_build(decoder_factory); uint32_t payload_size = krlnc_encoder_payload_size(encoder); uint8_t* payload = (uint8_t*)malloc(payload_size); uint32_t block_size = krlnc_encoder_block_size(encoder); uint8_t* data_in = (uint8_t*)malloc(block_size); uint8_t* data_out = (uint8_t*)malloc(block_size); krlnc_decoder_set_mutable_symbols(decoder, data_out, block_size); // Keeps track of which symbols have been decoded uint8_t* decoded = (uint8_t*)malloc(sizeof(uint8_t)*symbols); uint32_t i = 0; for (i = 0; i < block_size; ++i) data_in[i] = rand() % 256; // Zero initialize the decoded array memset(decoded, '\0', sizeof(uint8_t)*symbols); // We are starting the encoding / decoding loop without having // added any data to the encoder - we will add symbols on-the-fly while (!krlnc_decoder_is_complete(decoder)) { uint32_t bytes_used; // 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) && krlnc_encoder_rank(encoder) < symbols) { // The rank of an encoder indicates how many symbols have been added, // i.e. how many symbols are available for encoding uint32_t rank = krlnc_encoder_rank(encoder); // Calculate the offset to the next symbol to insert uint8_t* symbol = data_in + rank * symbol_size; krlnc_encoder_set_const_symbol(encoder, rank, symbol, symbol_size); } bytes_used = krlnc_encoder_write_payload(encoder, payload); printf("Payload generated by encoder, rank = %d, bytes used = %d\n", krlnc_encoder_rank(encoder), bytes_used); // Send the data to the decoders, here we just for fun // simulate that we are loosing 50% of the packets if (rand() % 2) { printf("Packet dropped\n"); continue; } // Packet got through - pass that packet to the decoder krlnc_decoder_read_payload(decoder, payload); // The rank of a decoder indicates how many symbols have been // decoded or partially decoded printf("Payload processed by decoder, current rank = %d\n", krlnc_decoder_rank(decoder)); // Check the decoder whether it is partially complete if (krlnc_decoder_is_partially_complete(decoder)) { uint32_t i = 0; for (; i < symbols; ++i) { if (!decoded[i] && krlnc_decoder_is_symbol_uncoded(decoder, i)) { uint8_t* original = data_in + i * symbol_size; uint8_t* target = data_out + i * symbol_size; // Update that this symbol now has been decoded printf("Symbol %d was decoded\n", i); decoded[i] = 1; // Verify the symbol against the original data if (memcmp(original, target, symbol_size) == 0) { printf("Symbol %d decoded correctly\n", i); } else { printf("SYMBOL %d DECODING FAILED.\n", i); } } } } } 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); krlnc_delete_encoder(encoder); krlnc_delete_decoder(decoder); krlnc_delete_encoder_factory(encoder_factory); krlnc_delete_decoder_factory(decoder_factory); return 0; }