]> sjero.net Git - linphone/blob - linphone/mediastreamer2/plugins/msilbc/ilbc.c
remote ortp and add it as a submodule instead.
[linphone] / linphone / mediastreamer2 / plugins / msilbc / ilbc.c
1 /*
2         NO LICENSE
3 */
4 #include <ilbc/iLBC_encode.h>
5 #include <ilbc/iLBC_decode.h>
6
7 #include "mediastreamer2/msfilter.h"
8
9 typedef struct EncState{
10         int nsamples;
11         int nbytes;
12         int ms_per_frame;
13         int ptime;
14         uint32_t ts;
15         MSBufferizer bufferizer;
16         iLBC_Enc_Inst_t ilbc_enc;       
17 }EncState;
18
19 static void enc_init(MSFilter *f){
20         EncState *s=ms_new(EncState,1);
21         s->nsamples=BLOCKL_20MS;
22         s->nbytes=NO_OF_BYTES_20MS;
23         s->ms_per_frame=20;
24         s->ptime=0;
25         s->ts=0;
26         ms_bufferizer_init(&s->bufferizer);
27         f->data=s;
28 }
29
30 static void enc_uninit(MSFilter *f){
31         EncState *s=(EncState*)f->data;
32         ms_bufferizer_uninit(&s->bufferizer);
33         ms_free(f->data);
34 }
35
36 static void enc_preprocess(MSFilter *f){
37         EncState *s=(EncState*)f->data;
38         initEncode(&s->ilbc_enc,s->ms_per_frame);
39 }
40
41 static int enc_add_fmtp(MSFilter *f, void *arg){
42         char buf[64];
43         const char *fmtp=(const char *)arg;
44         EncState *s=(EncState*)f->data;
45
46         memset(buf, '\0', sizeof(buf));
47         fmtp_get_value(fmtp, "mode", buf, sizeof(buf));
48         if (buf[0]=='\0'){
49                 ms_warning("unsupported fmtp parameter (%s)!", fmtp);
50         }
51         else if (strstr(buf,"20")!=NULL){
52                 s->nsamples=BLOCKL_20MS;
53                 s->nbytes=NO_OF_BYTES_20MS;
54                 s->ms_per_frame=20;
55         }else if (strstr(buf,"30")!=NULL){
56                 s->nsamples=BLOCKL_30MS;
57                 s->nbytes=NO_OF_BYTES_30MS;
58                 s->ms_per_frame=30;
59         }
60         return 0;
61 }
62
63 static int enc_add_attr(MSFilter *f, void *arg){
64         const char *fmtp=(const char *)arg;
65         EncState *s=(EncState*)f->data;
66         if (strstr(fmtp,"ptime:20")!=NULL){
67                 s->ptime=20;
68         }else if (strstr(fmtp,"ptime:30")!=NULL){
69                 s->ptime=30;
70         }else if (strstr(fmtp,"ptime:40")!=NULL){
71                 s->ptime=40;
72         }else if (strstr(fmtp,"ptime:60")!=NULL){
73                 s->ptime=60;
74         }else if (strstr(fmtp,"ptime:80")!=NULL){
75                 s->ptime=80;
76         }else if (strstr(fmtp,"ptime:90")!=NULL){
77                 s->ptime=90;
78         }else if (strstr(fmtp,"ptime:100")!=NULL){
79                 s->ptime=100;
80         }else if (strstr(fmtp,"ptime:120")!=NULL){
81                 s->ptime=120;
82         }else if (strstr(fmtp,"ptime:140")!=NULL){
83                 s->ptime=140;
84         }
85         return 0;
86 }
87
88 static void enc_process(MSFilter *f){
89         EncState *s=(EncState*)f->data;
90         mblk_t *im,*om;
91         int size=s->nsamples*2;
92         int16_t samples[1610]; /* BLOCKL_MAX * 7 is the largest size for ptime == 140 */
93         float samples2[BLOCKL_MAX];
94         int i;
95         int frame_per_packet=1;
96
97         if (s->ptime>=20 && s->ms_per_frame>0 && s->ptime%s->ms_per_frame==0)
98         {
99                 frame_per_packet = s->ptime/s->ms_per_frame;
100         }
101
102         if (frame_per_packet<=0)
103                 frame_per_packet=1;
104         if (frame_per_packet>7) /* 7*20 == 140 ms max */
105                 frame_per_packet=7;
106
107         while((im=ms_queue_get(f->inputs[0]))!=NULL){
108                 ms_bufferizer_put(&s->bufferizer,im);
109         }
110         while(ms_bufferizer_read(&s->bufferizer,(uint8_t*)samples,size*frame_per_packet)==(size*frame_per_packet)){
111                 int k;
112                 om=allocb(s->nbytes*frame_per_packet,0);
113                 for (k=0;k<frame_per_packet;k++)
114                 {
115                         for (i=0;i<s->nsamples;i++){
116                                 samples2[i]=samples[i+(s->nsamples*k)];
117                         }
118                         iLBC_encode((uint8_t*)om->b_wptr,samples2,&s->ilbc_enc);
119                         om->b_wptr+=s->nbytes;
120                         s->ts+=s->nsamples;
121                 }
122                 mblk_set_timestamp_info(om,s->ts-s->nsamples);
123                 ms_queue_put(f->outputs[0],om);
124         }
125 }
126
127 static MSFilterMethod enc_methods[]={
128         {       MS_FILTER_ADD_FMTP,             enc_add_fmtp },
129         {       MS_FILTER_ADD_ATTR,             enc_add_attr},
130         {       0                                                               ,               NULL                    }
131 };
132
133 #ifdef _MSC_VER
134
135 MSFilterDesc ms_ilbc_enc_desc={
136         MS_FILTER_PLUGIN_ID,
137         "MSIlbcEnc",
138         "iLBC encoder",
139         MS_FILTER_ENCODER,
140         "iLBC",
141         1,
142         1,
143         enc_init,
144     enc_preprocess,
145         enc_process,
146     NULL,
147         enc_uninit,
148         enc_methods
149 };
150
151 #else
152
153 MSFilterDesc ms_ilbc_enc_desc={
154         .id=MS_FILTER_PLUGIN_ID,
155         .name="MSIlbcEnc",
156         .text="iLBC encoder",
157         .category=MS_FILTER_ENCODER,
158         .enc_fmt="iLBC",
159         .ninputs=1,
160         .noutputs=1,
161         .init=enc_init,
162         .preprocess=enc_preprocess,
163         .process=enc_process,
164         .uninit=enc_uninit,
165         .methods=enc_methods
166 };
167
168 #endif
169
170 typedef struct DecState{
171         int nsamples;
172         int nbytes;
173         int ms_per_frame;
174         iLBC_Dec_Inst_t ilbc_dec;       
175 }DecState;
176
177
178 static void dec_init(MSFilter *f){
179         DecState *s=ms_new(DecState,1);
180         s->nsamples=0;
181         s->nbytes=0;
182         s->ms_per_frame=0;
183         f->data=s;
184 }
185
186 static void dec_uninit(MSFilter *f){
187         ms_free(f->data);
188 }
189
190 static void dec_process(MSFilter *f){
191         DecState *s=(DecState*)f->data;
192         mblk_t *im,*om;
193         int nbytes;
194         float samples[BLOCKL_MAX];
195         int i;
196
197         while ((im=ms_queue_get(f->inputs[0]))!=NULL){
198                 nbytes=msgdsize(im);
199                 if (nbytes<=0)
200                         return;
201                 if (nbytes%38!=0 && nbytes%50!=0)
202                         return;
203                 if (nbytes%38==0 && s->nbytes!=NO_OF_BYTES_20MS)
204                 {
205                         /* not yet configured, or misconfigured */
206                         s->ms_per_frame=20;
207                         s->nbytes=NO_OF_BYTES_20MS;
208                         s->nsamples=BLOCKL_20MS;
209                         initDecode(&s->ilbc_dec,s->ms_per_frame,0);
210                 }
211                 else if (nbytes%50==0 && s->nbytes!=NO_OF_BYTES_30MS)
212                 {
213                         /* not yet configured, or misconfigured */
214                         s->ms_per_frame=30;
215                         s->nbytes=NO_OF_BYTES_30MS;
216                         s->nsamples=BLOCKL_30MS;
217                         initDecode(&s->ilbc_dec,s->ms_per_frame,0);
218                 }
219                 if (s->nbytes>0 && nbytes>=s->nbytes){
220                         int frame_per_packet = nbytes/s->nbytes;
221                         int k;
222
223                         for (k=0;k<frame_per_packet;k++)
224                         {
225                                 om=allocb(s->nsamples*2,0);
226                                 iLBC_decode(samples,(uint8_t*)im->b_rptr+(k*s->nbytes),&s->ilbc_dec,1);
227                                 for (i=0;i<s->nsamples;i++,om->b_wptr+=2){
228                                         *((int16_t*)om->b_wptr)=samples[i];
229                                 }
230                                 ms_queue_put(f->outputs[0],om);
231                         }
232                 }else{
233                         ms_warning("bad iLBC frame !");
234                 }
235                 freemsg(im);
236         }
237 }
238
239 #ifdef _MSC_VER
240
241 MSFilterDesc ms_ilbc_dec_desc={
242         MS_FILTER_PLUGIN_ID,
243         "MSIlbcDec",
244         "iLBC decoder",
245         MS_FILTER_DECODER,
246         "iLBC",
247         1,
248         1,
249         dec_init,
250     NULL,
251         dec_process,
252     NULL,
253         dec_uninit,
254     NULL
255 };
256
257 #else
258
259 MSFilterDesc ms_ilbc_dec_desc={
260         .id=MS_FILTER_PLUGIN_ID,
261         .name="MSIlbcDec",
262         .text="iLBC decoder",
263         .category=MS_FILTER_DECODER,
264         .enc_fmt="iLBC",
265         .ninputs=1,
266         .noutputs=1,
267         .init=dec_init,
268         .process=dec_process,
269         .uninit=dec_uninit
270 };
271
272 #endif
273
274 #ifdef _MSC_VER
275 #define MS_PLUGIN_DECLARE(type) __declspec(dllexport) type
276 #else
277 #define MS_PLUGIN_DECLARE(type) type
278 #endif
279
280 MS_PLUGIN_DECLARE(void) libmsilbc_init(){
281         ms_filter_register(&ms_ilbc_enc_desc);
282         ms_filter_register(&ms_ilbc_dec_desc);
283 }