source: mediastreamer2/src/msspeex.c @ 1111:e207f189903a

Last change on this file since 1111:e207f189903a was 1111:e207f189903a, checked in by Simon Morlat <simon.morlat@…>, 3 years ago

implement PLC on speex decoder

File size: 13.9 KB
Line 
1/*
2mediastreamer2 library - modular sound and video processing and streaming
3Copyright (C) 2006  Simon MORLAT (simon.morlat@linphone.org)
4
5This program is free software; you can redistribute it and/or
6modify it under the terms of the GNU General Public License
7as published by the Free Software Foundation; either version 2
8of the License, or (at your option) any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18*/
19
20#include "mediastreamer2/msfilter.h"
21#include "mediastreamer2/msticker.h"
22
23#include <speex/speex.h>
24
25#ifdef WIN32
26#include <malloc.h> /* for alloca */
27#endif
28
29typedef struct SpeexEncState{
30        int rate;
31        int bitrate;
32        int maxbitrate;
33        int ptime;
34        int vbr;
35        int cng;
36        int mode;
37        int frame_size;
38        void *state;
39        uint32_t ts;
40        MSBufferizer *bufferizer;
41} SpeexEncState;
42
43static void enc_init(MSFilter *f){
44        SpeexEncState *s=(SpeexEncState *)ms_new(SpeexEncState,1);
45        s->rate=8000;
46        s->bitrate=-1;
47        s->maxbitrate=-1;
48        s->ptime=0;
49        s->mode=-1;
50        s->vbr=0;
51        s->cng=0;
52        s->frame_size=0;
53        s->state=0;
54        s->ts=0;
55        s->bufferizer=ms_bufferizer_new();
56        f->data=s;
57}
58
59static void enc_uninit(MSFilter *f){
60        SpeexEncState *s=(SpeexEncState*)f->data;
61        if (s==NULL)
62                return;
63        ms_bufferizer_destroy(s->bufferizer);
64        if (s->state!=NULL)
65                speex_encoder_destroy(s->state);
66        ms_free(s);
67}
68
69static void enc_preprocess(MSFilter *f){
70        SpeexEncState *s=(SpeexEncState*)f->data;
71        const SpeexMode *mode=NULL;
72        int _mode=0;
73
74        switch(s->rate){
75                case 8000:
76                _mode = SPEEX_MODEID_NB;    /* rate = 8000Hz */
77                        break;
78                case 16000:
79                _mode = SPEEX_MODEID_WB;    /* rate = 16000Hz */
80                        break;
81                        /* should be supported in the future */
82                case 32000:
83                _mode = SPEEX_MODEID_UWB;   /* rate = 32000Hz */
84                        break;
85                default:
86                        ms_error("Unsupported rate for speex encoder (back to default rate=8000).");
87                        s->rate=8000;
88        }
89        /* warning: speex_lib_get_mode() is not available on speex<1.1.12 */
90        mode = speex_lib_get_mode(_mode);
91
92        if (mode==NULL)
93                return;
94        s->state=speex_encoder_init(mode);
95
96        if (s->vbr==1)
97        {
98                if (speex_encoder_ctl(s->state,SPEEX_SET_VBR,&s->vbr)!=0){
99                        ms_error("Could not set vbr mode to speex encoder.");
100                }
101                /* implicit VAD */
102                speex_encoder_ctl (s->state, SPEEX_SET_DTX, &s->vbr);
103        }
104        else if (s->vbr==2)
105        {
106                int vad=1;
107                /* VAD */
108                speex_encoder_ctl (s->state, SPEEX_SET_VAD, &vad);
109                speex_encoder_ctl (s->state, SPEEX_SET_DTX, &vad);
110        }
111        else if (s->cng==1)
112        {
113                speex_encoder_ctl (s->state, SPEEX_SET_VAD, &s->cng);
114        }
115
116        if (s->rate==8000){
117                //+------+---------------+-------------+
118                //| mode | Speex quality |   bit-rate  |
119                //+------+---------------+-------------+
120                //|   1  |       0       | 2.15 kbit/s |
121                //|   2  |       2       | 5.95 kbit/s |
122                //|   3  |     3 or 4    | 8.00 kbit/s |
123                //|   4  |     5 or 6    | 11.0 kbit/s |
124                //|   5  |     7 or 8    | 15.0 kbit/s |
125                //|   6  |       9       | 18.2 kbit/s |
126                //|   7  |      10       | 24.6 kbit/s |
127                //|   8  |       1       | 3.95 kbit/s |
128                //+------+---------------+-------------+
129                if (s->mode<=0 || s->mode>8)
130                        s->mode = 3; /* default mode */
131
132                if (s->mode==1)
133                        s->bitrate = 2150;
134                else if (s->mode==2)
135                        s->bitrate = 5950;
136                else if (s->mode==3)
137                        s->bitrate = 8000;
138                else if (s->mode==4)
139                        s->bitrate = 11000;
140                else if (s->mode==5)
141                        s->bitrate = 15000;
142                else if (s->mode==6)
143                        s->bitrate = 18200;
144                else if (s->mode==7)
145                        s->bitrate = 24600;
146                else if (s->mode==8)
147                        s->bitrate = 3950;
148
149                if (s->bitrate!=-1){
150                        if (speex_encoder_ctl(s->state,SPEEX_SET_BITRATE,&s->bitrate)!=0){
151                                ms_error("Could not set bitrate %i to speex encoder.",s->bitrate);
152                        }
153                }
154        }
155        else if (s->rate==16000 || s->rate==32000){
156                //+------+---------------+-------------------+------------------------+
157                //| mode | Speex quality | wideband bit-rate |     ultra wideband     |
158                //|      |               |                   |        bit-rate        |
159                //+------+---------------+-------------------+------------------------+
160                //|   0  |       0       |    3.95 kbit/s    |       5.75 kbit/s      |
161                //|   1  |       1       |    5.75 kbit/s    |       7.55 kbit/s      |
162                //|   2  |       2       |    7.75 kbit/s    |       9.55 kbit/s      |
163                //|   3  |       3       |    9.80 kbit/s    |       11.6 kbit/s      |
164                //|   4  |       4       |    12.8 kbit/s    |       14.6 kbit/s      |
165                //|   5  |       5       |    16.8 kbit/s    |       18.6 kbit/s      |
166                //|   6  |       6       |    20.6 kbit/s    |       22.4 kbit/s      |
167                //|   7  |       7       |    23.8 kbit/s    |       25.6 kbit/s      |
168                //|   8  |       8       |    27.8 kbit/s    |       29.6 kbit/s      |
169                //|   9  |       9       |    34.2 kbit/s    |       36.0 kbit/s      |
170                //|  10  |       10      |    42.2 kbit/s    |       44.0 kbit/s      |
171                //+------+---------------+-------------------+------------------------+
172                int q=0;
173                if (s->mode<0 || s->mode>10)
174                        s->mode = 8; /* default mode */
175                q=s->mode;
176                if (speex_encoder_ctl(s->state,SPEEX_SET_QUALITY,&q)!=0){
177                        ms_error("Could not set quality %i to speex encoder.",q);
178                }
179        }
180
181        if (s->maxbitrate>0){
182                /* convert from network bitrate to codec bitrate:*/
183                /* ((nbr/(50*8)) -20-12-8)*50*8*/
184                int cbr=(int)( ((((float)s->maxbitrate)/(50.0*8))-20-12-8)*50*8);
185                ms_message("Setting maxbitrate=%i to speex encoder.",cbr);
186                if (speex_encoder_ctl(s->state,SPEEX_SET_BITRATE,&cbr)!=0){
187                        ms_error("Could not set maxbitrate %i to speex encoder.",s->bitrate);
188                }
189        }
190        if (speex_encoder_ctl(s->state,SPEEX_GET_BITRATE,&s->bitrate)!=0){
191                        ms_error("Could not get bitrate %i to speex encoder.",s->bitrate);
192        }
193        else ms_message("Using bitrate %i for speex encoder.",s->bitrate);
194
195        speex_mode_query(mode,SPEEX_MODE_FRAME_SIZE,&s->frame_size);
196}
197
198static void enc_process(MSFilter *f){
199        SpeexEncState *s=(SpeexEncState*)f->data;
200        mblk_t *im;
201        int nbytes;
202        uint8_t *buf;
203        int frame_per_packet=1;
204
205        if (s->frame_size<=0)
206                return;
207
208        if (s->ptime>=20)
209        {
210                frame_per_packet = s->ptime/20;
211        }
212
213        if (frame_per_packet<=0)
214                frame_per_packet=1;
215        if (frame_per_packet>7) /* 7*20 == 140 ms max */
216                frame_per_packet=7;
217
218        nbytes=s->frame_size*2;
219        buf=(uint8_t*)alloca(nbytes*frame_per_packet);
220
221        while((im=ms_queue_get(f->inputs[0]))!=NULL){
222                ms_bufferizer_put(s->bufferizer,im);
223        }
224        while(ms_bufferizer_read(s->bufferizer,buf,nbytes*frame_per_packet)==nbytes*frame_per_packet){
225                mblk_t *om=allocb(nbytes*frame_per_packet,0);//too large...
226                int k;
227                SpeexBits bits;
228                speex_bits_init(&bits);
229                for (k=0;k<frame_per_packet;k++)
230                {
231                        speex_encode_int(s->state,(int16_t*)(buf + (k*s->frame_size*2)),&bits);
232                        s->ts+=s->frame_size;
233                }
234                speex_bits_insert_terminator(&bits);
235                k=speex_bits_write(&bits, (char*)om->b_wptr, nbytes*frame_per_packet);
236                om->b_wptr+=k;
237
238                mblk_set_timestamp_info(om,s->ts-s->frame_size);
239                ms_queue_put(f->outputs[0],om);
240                speex_bits_destroy(&bits);
241        }
242}
243
244static void enc_postprocess(MSFilter *f){
245        SpeexEncState *s=(SpeexEncState*)f->data;
246        speex_encoder_destroy(s->state);
247        s->state=NULL;
248}
249
250static int enc_set_sr(MSFilter *f, void *arg){
251        SpeexEncState *s=(SpeexEncState*)f->data;
252        /* TODO: should be done with fmtp parameter */
253        s->rate=((int*)arg)[0];
254        return 0;
255}
256
257static int enc_set_br(MSFilter *f, void *arg){
258        SpeexEncState *s=(SpeexEncState*)f->data;
259        s->maxbitrate=((int*)arg)[0];
260        return 0;
261}
262
263static int enc_add_fmtp(MSFilter *f, void *arg){
264        char buf[64];
265        const char *fmtp=(const char *)arg;
266        SpeexEncState *s=(SpeexEncState*)f->data;
267
268        memset(buf, '\0', sizeof(buf));
269        fmtp_get_value(fmtp, "vbr", buf, sizeof(buf));
270        if (buf[0]=='\0'){
271        }
272        else if (strstr(buf,"off")!=NULL){
273                s->vbr=0;
274        }
275        else if (strstr(buf,"on")!=NULL){
276                s->vbr=1;
277        }
278        else if (strstr(buf,"vad")!=NULL){
279                s->vbr=2;
280        }
281
282        memset(buf, '\0', sizeof(buf));
283        fmtp_get_value(fmtp, "cng", buf, sizeof(buf));
284        if (buf[0]=='\0'){
285        }
286        else if (strstr(buf,"off")!=NULL){
287                s->cng=0;
288        }
289        else if (strstr(buf,"on")!=NULL){
290                s->cng=1;
291        }
292
293        memset(buf, '\0', sizeof(buf));
294        fmtp_get_value(fmtp, "mode", buf, sizeof(buf));
295        if (buf[0]=='\0' || buf[1]=='\0'){
296        }
297        else if (buf[0]=='0' || (buf[0]=='"' && buf[1]=='0')){
298                s->mode=0;
299        }
300        else if (buf[0]=='"' && atoi(buf+1)>=0){
301                s->mode=atoi(buf+1);
302        }
303        else if (buf[0]!='"' && atoi(buf)>=0){
304                s->mode=atoi(buf);
305        }
306        else {
307                s->mode = -1; /* deault mode */
308        }
309        return 0;
310}
311
312static int enc_add_attr(MSFilter *f, void *arg){
313        const char *fmtp=(const char *)arg;
314        SpeexEncState *s=(SpeexEncState*)f->data;
315        if (strstr(fmtp,"ptime:10")!=NULL){
316                s->ptime=20;
317        }else if (strstr(fmtp,"ptime:20")!=NULL){
318                s->ptime=20;
319        }else if (strstr(fmtp,"ptime:30")!=NULL){
320                s->ptime=40;
321        }else if (strstr(fmtp,"ptime:40")!=NULL){
322                s->ptime=40;
323        }else if (strstr(fmtp,"ptime:50")!=NULL){
324                s->ptime=60;
325        }else if (strstr(fmtp,"ptime:60")!=NULL){
326                s->ptime=60;
327        }else if (strstr(fmtp,"ptime:70")!=NULL){
328                s->ptime=80;
329        }else if (strstr(fmtp,"ptime:80")!=NULL){
330                s->ptime=80;
331        }else if (strstr(fmtp,"ptime:90")!=NULL){
332                s->ptime=100; /* not allowed */
333        }else if (strstr(fmtp,"ptime:100")!=NULL){
334                s->ptime=100;
335        }else if (strstr(fmtp,"ptime:110")!=NULL){
336                s->ptime=120;
337        }else if (strstr(fmtp,"ptime:120")!=NULL){
338                s->ptime=120;
339        }else if (strstr(fmtp,"ptime:130")!=NULL){
340                s->ptime=140;
341        }else if (strstr(fmtp,"ptime:140")!=NULL){
342                s->ptime=140;
343        }
344        return 0;
345}
346
347static MSFilterMethod enc_methods[]={
348        {       MS_FILTER_SET_SAMPLE_RATE       ,       enc_set_sr      },
349        {       MS_FILTER_SET_BITRATE           ,       enc_set_br      },
350        {       MS_FILTER_ADD_FMTP              ,       enc_add_fmtp },
351        {       MS_FILTER_ADD_ATTR              ,       enc_add_attr},
352        {       0                               ,       NULL            }
353};
354
355#ifdef _MSC_VER
356
357MSFilterDesc ms_speex_enc_desc={
358        MS_SPEEX_ENC_ID,
359        "MSSpeexEnc",
360        N_("The free and wonderful speex codec"),
361        MS_FILTER_ENCODER,
362        "speex",
363        1,
364        1,
365        enc_init,
366        enc_preprocess,
367        enc_process,
368        enc_postprocess,
369        enc_uninit,
370        enc_methods
371};
372
373#else
374
375MSFilterDesc ms_speex_enc_desc={
376        .id=MS_SPEEX_ENC_ID,
377        .name="MSSpeexEnc",
378        .text=N_("The free and wonderful speex codec"),
379        .category=MS_FILTER_ENCODER,
380        .enc_fmt="speex",
381        .ninputs=1,
382        .noutputs=1,
383        .init=enc_init,
384        .preprocess=enc_preprocess,
385        .postprocess=enc_postprocess,
386        .process=enc_process,
387        .uninit=enc_uninit,
388        .methods=enc_methods
389};
390
391#endif
392
393typedef struct DecState{
394        int rate;
395        int penh;
396        int frsz;
397        uint64_t sample_time;
398        void *state;
399} DecState;
400
401static void dec_init(MSFilter *f){
402        DecState *s=(DecState *)ms_new(DecState,1);
403        s->rate=8000;
404        s->frsz=0;
405        s->state=NULL;
406        s->penh=1;
407        s->sample_time=0;
408        f->data=s;
409}
410
411static void dec_uninit(MSFilter *f){
412        DecState *s=(DecState*)f->data;
413    if (s==NULL)
414                return;
415    if (s->state!=NULL)
416                speex_decoder_destroy(s->state);
417        ms_free(s);
418}
419
420static void dec_preprocess(MSFilter *f){
421        DecState *s=(DecState*)f->data;
422        const SpeexMode *mode=NULL;
423        int modeid;
424        switch(s->rate){
425                case 8000:
426                modeid = SPEEX_MODEID_NB;    /* rate = 8000Hz */
427                        break;
428                case 16000:
429                modeid = SPEEX_MODEID_WB;    /* rate = 16000Hz */
430                        break;
431                        /* should be supported in the future */
432                case 32000:
433                modeid = SPEEX_MODEID_UWB;   /* rate = 32000Hz */
434                        break;
435                default:
436                        ms_error("Unsupported rate for speex decoder (back to default rate=8000).");
437                        modeid=SPEEX_MODEID_NB;
438        }
439        /* warning: speex_lib_get_mode() is not available on speex<1.1.12 */
440        mode = speex_lib_get_mode(modeid);
441        s->state=speex_decoder_init(mode);
442        speex_mode_query(mode,SPEEX_MODE_FRAME_SIZE,&s->frsz);
443        if (s->penh==1)
444                speex_decoder_ctl (s->state, SPEEX_SET_ENH, &s->penh);
445        s->sample_time=0;
446}
447
448static void dec_postprocess(MSFilter *f){
449        DecState *s=(DecState*)f->data;
450        speex_decoder_destroy(s->state);
451        s->state=NULL;
452}
453
454static int dec_set_sr(MSFilter *f, void *arg){
455        DecState *s=(DecState*)f->data;
456        s->rate=((int*)arg)[0];
457        return 0;
458}
459
460static void dec_process(MSFilter *f){
461        DecState *s=(DecState*)f->data;
462        mblk_t *im;
463        mblk_t *om;
464        int err=-2;
465        SpeexBits bits;
466        int bytes=s->frsz*2;
467        bool_t bits_initd=FALSE;
468       
469        while((im=ms_queue_get(f->inputs[0]))!=NULL){
470                int rem_bits=(im->b_wptr-im->b_rptr)*8;
471
472                if (s->sample_time==0){
473                        s->sample_time=f->ticker->time;
474                }
475               
476                if (!bits_initd) {
477                        speex_bits_init(&bits);
478                        bits_initd=TRUE;
479                }else speex_bits_reset(&bits);
480               
481                speex_bits_read_from(&bits,(char*)im->b_rptr,im->b_wptr-im->b_rptr);
482               
483                /* support for multiple frame  in one RTP packet */
484                do{
485                        om=allocb(bytes,0);
486                        err=speex_decode_int(s->state,&bits,(int16_t*)om->b_wptr);
487                        om->b_wptr+=bytes;
488
489                        if (err==0){
490                                ms_queue_put(f->outputs[0],om);
491                                s->sample_time+=20;
492                        }else {
493                                if (err==-1)
494                                        ms_warning("speex end of stream");
495                                else if (err==-2)
496                                        ms_warning("speex corrupted stream");
497                                freemsg(om);
498                        }
499                }while((rem_bits= speex_bits_remaining(&bits))>10);
500                freemsg(im);
501        }
502        if (s->sample_time!=0 && f->ticker->time>s->sample_time){
503                /* we should output a frame but no packet were decoded
504                 thus do packet loss concealment*/
505                om=allocb(bytes,0);
506                err=speex_decode_int(s->state,NULL,(int16_t*)om->b_wptr);
507                om->b_wptr+=bytes;
508                ms_queue_put(f->outputs[0],om);
509                ms_warning("Doing speex packet loss concealment.");
510                s->sample_time+=20;
511        }
512        if (bits_initd) speex_bits_destroy(&bits);
513}
514
515static MSFilterMethod dec_methods[]={
516        {       MS_FILTER_SET_SAMPLE_RATE       ,       dec_set_sr      },
517        {       0                               ,       NULL            }
518};
519
520#ifdef _MSC_VER
521
522MSFilterDesc ms_speex_dec_desc={
523        MS_SPEEX_DEC_ID,
524        "MSSpeexDec",
525        N_("The free and wonderful speex codec"),
526        MS_FILTER_DECODER,
527        "speex",
528        1,
529        1,
530        dec_init,
531        dec_preprocess,
532        dec_process,
533        dec_postprocess,
534        dec_uninit,
535        dec_methods
536};
537
538#else
539
540MSFilterDesc ms_speex_dec_desc={
541        .id=MS_SPEEX_DEC_ID,
542        .name="MSSpeexDec",
543        .text=N_("The free and wonderful speex codec"),
544        .category=MS_FILTER_DECODER,
545        .enc_fmt="speex",
546        .ninputs=1,
547        .noutputs=1,
548        .init=dec_init,
549        .preprocess=dec_preprocess,
550        .postprocess=dec_postprocess,
551        .process=dec_process,
552        .uninit=dec_uninit,
553        .methods=dec_methods
554};
555
556#endif
557
558MS_FILTER_DESC_EXPORT(ms_speex_dec_desc)
559MS_FILTER_DESC_EXPORT(ms_speex_enc_desc)
Note: See TracBrowser for help on using the repository browser.