xor_fec.c

Go to the documentation of this file.
00001 
00034 #include <stdlib.h>
00035 #include <stdio.h>
00036 #include <math.h>
00037 #include <memory.h>
00038 
00039 #include "xor_fec.h"
00040 
00041 trans_block_t* xor_fec_encode_src_block(char *data, unsigned long long len,
00042                                                                                 unsigned int sbn, unsigned short es_len) {
00043                 
00044         trans_block_t *tr_block;                /* transport block struct */
00045         trans_unit_t *tr_unit;                  /* transport unit struct */
00046         unsigned int nb_of_units;               /* number of units */
00047 
00048         unsigned int i;                                 /* loop variables */
00049         unsigned long long data_left;
00050 
00051         char *ptr;                                      /* pointer to left data */
00052         char *parity_symb;
00053     char *padded_symb;
00054         int j;
00055 
00056         data_left = len;
00057 
00058     parity_symb = (char*)calloc(es_len, sizeof(char));
00059         padded_symb = (char*)calloc(es_len, sizeof(char));
00060 
00061         nb_of_units = (unsigned int)ceil((double)(unsigned int)len / (double)es_len);
00062 
00063         tr_block = create_block();
00064 
00065         if(tr_block == NULL) {
00066                 return tr_block;
00067         }
00068 
00069         tr_unit = create_units(nb_of_units + 1); /* One parity symbol */
00070 
00071         if(tr_unit == NULL) {
00072                 free(tr_block);
00073                 return NULL;
00074         }
00075 
00076         ptr = data;
00077 
00078         tr_block->unit_list = tr_unit;
00079         tr_block->sbn = sbn;
00080     tr_block->k = nb_of_units;
00081         tr_block->n = nb_of_units + 1;
00082                 
00083         for(i = 0; i < nb_of_units; i++) {
00084 
00085                 tr_unit->esi = i;
00086                 tr_unit->len = data_left < es_len ? (unsigned short)data_left : es_len; /*min(es_len, data_left);*/
00087 
00088                 /* Alloc memory for TU data */
00089                 if(!(tr_unit->data = (char*)calloc(tr_unit->len, sizeof(char)))) {
00090                         printf("Could not alloc memory for transport unit's data!\n");
00091                         
00092                         tr_unit = tr_block->unit_list;  
00093 
00094                         while(tr_unit != NULL) {
00095                                 free(tr_unit->data);
00096                                 tr_unit++;
00097                         }
00098         
00099                         free(tr_block->unit_list);
00100                         free(tr_block);
00101                         free(parity_symb);
00102                         free(padded_symb);
00103                         return NULL;
00104                 }
00105 
00106                 memcpy(tr_unit->data, ptr, tr_unit->len);
00107 
00108                 memset(padded_symb, 0, es_len);
00109                 memcpy(padded_symb, tr_unit->data, tr_unit->len);
00110                 
00111                 if(i == 0) {
00112                         memcpy(parity_symb, tr_unit->data, tr_unit->len);
00113                 }
00114                 else {
00115                         /* We need to create the parity symbol by XORing the symbols, first symbol is not XORed. */
00116 
00117                         for(j = 0; j < es_len; j++) {
00118                                 *(parity_symb + j) = *(parity_symb + j) ^ *(padded_symb + j);
00119                         }
00120                 }
00121 
00122                 ptr += tr_unit->len;
00123                 data_left -= tr_unit->len;
00124                 tr_unit++;
00125 
00126                 if (i == (nb_of_units-1)) {
00127                         
00128                 /* Now we need to add the parity symbol to the block (XOR of all other symbols). */
00129 
00130                         tr_unit->esi = i+1;
00131                         tr_unit->len = es_len;
00132 
00133                         /* Alloc memory for TU data */
00134                         if(!(tr_unit->data = (char*)calloc(es_len, sizeof(char)))) {
00135                                 printf("Could not alloc memory for transport unit's data!\n");
00136 
00137                                 tr_unit = tr_block->unit_list;
00138 
00139                                 while(tr_unit != NULL) {
00140                                         free(tr_unit->data);
00141                                         tr_unit++;
00142                                 }
00143 
00144                                 free(tr_block->unit_list);
00145                                 free(tr_block);
00146                                 free(parity_symb);
00147                                 free(padded_symb);
00148                                 return NULL;
00149                         }
00150 
00151                         memcpy(tr_unit->data, parity_symb, es_len);
00152                 }
00153         }
00154 
00155         free(parity_symb);
00156         free(padded_symb);
00157 
00158         return tr_block;
00159 }
00160 
00161 char *xor_fec_decode_src_block(trans_block_t *tr_block, unsigned long long *block_len,
00162                                                            unsigned short es_len) {
00163 
00164   char *buf = NULL; /* buffer where to construct the source block from data units */
00165 
00166   trans_unit_t *next_tu = NULL;
00167   trans_unit_t *tu = NULL;
00168 
00169   unsigned long long len = 0;
00170   unsigned long long tmp = 0;
00171 
00172     int last_esi = -1;
00173     int missing_esi = -1;
00174     
00175     char *missing_symb = NULL;
00176     char *padded_symb = NULL;
00177     trans_unit_t *missing_unit = NULL;
00178     unsigned int j = 0;
00179 
00180     missing_symb = (char*)calloc(es_len, sizeof(char));
00181     padded_symb = (char*)calloc(es_len, sizeof(char));
00182 
00183     memset(missing_symb, 0, es_len);
00184     memset(padded_symb, 0, es_len);
00185 
00186     len = es_len*tr_block->k;
00187 
00188     /* Allocate memory for buf */
00189     if(!(buf = (char*)calloc((unsigned int)(len + 1), sizeof(char)))) {
00190         printf("Could not alloc memory for buf!\n");
00191         return NULL;
00192     }
00193 
00194     tmp = 0;
00195 
00196         /* We must first find out is there a parity symbol */
00197 
00198         next_tu = tr_block->unit_list;
00199  
00200         /* We must scroll to the last symbol */
00201 
00202         while(next_tu != NULL) {
00203 
00204                 tu = next_tu;
00205                 next_tu = tu->next;
00206         }
00207 
00208         if(tu->esi == tr_block->k) { /* There is a parity symbol */
00209                 
00210                 /* We need to find out which symbol is missing */
00211                 
00212                 next_tu = tr_block->unit_list;  
00213 
00214                 while(next_tu != NULL) {
00215 
00216                         tu = next_tu;
00217 
00218                         if((int)tu->esi != (last_esi + 1)) {
00219                                 missing_esi = (tu->esi - 1);
00220                                 break;
00221                         }
00222 
00223                         next_tu = tu->next;
00224                         last_esi = tu->esi;
00225                 }
00226 
00227                 /* Now we need to construct the missing symbol */
00228 
00229                 next_tu = tr_block->unit_list;
00230 
00231                 while(next_tu != NULL) {
00232 
00233                         tu = next_tu;
00234 
00235                         memset(padded_symb, 0, es_len);
00236                         memcpy(padded_symb, tu->data, tu->len);
00237 
00238                         for(j = 0; j < es_len; j++) {
00239                                 *(missing_symb + j) = *(missing_symb + j) ^ *(padded_symb + j);
00240                         }
00241 
00242                         next_tu = tu->next;
00243                 }
00244 
00245                 /* Now we need to create the missing unit */
00246 
00247                 missing_unit = create_units(1);
00248 
00249                 missing_unit->data = (char*)calloc(es_len, sizeof(char));
00250 
00251                 missing_unit->esi = missing_esi;
00252                 memcpy(missing_unit->data, missing_symb, es_len);               
00253                 missing_unit->len = es_len;
00254 
00255                 /* Now we need to insert the missing symbol to the block */
00256 
00257                 next_tu = tr_block->unit_list;
00258 
00259                 while(next_tu != NULL) {
00260 
00261                         tu = next_tu;
00262 
00263                         if(missing_esi == 0) { /* The first symbol was missing */
00264 
00265                                 tr_block->unit_list = missing_unit;
00266                                 missing_unit->next = tu;
00267                                 tu->prev = missing_unit;        
00268                                 break;
00269                         }
00270 
00271                         if((int)tu->esi > missing_esi) { /* It was the previous symbol which was missing */
00272 
00273                                 tu->prev->next = missing_unit;
00274                                 missing_unit->prev = tu->prev;
00275                                 missing_unit->next = tu;
00276                                 tu->prev = missing_unit;
00277                                 break;
00278                         }
00279 
00280                         next_tu = tu->next;
00281                 }
00282 
00283                 /* Now we need to remove the parity symbol from the block */
00284 
00285                 tu = tr_block->unit_list;
00286                 
00287                 for(j = 0; j < tr_block->k; j++) {
00288 
00289                         if(tu->esi == (tr_block->k - 1)) { /* Second last symbol */
00290 
00291 #ifndef USE_RETRIEVE_UNIT
00292                                 free(tu->next->data);
00293                                 free(tu->next);
00294 #else
00295                 tu->next->used = 0;
00296 #endif
00297 
00298                                 tu->next = NULL;
00299                                 break;
00300                         }
00301 
00302                         tu = tu->next;
00303                 }
00304 
00305                         next_tu = tr_block->unit_list;
00306 
00307         }
00308 
00309         next_tu = tr_block->unit_list;
00310 
00311         while(next_tu != NULL) {
00312 
00313                 tu = next_tu;
00314                 memcpy((buf+(unsigned int)tmp), tu->data, tu->len);
00315 
00316 #ifndef USE_RETRIEVE_UNIT
00317         free(tu->data);
00318         tu->data = NULL;
00319 #endif
00320                 tmp += tu->len;
00321 
00322                 next_tu = tu->next;
00323         }
00324 
00325         *block_len = len;
00326 
00327         free(missing_symb);
00328         free(padded_symb);
00329 
00330         return buf;
00331 }
00332 
00333 char *xor_fec_decode_object(trans_obj_t *to, unsigned long long *data_len, alc_session_t *s) {
00334         
00335         char *object = NULL;
00336         char *block = NULL;
00337 
00338         trans_block_t *tb;
00339 
00340         unsigned long long to_data_left;
00341         unsigned long long len;
00342         unsigned long long block_len;
00343         unsigned long long position;
00344 
00345         unsigned int i;
00346         
00347         /* Allocate memory for buf */
00348         if(!(object = (char*)calloc((unsigned int)(to->len+1), sizeof(char)))) {
00349                 printf("Could not alloc memory for buf!\n");
00350                 return NULL;
00351         }
00352         
00353         to_data_left = to->len;
00354 
00355         tb = to->block_list;
00356         position = 0;
00357         
00358         for(i = 0; i < to->bs->N; i++) {
00359 
00360                 block = xor_fec_decode_src_block(tb, &block_len, (unsigned short)to->es_len);
00361 
00362                 /* the last packet of the last source block might be padded with zeros */
00363                 len = to_data_left < block_len ? to_data_left : block_len;
00364 
00365                 memcpy(object+(unsigned int)position, block, (unsigned int)len);
00366                 position += len;
00367                 to_data_left -= len;
00368 
00369                 free(block);
00370                 tb = to->block_list+(i+1);
00371         }
00372         
00373         *data_len = to->len;
00374         return object;
00375 }
00376 

Generated on Fri Mar 9 20:08:51 2007 for MAD-FCL by  doxygen 1.5.0