1 /** \file null_fec.c \brief Compact No-Code FEC
2 *
3 * $Author: peltotal $ $Date: 2007/02/28 08:58:00 $ $Revision: 1.33 $
4 *
5 * MAD-ALCLIB: Implementation of ALC/LCT protocols, Compact No-Code FEC,
6 * Simple XOR FEC, Reed-Solomon FEC, and RLC Congestion Control protocol.
7 * Copyright (c) 2003-2007 TUT - Tampere University of Technology
8 * main authors/contacts: jani.peltotalo@tut.fi and sami.peltotalo@tut.fi
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * In addition, as a special exception, TUT - Tampere University of Technology
25 * gives permission to link the code of this program with the OpenSSL library (or
26 * with modified versions of OpenSSL that use the same license as OpenSSL), and
27 * distribute linked combinations including the two. You must obey the GNU
28 * General Public License in all respects for all of the code used other than
29 * OpenSSL. If you modify this file, you may extend this exception to your version
30 * of the file, but you are not obligated to do so. If you do not wish to do so,
31 * delete this exception statement from your version.
32 */
33
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <math.h>
37 #include <memory.h>
38 #include <assert.h>
39
40 #include "null_fec.h"
41
null_fec_encode_src_block(char * data,unsigned long long len,unsigned int sbn,unsigned short es_len)42 trans_block_t* null_fec_encode_src_block(char *data, unsigned long long len,
43 unsigned int sbn, unsigned short es_len) {
44
45 trans_block_t *tr_block; /* transport block struct */
46 trans_unit_t *tr_unit; /* transport unit struct */
47 unsigned int nb_of_units; /* number of units */
48 unsigned int i; /* loop variables */
49 unsigned long long data_left;
50 char *ptr; /* pointer to left data */
51
52 data_left = len;
53
54 nb_of_units = (unsigned int)ceil((double)(unsigned int)len / (double)es_len);
55
56 tr_block = create_block();
57
58 if(tr_block == NULL) {
59 return tr_block;
60 }
61
62 tr_unit = create_units(nb_of_units);
63
64 if(tr_unit == NULL) {
65 free(tr_block);
66 return NULL;
67 }
68
69 ptr = data;
70
71 tr_block->unit_list = tr_unit;
72 tr_block->sbn = sbn;
73 tr_block->n = nb_of_units;
74 tr_block->k = nb_of_units;
75
76 for(i = 0; i < nb_of_units; i++) {
77 tr_unit->esi = i;
78 tr_unit->len = data_left < es_len ? (unsigned short)data_left : es_len; /*min(eslen, data_left);*/
79
80 /* Alloc memory for TU data */
81 if(!(tr_unit->data = (char*)calloc(tr_unit->len, sizeof(char)))) {
82 printf("Could not alloc memory for transport unit's data!\n");
83
84 tr_unit = tr_block->unit_list;
85
86 while(tr_unit != NULL) {
87 free(tr_unit->data);
88 tr_unit++;
89 }
90
91 free(tr_block->unit_list);
92 free(tr_block);
93 return NULL;
94 }
95
96 memcpy(tr_unit->data, ptr, tr_unit->len);
97
98 ptr += tr_unit->len;
99 data_left -= tr_unit->len;
100 tr_unit++;
101 }
102
103 return tr_block;
104 }
105
null_fec_decode_src_block(trans_block_t * tr_block,unsigned long long * block_len,unsigned short eslen)106 char *null_fec_decode_src_block(trans_block_t *tr_block, unsigned long long *block_len,
107 unsigned short eslen) {
108
109 char *buf = NULL; /* buffer where to construct the source block from data units */
110
111 trans_unit_t *next_tu;
112 trans_unit_t *tu;
113
114 unsigned long long len;
115 unsigned long long tmp;
116
117 len = eslen*tr_block->k;
118
119 /* Allocate memory for buf */
120 if(!(buf = (char*)calloc((unsigned int)(len + 1), sizeof(char)))) {
121 printf("Could not alloc memory for buf!\n");
122 return NULL;
123 }
124
125 tmp = 0;
126
127 next_tu = tr_block->unit_list;
128
129 while(next_tu != NULL) {
130
131 tu = next_tu;
132
133 /*if(tu->data == NULL) {
134 printf("SB: %i, esi: %i\n", tr_block->sbn, tu->esi);
135 fflush(stdout);
136 }*/
137
138 memcpy((buf+(unsigned int)tmp), tu->data, tu->len);
139
140 #ifndef USE_RETRIEVE_UNIT
141 free(tu->data);
142 tu->data = NULL;
143 #endif
144
145 tmp += tu->len;
146
147 next_tu = tu->next;
148 }
149
150 *block_len = len;
151
152 return buf;
153 }
154
null_fec_decode_object(trans_obj_t * to,unsigned long long * data_len,alc_session_t * s)155 char *null_fec_decode_object(trans_obj_t *to, unsigned long long *data_len,
156 alc_session_t *s) {
157
158 char *object = NULL;
159 char *block = NULL;
160
161 trans_block_t *tb;
162
163 unsigned long long to_data_left;
164 unsigned long long len;
165 unsigned long long block_len;
166 unsigned long long position;
167 unsigned int i;
168
169 /* Allocate memory for buf */
170 if(!(object = (char*)calloc((unsigned int)(to->len+1), sizeof(char)))) {
171 printf("Could not alloc memory for buf!\n");
172 *data_len = 0;
173 return NULL;
174 }
175
176 to_data_left = to->len;
177
178 tb = to->block_list;
179 position = 0;
180
181 for(i = 0; i < to->bs->N; i++) {
182 block = null_fec_decode_src_block(tb, &block_len, (unsigned short)to->es_len);
183
184 /* the last packet of the last source block might be padded with zeros */
185 len = to_data_left < block_len ? to_data_left : block_len;
186
187 assert (0 <= position);
188 assert (position < to->len+1);
189 assert (len <= (to->len-position));
190
191 memcpy(object+(unsigned int)position, block, (unsigned int)len);
192 position += len;
193 to_data_left -= len;
194
195 free(block);
196 tb = to->block_list+(i+1);
197 }
198
199 *data_len = to->len;
200
201 return object;
202 }
203