source: roaraudio/roard/codecfilter_speex.c @ 618:54c999bd8696

Last change on this file since 618:54c999bd8696 was 618:54c999bd8696, checked in by phi, 16 years ago

use local vars in host order, not network byte order ;)

File size: 7.2 KB
Line 
1//codecfilter_speex.c:
2
3#include "roard.h"
4#ifdef ROAR_HAVE_LIBSPEEX
5
6int cf_speex_open(CODECFILTER_USERDATA_T * inst, int codec,
7                                            struct roar_stream_server * info,
8                                            struct roar_codecfilter   * filter) {
9 struct codecfilter_speex_inst * self = malloc(sizeof(struct codecfilter_speex_inst));
10 struct roar_stream * s = ROAR_STREAM(info);
11
12 *inst = NULL;
13
14 if (!self)
15  return -1;
16
17 self->encoder = NULL;
18 self->decoder = NULL;
19
20 self->stream  = info;
21
22 self->cd      = NULL;
23
24 self->i_rest  = NULL;
25 self->fi_rest = 0;
26 self->o_rest  = NULL;
27 self->fo_rest = 0;
28
29 speex_bits_init(&(self->bits));
30
31 s->info.codec    = ROAR_CODEC_DEFAULT;
32 s->info.bits     = 16; // speex hardcoded
33 s->info.channels =  1; // only mono support at the moment
34
35 *inst = (void*) self;
36
37 return 0;
38}
39
40int cf_speex_close(CODECFILTER_USERDATA_T   inst) {
41 struct codecfilter_speex_inst * self = (struct codecfilter_speex_inst *) inst;
42
43 if (!self)
44  return -1;
45
46 if ( self->encoder )
47  speex_encoder_destroy(self->encoder);
48
49 self->encoder = NULL;
50
51 if ( self->decoder )
52  speex_decoder_destroy(self->decoder);
53
54 self->decoder = NULL;
55
56 speex_bits_destroy(&(self->bits));
57
58 if ( self->cd )
59  free(self->cd);
60
61 if ( self->i_rest )
62  free(self->i_rest);
63
64 free((void*)self);
65
66 return 0;
67}
68
69int cf_speex_read(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
70 struct codecfilter_speex_inst * self = (struct codecfilter_speex_inst *) inst;
71 int mode;
72 uint16_t ui;
73 int tmp;
74 int still_todo = len / 2 /* 16 bit */;
75 int ret = 0;
76 int fs2; // = self->frame_size * 2;
77 char magic[ROAR_SPEEX_MAGIC_LEN];
78
79 ROAR_DBG("cf_speex_read(inst=%p, buf=%p, len=%i) = ?", inst, buf, len);
80
81 if ( ! self->decoder ) {
82  ROAR_DBG("cf_speex_read(*): no decoder, starting one!");
83
84  if ( stream_vio_s_read(self->stream, magic, ROAR_SPEEX_MAGIC_LEN) != ROAR_SPEEX_MAGIC_LEN )
85   return 0;
86
87  if ( memcmp(magic, ROAR_SPEEX_MAGIC, ROAR_SPEEX_MAGIC_LEN) != 0 )
88   return -1;
89
90  if ( stream_vio_s_read(self->stream, &ui, 2) != 2 )
91   return 0;
92
93  mode = ntohs(ui);
94
95  if ( mode == ROAR_SPEEX_MODE_NB ) {
96   self->decoder = speex_decoder_init(&speex_nb_mode);
97  } else if ( mode == ROAR_SPEEX_MODE_WB ) {
98   self->decoder = speex_decoder_init(&speex_wb_mode);
99  } else if ( mode == ROAR_SPEEX_MODE_UWB ) {
100   self->decoder = speex_decoder_init(&speex_uwb_mode);
101  } else {
102   return 0;
103  }
104
105  tmp=1;
106  speex_decoder_ctl(self->decoder, SPEEX_SET_ENH, &tmp);
107
108  speex_decoder_ctl(self->decoder, SPEEX_GET_FRAME_SIZE, &(self->frame_size));
109
110  fs2 = self->frame_size * 2;
111
112  ROAR_DBG("cf_speex_read(*): frame_size=%i (%i bytes)", self->frame_size, fs2);
113
114  if ( !self->cd ) {
115   self->cd = malloc(fs2);
116   if ( !self->cd )
117    return 0;
118  }
119
120  if ( !self->i_rest ) {
121   self->i_rest = malloc(fs2);
122   if ( !self->i_rest )
123    return 0;
124  }
125 }
126 fs2 = self->frame_size * 2;
127
128 ROAR_DBG("cf_speex_read(*): Have a working decoder!");
129
130 ROAR_DBG("cf_speex_read(*): frame_size=%i (%i bytes)", self->frame_size, fs2);
131 ROAR_DBG("cf_speex_read(*): i_rest is %i bytes after cd", ((void*)self->i_rest - (void*)self->cd));
132
133
134 if ( self->fi_rest ) {
135  if ( self->fi_rest > (still_todo*2) ) {
136   ROAR_DBG("cf_speex_read(*): using data from input rest buffer: len=%i (no need to read new data)", self->fi_rest);
137   still_todo *= 2; // we will set this to zero one way or another,
138                    // so we don't need to care about soring a 'warong' value here.
139   memcpy(buf, self->i_rest, still_todo);
140   memmove(self->i_rest, self->i_rest + still_todo, self->fi_rest - still_todo);
141   self->fi_rest -= still_todo;
142   ret += still_todo;
143   still_todo = 0;
144  } else {
145   ROAR_DBG("cf_speex_read(*): using data from input rest buffer: len=%i", self->fi_rest);
146   memcpy(buf, self->i_rest, self->fi_rest);
147   buf += self->fi_rest;
148   still_todo -= self->fi_rest/2;
149   ret += self->fi_rest;
150   self->fi_rest = 0;
151  }
152 }
153
154 while (still_todo) {
155  ROAR_DBG("cf_speex_read(*): we sill need %i frames", still_todo);
156  if ( stream_vio_s_read(self->stream, &ui, 2) != 2 )
157   return -1;
158
159  ui = ntohs(ui);
160
161  if ( ui > ROAR_SPEEX_MAX_CC )
162   return 0;
163
164  if ( stream_vio_s_read(self->stream, self->cc, ui) != ui )
165   break;
166
167  speex_bits_read_from(&(self->bits), self->cc, ui);
168
169  speex_decode_int(self->decoder, &(self->bits), self->cd);
170
171  if ( self->frame_size > still_todo ) {
172   memcpy(buf, self->cd, still_todo*2);
173   ret += still_todo*2;
174   self->fi_rest = (self->frame_size - still_todo)*2;
175   ROAR_DBG("cf_speex_read(*): self->fi_rest=%i, off=%i", self->fi_rest, still_todo*2);
176   memcpy(self->i_rest, (self->cd)+(still_todo*2), self->fi_rest);
177   still_todo = 0;
178  } else {
179   memcpy(buf, self->cd, fs2);
180   buf        += fs2;
181   ret        += fs2;
182   still_todo -= self->frame_size;
183  }
184 }
185
186 if ( still_todo ) {
187  ROAR_DBG("cf_speex_read(*): could not read all reqquested data, returning %i byte less", still_todo*2);
188 }
189
190 ROAR_DBG("cf_speex_read(*) = %i", ret);
191
192 return ret;
193}
194
195int cf_speex_write(CODECFILTER_USERDATA_T   inst, char * buf, int len) {
196 struct codecfilter_speex_inst * self = (struct codecfilter_speex_inst *) inst;
197 uint16_t mode = ROAR_SPEEX_MODE_UWB;
198 int tmp;
199 int fs2;
200 int ret = 0;
201 int need_extra;
202
203 if ( ! self->encoder ) {
204  if ( stream_vio_s_write(self->stream, ROAR_SPEEX_MAGIC, ROAR_SPEEX_MAGIC_LEN) != ROAR_SPEEX_MAGIC_LEN )
205   return -1;
206
207  if ( mode == ROAR_SPEEX_MODE_NB ) {
208   self->encoder = speex_encoder_init(&speex_nb_mode);
209  } else if ( mode == ROAR_SPEEX_MODE_WB ) {
210   self->encoder = speex_encoder_init(&speex_wb_mode);
211  } else if ( mode == ROAR_SPEEX_MODE_UWB ) {
212   self->encoder = speex_encoder_init(&speex_uwb_mode);
213  }
214
215  mode = ROAR_HOST2NET16(mode);
216
217  if ( stream_vio_s_write(self->stream, &mode, 2) != 2 )
218   return -1;
219
220  tmp = 8;
221  speex_encoder_ctl(self->encoder, SPEEX_SET_QUALITY,    &tmp);
222  speex_encoder_ctl(self->encoder, SPEEX_GET_FRAME_SIZE, &(self->frame_size));
223
224  fs2 = self->frame_size * 2;
225
226  if ( !self->cd ) {
227   self->cd = malloc(fs2);
228   if ( !self->cd )
229    return 0;
230  }
231
232  if ( !self->o_rest ) {
233   self->o_rest = malloc(fs2);
234   if ( !self->o_rest )
235    return 0;
236  }
237 }
238
239 fs2 = self->frame_size * 2;
240
241 if ( self->fo_rest ) { // ignore the rest for the moment
242  if ( (self->fo_rest + len) > fs2 ) {
243   need_extra = fs2 - self->fo_rest;
244   memcpy(self->o_rest + self->fo_rest, buf, need_extra);
245
246   speex_bits_reset(&(self->bits));
247
248   speex_encode_int(self->encoder, (spx_int16_t *) self->o_rest, &(self->bits));
249
250   tmp = mode = speex_bits_write(&(self->bits), self->cd, fs2);
251
252   mode = ROAR_HOST2NET16(mode);
253   stream_vio_s_write(self->stream, &mode, 2);
254   if ( stream_vio_s_write(self->stream, self->cd, tmp) != tmp )
255    return -1;
256
257   buf += need_extra;
258   ret += need_extra;
259   len -= need_extra;
260   self->fo_rest = 0;
261  } else { // just add the data to o_rest
262   memcpy(self->o_rest + self->fo_rest, buf, len);
263   self->fo_rest += len;
264   return len;
265  }
266 }
267
268 // TODO: do we realy need such a loop?
269 while (len > fs2) {
270  ROAR_WARN("cf_speex_write(*): Discarding a full block of data as non-o_rest encoding is not supported!");
271  len -= fs2;
272  buf += fs2;
273  ret += fs2;
274 }
275
276 if ( len ) { // we still have some data, add this to o_rest
277  memcpy(self->o_rest, buf, len);
278  self->fo_rest = len;
279  ret += len;
280 }
281
282 return ret;
283}
284
285#endif
286
287//ll
Note: See TracBrowser for help on using the repository browser.