12024
|
1 /*
|
|
2 The mediastreamer library aims at providing modular media processing and I/O
|
|
3 for linphone, but also for any telephony application.
|
|
4 Copyright (C) 2001 Simon MORLAT simon.morlat@linphone.org
|
|
5
|
|
6 This library is free software; you can redistribute it and/or
|
|
7 modify it under the terms of the GNU Lesser General Public
|
|
8 License as published by the Free Software Foundation; either
|
|
9 version 2.1 of the License, or (at your option) any later version.
|
|
10
|
|
11 This library is distributed in the hope that it will be useful,
|
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
14 Lesser General Public License for more details.
|
|
15
|
|
16 You should have received a copy of the GNU Lesser General Public
|
|
17 License along with this library; if not, write to the Free Software
|
|
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
19 */
|
|
20
|
|
21
|
|
22
|
|
23 #include "msspeexenc.h"
|
|
24 #include "ms.h"
|
|
25 extern MSCodecInfo speex_info;
|
|
26
|
|
27 static MSSpeexEncClass * ms_speex_enc_class=NULL;
|
|
28
|
|
29 MSFilter * ms_speex_enc_new()
|
|
30 {
|
|
31 MSSpeexEnc *obj=g_new(MSSpeexEnc,1);
|
|
32
|
|
33 if (ms_speex_enc_class==NULL){
|
|
34 ms_speex_enc_class=g_new(MSSpeexEncClass,1);
|
|
35 ms_speex_enc_class_init(ms_speex_enc_class);
|
|
36 }
|
|
37 MS_FILTER(obj)->klass=MS_FILTER_CLASS(ms_speex_enc_class);
|
|
38 ms_speex_enc_init(MS_SPEEX_ENC(obj));
|
|
39 return MS_FILTER(obj);
|
|
40 }
|
|
41
|
|
42 void ms_speex_enc_init(MSSpeexEnc *obj)
|
|
43 {
|
|
44 ms_filter_init(MS_FILTER(obj));
|
|
45 MS_FILTER(obj)->infifos=obj->inf;
|
|
46 MS_FILTER(obj)->outqueues=obj->outq;
|
|
47 obj->inf[0]=NULL;
|
|
48 obj->outq[0]=NULL;
|
|
49 obj->frequency=8000;
|
|
50 obj->bitrate=30000;
|
|
51 obj->initialized=0;
|
|
52 }
|
|
53
|
|
54 void ms_speex_enc_init_core(MSSpeexEnc *obj,const SpeexMode *mode, gint bitrate)
|
|
55 {
|
|
56 int proc_type, proc_speed;
|
|
57 gchar *proc_vendor;
|
|
58 int tmp;
|
|
59 int frame_size;
|
|
60
|
|
61 obj->speex_state=speex_encoder_init(mode);
|
|
62 speex_bits_init(&obj->bits);
|
|
63
|
|
64 if (bitrate>0) {
|
|
65 bitrate++;
|
|
66 speex_encoder_ctl(obj->speex_state, SPEEX_SET_BITRATE, &bitrate);
|
|
67 g_message("Setting speex output bitrate less or equal than %i",bitrate-1);
|
|
68 }
|
|
69
|
|
70 proc_speed=ms_proc_get_speed();
|
|
71 proc_vendor=ms_proc_get_param("vendor_id");
|
|
72 if (proc_speed<0 || proc_vendor==NULL){
|
|
73 g_warning("Can't guess processor features: setting speex encoder to its lowest complexity.");
|
|
74 tmp=1;
|
|
75 speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp);
|
|
76 }else if ((proc_speed!=-1) && (proc_speed<200)){
|
|
77 g_warning("A cpu speed less than 200 Mhz is not enough: let's reduce the complexity of the speex codec.");
|
|
78 tmp=1;
|
|
79 speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp);
|
|
80 }else if (proc_vendor!=NULL) {
|
|
81 if (strncmp(proc_vendor,"GenuineIntel",strlen("GenuineIntel"))==0){
|
|
82 proc_type=ms_proc_get_type();
|
|
83 if (proc_type==5){
|
|
84 g_warning("A pentium I is not enough fast for speex codec in normal mode: let's reduce its complexity.");
|
|
85 tmp=1;
|
|
86 speex_encoder_ctl(obj->speex_state,SPEEX_SET_COMPLEXITY,&tmp);
|
|
87 }
|
|
88 }
|
|
89 g_free(proc_vendor);
|
|
90 }
|
|
91 /* guess the used input frame size */
|
|
92 speex_mode_query(mode, SPEEX_MODE_FRAME_SIZE, &frame_size);
|
|
93 MS_FILTER(obj)->r_mingran=frame_size*2;
|
|
94 ms_trace("ms_speex_init: using frame size of %i.",MS_FILTER(obj)->r_mingran);
|
|
95
|
|
96 obj->initialized=1;
|
|
97 }
|
|
98
|
|
99 /* must be called before the encoder is running*/
|
|
100 int ms_speex_enc_set_property(MSSpeexEnc *obj,int property,int *value)
|
|
101 {
|
|
102 if (obj->initialized){
|
|
103 /* we are called when speex is running !! forbid that! */
|
|
104 ms_warning("ms_speex_enc_set_property: cannot call this function when running!");
|
|
105 return -1;
|
|
106 }
|
|
107 switch(property){
|
|
108 case MS_FILTER_PROPERTY_FREQ:
|
|
109 obj->frequency=value[0];
|
|
110 break;
|
|
111 case MS_FILTER_PROPERTY_BITRATE: /* to specify max bitrate */
|
|
112 obj->bitrate=value[0];
|
|
113 break;
|
|
114 }
|
|
115 return 0;
|
|
116 }
|
|
117
|
|
118 void ms_speex_enc_setup(MSSpeexEnc *obj)
|
|
119 {
|
|
120 const SpeexMode *mode;
|
|
121 g_message("Speex encoder setup: freq=%i",obj->frequency);
|
|
122 if ( obj->frequency< 16000) mode=&speex_nb_mode;
|
|
123 else mode=&speex_wb_mode;
|
|
124 ms_speex_enc_init_core(obj,mode,obj->bitrate);
|
|
125
|
|
126 }
|
|
127
|
|
128 void ms_speex_enc_unsetup(MSSpeexEnc *obj)
|
|
129 {
|
|
130 ms_speex_enc_uninit_core(obj);
|
|
131 }
|
|
132
|
|
133 void ms_speex_enc_class_init(MSSpeexEncClass *klass)
|
|
134 {
|
|
135 gint frame_size=0;
|
|
136
|
|
137 ms_filter_class_init(MS_FILTER_CLASS(klass));
|
|
138 /* we take the larger (wb) frame size */
|
|
139 speex_mode_query(&speex_wb_mode, SPEEX_MODE_FRAME_SIZE, &frame_size);
|
|
140 MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_speex_enc_process;
|
|
141 MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_speex_enc_destroy;
|
|
142 MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_speex_enc_setup;
|
|
143 MS_FILTER_CLASS(klass)->unsetup=(MSFilterSetupFunc)ms_speex_enc_unsetup;
|
|
144 MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_speex_enc_set_property;
|
|
145 ms_filter_class_set_name(MS_FILTER_CLASS(klass),"SpeexEncoder");
|
|
146 MS_FILTER_CLASS(klass)->info=(MSFilterInfo*)&speex_info;
|
|
147 MS_FILTER_CLASS(klass)->max_finputs=1;
|
|
148 MS_FILTER_CLASS(klass)->max_qoutputs=1;
|
|
149 MS_FILTER_CLASS(klass)->r_maxgran=frame_size*2;
|
|
150 ms_trace("ms_speex_enc_class_init: r_maxgran is %i.",MS_FILTER_CLASS(klass)->r_maxgran);
|
|
151 }
|
|
152
|
|
153 void ms_speex_enc_uninit_core(MSSpeexEnc *obj)
|
|
154 {
|
|
155 if (obj->initialized){
|
|
156 speex_encoder_destroy(obj->speex_state);
|
|
157 obj->initialized=0;
|
|
158 }
|
|
159 }
|
|
160
|
|
161 void ms_speex_enc_destroy(MSSpeexEnc *obj)
|
|
162 {
|
|
163 ms_speex_enc_uninit_core(obj);
|
|
164 g_free(obj);
|
|
165 }
|
|
166
|
|
167 void ms_speex_enc_process(MSSpeexEnc *obj)
|
|
168 {
|
|
169 MSFifo *inf=obj->inf[0];
|
|
170 MSQueue *outq=obj->outq[0];
|
|
171 gint16 *input;
|
|
172 gint gran=MS_FILTER(obj)->r_mingran;
|
|
173 MSMessage *m;
|
|
174
|
|
175 g_return_if_fail(inf!=NULL);
|
|
176 g_return_if_fail(outq!=NULL);
|
|
177
|
|
178 ms_fifo_get_read_ptr(inf,gran,(void**)&input);
|
|
179 g_return_if_fail(input!=NULL);
|
|
180 /* encode */
|
|
181 speex_bits_reset(&obj->bits);
|
|
182 speex_encode_int(obj->speex_state,(short*)input,&obj->bits);
|
|
183 m=ms_message_new(speex_bits_nbytes(&obj->bits));
|
|
184 m->size=speex_bits_write(&obj->bits,m->data,m->size);
|
|
185 ms_queue_put(outq,m);
|
|
186 }
|