2 mediastreamer2 library - modular sound and video processing and streaming
3 Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "mediastreamer2/msfilter.h"
22 #include <speex/speex.h>
25 #include <malloc.h> /* for alloca */
28 typedef struct SpeexEncState{
39 MSBufferizer *bufferizer;
42 static void enc_init(MSFilter *f){
43 SpeexEncState *s=(SpeexEncState *)ms_new(SpeexEncState,1);
54 s->bufferizer=ms_bufferizer_new();
58 static void enc_uninit(MSFilter *f){
59 SpeexEncState *s=(SpeexEncState*)f->data;
62 ms_bufferizer_destroy(s->bufferizer);
64 speex_encoder_destroy(s->state);
68 static void enc_preprocess(MSFilter *f){
69 SpeexEncState *s=(SpeexEncState*)f->data;
70 const SpeexMode *mode=NULL;
75 _mode = SPEEX_MODEID_NB; /* rate = 8000Hz */
78 _mode = SPEEX_MODEID_WB; /* rate = 16000Hz */
80 /* should be supported in the future */
82 _mode = SPEEX_MODEID_UWB; /* rate = 32000Hz */
85 ms_error("Unsupported rate for speex encoder (back to default rate=8000).");
88 /* warning: speex_lib_get_mode() is not available on speex<1.1.12 */
89 mode = speex_lib_get_mode(_mode);
93 s->state=speex_encoder_init(mode);
97 if (speex_encoder_ctl(s->state,SPEEX_SET_VBR,&s->vbr)!=0){
98 ms_error("Could not set vbr mode to speex encoder.");
101 speex_encoder_ctl (s->state, SPEEX_SET_DTX, &s->vbr);
107 speex_encoder_ctl (s->state, SPEEX_SET_VAD, &vad);
108 speex_encoder_ctl (s->state, SPEEX_SET_DTX, &vad);
112 speex_encoder_ctl (s->state, SPEEX_SET_VAD, &s->cng);
116 //+------+---------------+-------------+
117 //| mode | Speex quality | bit-rate |
118 //+------+---------------+-------------+
119 //| 1 | 0 | 2.15 kbit/s |
120 //| 2 | 2 | 5.95 kbit/s |
121 //| 3 | 3 or 4 | 8.00 kbit/s |
122 //| 4 | 5 or 6 | 11.0 kbit/s |
123 //| 5 | 7 or 8 | 15.0 kbit/s |
124 //| 6 | 9 | 18.2 kbit/s |
125 //| 7 | 10 | 24.6 kbit/s |
126 //| 8 | 1 | 3.95 kbit/s |
127 //+------+---------------+-------------+
128 if (s->mode<=0 || s->mode>8)
129 s->mode = 3; /* default mode */
149 if (speex_encoder_ctl(s->state,SPEEX_SET_BITRATE,&s->bitrate)!=0){
150 ms_error("Could not set bitrate %i to speex encoder.",s->bitrate);
154 else if (s->rate==16000 || s->rate==32000){
155 //+------+---------------+-------------------+------------------------+
156 //| mode | Speex quality | wideband bit-rate | ultra wideband |
158 //+------+---------------+-------------------+------------------------+
159 //| 0 | 0 | 3.95 kbit/s | 5.75 kbit/s |
160 //| 1 | 1 | 5.75 kbit/s | 7.55 kbit/s |
161 //| 2 | 2 | 7.75 kbit/s | 9.55 kbit/s |
162 //| 3 | 3 | 9.80 kbit/s | 11.6 kbit/s |
163 //| 4 | 4 | 12.8 kbit/s | 14.6 kbit/s |
164 //| 5 | 5 | 16.8 kbit/s | 18.6 kbit/s |
165 //| 6 | 6 | 20.6 kbit/s | 22.4 kbit/s |
166 //| 7 | 7 | 23.8 kbit/s | 25.6 kbit/s |
167 //| 8 | 8 | 27.8 kbit/s | 29.6 kbit/s |
168 //| 9 | 9 | 34.2 kbit/s | 36.0 kbit/s |
169 //| 10 | 10 | 42.2 kbit/s | 44.0 kbit/s |
170 //+------+---------------+-------------------+------------------------+
172 if (s->mode<0 || s->mode>10)
173 s->mode = 8; /* default mode */
175 if (speex_encoder_ctl(s->state,SPEEX_SET_QUALITY,&q)!=0){
176 ms_error("Could not set quality %i to speex encoder.",q);
180 if (s->maxbitrate>0){
181 /* convert from network bitrate to codec bitrate:*/
182 /* ((nbr/(50*8)) -20-12-8)*50*8*/
183 int cbr=(int)( ((((float)s->maxbitrate)/(50.0*8))-20-12-8)*50*8);
184 ms_message("Setting maxbitrate=%i to speex encoder.",cbr);
185 if (speex_encoder_ctl(s->state,SPEEX_SET_BITRATE,&cbr)!=0){
186 ms_error("Could not set maxbitrate %i to speex encoder.",s->bitrate);
189 if (speex_encoder_ctl(s->state,SPEEX_GET_BITRATE,&s->bitrate)!=0){
190 ms_error("Could not get bitrate %i to speex encoder.",s->bitrate);
192 else ms_message("Using bitrate %i for speex encoder.",s->bitrate);
194 speex_mode_query(mode,SPEEX_MODE_FRAME_SIZE,&s->frame_size);
197 static void enc_process(MSFilter *f){
198 SpeexEncState *s=(SpeexEncState*)f->data;
202 int frame_per_packet=1;
204 if (s->frame_size<=0)
209 frame_per_packet = s->ptime/20;
212 if (frame_per_packet<=0)
214 if (frame_per_packet>7) /* 7*20 == 140 ms max */
217 nbytes=s->frame_size*2;
218 buf=(uint8_t*)alloca(nbytes*frame_per_packet);
220 while((im=ms_queue_get(f->inputs[0]))!=NULL){
221 ms_bufferizer_put(s->bufferizer,im);
223 while(ms_bufferizer_read(s->bufferizer,buf,nbytes*frame_per_packet)==nbytes*frame_per_packet){
224 mblk_t *om=allocb(nbytes*frame_per_packet,0);//too large...
227 speex_bits_init(&bits);
228 for (k=0;k<frame_per_packet;k++)
230 speex_encode_int(s->state,(int16_t*)(buf + (k*s->frame_size*2)),&bits);
231 s->ts+=s->frame_size;
233 speex_bits_insert_terminator(&bits);
234 k=speex_bits_write(&bits, (char*)om->b_wptr, nbytes*frame_per_packet);
237 mblk_set_timestamp_info(om,s->ts-s->frame_size);
238 ms_queue_put(f->outputs[0],om);
239 speex_bits_destroy(&bits);
243 static void enc_postprocess(MSFilter *f){
244 SpeexEncState *s=(SpeexEncState*)f->data;
245 speex_encoder_destroy(s->state);
249 static int enc_set_sr(MSFilter *f, void *arg){
250 SpeexEncState *s=(SpeexEncState*)f->data;
251 /* TODO: should be done with fmtp parameter */
252 s->rate=((int*)arg)[0];
256 static int enc_set_br(MSFilter *f, void *arg){
257 SpeexEncState *s=(SpeexEncState*)f->data;
258 s->maxbitrate=((int*)arg)[0];
262 static int enc_add_fmtp(MSFilter *f, void *arg){
264 const char *fmtp=(const char *)arg;
265 SpeexEncState *s=(SpeexEncState*)f->data;
267 memset(buf, '\0', sizeof(buf));
268 fmtp_get_value(fmtp, "vbr", buf, sizeof(buf));
271 else if (strstr(buf,"off")!=NULL){
274 else if (strstr(buf,"on")!=NULL){
277 else if (strstr(buf,"vad")!=NULL){
281 memset(buf, '\0', sizeof(buf));
282 fmtp_get_value(fmtp, "cng", buf, sizeof(buf));
285 else if (strstr(buf,"off")!=NULL){
288 else if (strstr(buf,"on")!=NULL){
292 memset(buf, '\0', sizeof(buf));
293 fmtp_get_value(fmtp, "mode", buf, sizeof(buf));
294 if (buf[0]=='\0' || buf[1]=='\0'){
296 else if (buf[0]=='0' || (buf[0]=='"' && buf[1]=='0')){
299 else if (buf[0]=='"' && atoi(buf+1)>=0){
302 else if (buf[0]!='"' && atoi(buf)>=0){
306 s->mode = -1; /* deault mode */
311 static int enc_add_attr(MSFilter *f, void *arg){
312 const char *fmtp=(const char *)arg;
313 SpeexEncState *s=(SpeexEncState*)f->data;
314 if (strstr(fmtp,"ptime:10")!=NULL){
316 }else if (strstr(fmtp,"ptime:20")!=NULL){
318 }else if (strstr(fmtp,"ptime:30")!=NULL){
320 }else if (strstr(fmtp,"ptime:40")!=NULL){
322 }else if (strstr(fmtp,"ptime:50")!=NULL){
324 }else if (strstr(fmtp,"ptime:60")!=NULL){
326 }else if (strstr(fmtp,"ptime:70")!=NULL){
328 }else if (strstr(fmtp,"ptime:80")!=NULL){
330 }else if (strstr(fmtp,"ptime:90")!=NULL){
331 s->ptime=100; /* not allowed */
332 }else if (strstr(fmtp,"ptime:100")!=NULL){
334 }else if (strstr(fmtp,"ptime:110")!=NULL){
336 }else if (strstr(fmtp,"ptime:120")!=NULL){
338 }else if (strstr(fmtp,"ptime:130")!=NULL){
340 }else if (strstr(fmtp,"ptime:140")!=NULL){
346 static MSFilterMethod enc_methods[]={
347 { MS_FILTER_SET_SAMPLE_RATE , enc_set_sr },
348 { MS_FILTER_SET_BITRATE , enc_set_br },
349 { MS_FILTER_ADD_FMTP , enc_add_fmtp },
350 { MS_FILTER_ADD_ATTR , enc_add_attr},
356 MSFilterDesc ms_speex_enc_desc={
359 N_("The free and wonderful speex codec"),
374 MSFilterDesc ms_speex_enc_desc={
377 .text=N_("The free and wonderful speex codec"),
378 .category=MS_FILTER_ENCODER,
383 .preprocess=enc_preprocess,
384 .postprocess=enc_postprocess,
385 .process=enc_process,
392 typedef struct DecState{
399 static void dec_init(MSFilter *f){
400 DecState *s=(DecState *)ms_new(DecState,1);
408 static void dec_uninit(MSFilter *f){
409 DecState *s=(DecState*)f->data;
413 speex_decoder_destroy(s->state);
417 static void dec_preprocess(MSFilter *f){
418 DecState *s=(DecState*)f->data;
419 const SpeexMode *mode=NULL;
423 modeid = SPEEX_MODEID_NB; /* rate = 8000Hz */
426 modeid = SPEEX_MODEID_WB; /* rate = 16000Hz */
428 /* should be supported in the future */
430 modeid = SPEEX_MODEID_UWB; /* rate = 32000Hz */
433 ms_error("Unsupported rate for speex decoder (back to default rate=8000).");
434 modeid=SPEEX_MODEID_NB;
436 /* warning: speex_lib_get_mode() is not available on speex<1.1.12 */
437 mode = speex_lib_get_mode(modeid);
438 s->state=speex_decoder_init(mode);
439 speex_mode_query(mode,SPEEX_MODE_FRAME_SIZE,&s->frsz);
441 speex_decoder_ctl (s->state, SPEEX_SET_ENH, &s->penh);
444 static void dec_postprocess(MSFilter *f){
445 DecState *s=(DecState*)f->data;
446 speex_decoder_destroy(s->state);
450 static int dec_set_sr(MSFilter *f, void *arg){
451 DecState *s=(DecState*)f->data;
452 s->rate=((int*)arg)[0];
456 static void dec_process(MSFilter *f){
457 DecState *s=(DecState*)f->data;
461 int frame_per_packet;
464 speex_bits_init(&bits);
465 while((im=ms_queue_get(f->inputs[0]))!=NULL){
466 speex_bits_reset(&bits);
467 speex_bits_read_from(&bits,(char*)im->b_rptr,im->b_wptr-im->b_rptr);
468 om=allocb(bytes*7,0);
469 /* support for multiple frame (max=7 frames???) in one RTP packet */
470 for (frame_per_packet=0;frame_per_packet<7;frame_per_packet++)
473 err=speex_decode_int(s->state,&bits,(int16_t*)(om->b_wptr+(frame_per_packet*320)));
475 i = speex_bits_remaining(&bits);
476 if (i<10) /* this seems to work: don't know why. */
480 om->b_wptr+=bytes*(frame_per_packet+1);
481 ms_queue_put(f->outputs[0],om);
484 ms_warning("speex end of stream");
486 ms_warning("speex corrupted stream");
491 speex_bits_destroy(&bits);
494 static MSFilterMethod dec_methods[]={
495 { MS_FILTER_SET_SAMPLE_RATE , dec_set_sr },
501 MSFilterDesc ms_speex_dec_desc={
504 N_("The free and wonderful speex codec"),
519 MSFilterDesc ms_speex_dec_desc={
522 .text=N_("The free and wonderful speex codec"),
523 .category=MS_FILTER_DECODER,
528 .preprocess=dec_preprocess,
529 .postprocess=dec_postprocess,
530 .process=dec_process,
537 MS_FILTER_DESC_EXPORT(ms_speex_dec_desc)
538 MS_FILTER_DESC_EXPORT(ms_speex_enc_desc)