source: roaraudio/roard/codecfilter_speex.c @ 620:d612617809a5

Last change on this file since 620:d612617809a5 was 620:d612617809a5, checked in by phi, 16 years ago

added a bit docs

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