7568
|
1 #include <stdio.h>
|
|
2 #include <stdlib.h>
|
|
3 #include <string.h>
|
|
4
|
|
5 #ifdef HAVE_MALLOC_H
|
|
6 #include <malloc.h>
|
|
7 #endif
|
|
8
|
|
9 #include "../config.h"
|
|
10 #include "../mp_msg.h"
|
|
11
|
|
12 #include "af.h"
|
|
13
|
|
14 // Static list of filters
|
|
15 extern af_info_t af_info_dummy;
|
|
16 extern af_info_t af_info_delay;
|
|
17 extern af_info_t af_info_channels;
|
|
18 extern af_info_t af_info_format;
|
|
19 extern af_info_t af_info_resample;
|
|
20
|
|
21 static af_info_t* filter_list[]={ \
|
|
22 &af_info_dummy,\
|
|
23 &af_info_delay,\
|
|
24 &af_info_channels,\
|
|
25 &af_info_format,\
|
|
26 &af_info_resample,\
|
|
27 NULL \
|
|
28 };
|
|
29
|
|
30 // Command line config switches
|
|
31 af_cfg_t af_cfg={\
|
|
32 0,\
|
|
33 0,\
|
|
34 0,\
|
|
35 0,\
|
|
36 NULL,\
|
|
37 };
|
|
38
|
|
39
|
|
40 // Initialization types
|
|
41 #define SLOW 1
|
|
42 #define FAST 2
|
|
43 #define FORCE 3
|
|
44
|
|
45 // The first and last filter in the list
|
|
46 static af_instance_t* first=NULL;
|
|
47 static af_instance_t* last=NULL;
|
|
48 // Storage for input and output data formats (set by init)
|
|
49 static af_data_t input;
|
|
50 static af_data_t output;
|
|
51
|
|
52 /* Find a filter in the static list of filters using it's name. This
|
|
53 function is used internally */
|
|
54 af_info_t* af_find(char*name)
|
|
55 {
|
|
56 int i=0;
|
|
57 while(filter_list[i]){
|
|
58 if(!strcmp(filter_list[i]->name,name))
|
|
59 return filter_list[i];
|
|
60 i++;
|
|
61 }
|
|
62 mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't find audio filter '%s'\n",name);
|
|
63 return NULL;
|
|
64 }
|
|
65
|
|
66 // Function for creating a new filter of type name
|
|
67 af_instance_t* af_create(char* name)
|
|
68 {
|
|
69 // Allocate space for the new filter and reset all pointers
|
|
70 af_instance_t* new=malloc(sizeof(af_instance_t));
|
|
71 if(!new){
|
|
72 mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory\n");
|
|
73 return NULL;
|
|
74 }
|
|
75 memset(new,0,sizeof(af_instance_t));
|
|
76
|
|
77 // Find filter from name
|
|
78 new->info=af_find(name);
|
|
79
|
|
80 // Initialize the new filter
|
|
81 if(new->info && (AF_OK==new->info->open(new)))
|
|
82 return new;
|
|
83
|
|
84 free(new);
|
|
85 mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't create audio filter '%s'\n",name);
|
|
86 return NULL;
|
|
87 }
|
|
88
|
|
89 /* Create and insert a new filter of type name before the filter in the
|
|
90 argument. This function can be called during runtime, the return
|
|
91 value is the new filter */
|
|
92 af_instance_t* af_prepend(af_instance_t* af, char* name)
|
|
93 {
|
|
94 // Create the new filter and make sure it is ok
|
|
95 af_instance_t* new=af_create(name);
|
|
96 if(!new)
|
|
97 return NULL;
|
|
98 // Update pointers
|
|
99 new->next=af;
|
|
100 if(af){
|
|
101 new->prev=af->prev;
|
|
102 af->prev=new;
|
|
103 }
|
|
104 else
|
|
105 last=new;
|
|
106 if(new->prev)
|
|
107 new->prev->next=new;
|
|
108 else
|
|
109 first=new;
|
|
110 return new;
|
|
111 }
|
|
112
|
|
113 /* Create and insert a new filter of type name after the filter in the
|
|
114 argument. This function can be called during runtime, the return
|
|
115 value is the new filter */
|
|
116 af_instance_t* af_append(af_instance_t* af, char* name)
|
|
117 {
|
|
118 // Create the new filter and make sure it is OK
|
|
119 af_instance_t* new=af_create(name);
|
|
120 if(!new)
|
|
121 return NULL;
|
|
122 // Update pointers
|
|
123 new->prev=af;
|
|
124 if(af){
|
|
125 new->next=af->next;
|
|
126 af->next=new;
|
|
127 }
|
|
128 else
|
|
129 first=new;
|
|
130 if(new->next)
|
|
131 new->next->prev=new;
|
|
132 else
|
|
133 last=new;
|
|
134 return new;
|
|
135 }
|
|
136
|
|
137 // Uninit and remove the filter "af"
|
|
138 void af_remove(af_instance_t* af)
|
|
139 {
|
|
140 if(!af) return;
|
|
141
|
|
142 // Detach pointers
|
|
143 if(af->prev)
|
|
144 af->prev->next=af->next;
|
|
145 else
|
|
146 first=af->next;
|
|
147 if(af->next)
|
|
148 af->next->prev=af->prev;
|
|
149 else
|
|
150 last=af->prev;
|
|
151
|
|
152 // Uninitialize af and free memory
|
|
153 af->uninit(af);
|
|
154 free(af);
|
|
155 }
|
|
156
|
|
157 /* Reinitializes all filters downstream from the filter given in the argument */
|
|
158 int af_reinit(af_instance_t* af)
|
|
159 {
|
|
160 if(!af)
|
|
161 return AF_ERROR;
|
|
162
|
|
163 do{
|
|
164 af_data_t in; // Format of the input to current filter
|
|
165 int rv=0; // Return value
|
|
166
|
|
167 // Check if this is the first filter
|
|
168 if(!af->prev)
|
|
169 memcpy(&in,&input,sizeof(af_data_t));
|
|
170 else
|
|
171 memcpy(&in,af->prev->data,sizeof(af_data_t));
|
|
172 // Reset just in case...
|
|
173 in.audio=NULL;
|
|
174 in.len=0;
|
|
175
|
|
176 rv = af->control(af,AF_CONTROL_REINIT,&in);
|
|
177 switch(rv){
|
|
178 case AF_OK:
|
|
179 break;
|
|
180 case AF_FALSE:{ // Configuration filter is needed
|
|
181 af_instance_t* new = NULL;
|
|
182 // Insert channels filter
|
|
183 if((af->prev?af->prev->data->nch:input.nch) != in.nch){
|
|
184 // Create channels filter
|
|
185 if(NULL == (new = af_prepend(af,"channels")))
|
|
186 return AF_ERROR;
|
|
187 // Set number of output channels
|
|
188 if(AF_OK != (rv = new->control(new,AF_CONTROL_CHANNELS,&in.nch)))
|
|
189 return rv;
|
|
190 // Initialize channels filter
|
|
191 if(!new->prev)
|
|
192 memcpy(&in,&input,sizeof(af_data_t));
|
|
193 else
|
|
194 memcpy(&in,new->prev->data,sizeof(af_data_t));
|
|
195 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
|
|
196 return rv;
|
|
197 }
|
|
198 // Insert format filter
|
|
199 if(((af->prev?af->prev->data->format:input.format) != in.format) ||
|
|
200 ((af->prev?af->prev->data->bps:input.bps) != in.bps)){
|
|
201 // Create format filter
|
|
202 if(NULL == (new = af_prepend(af,"format")))
|
|
203 return AF_ERROR;
|
|
204 // Set output format
|
|
205 if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in)))
|
|
206 return rv;
|
|
207 // Initialize format filter
|
|
208 if(!new->prev)
|
|
209 memcpy(&in,&input,sizeof(af_data_t));
|
|
210 else
|
|
211 memcpy(&in,new->prev->data,sizeof(af_data_t));
|
|
212 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in)))
|
|
213 return rv;
|
|
214 }
|
|
215 if(!new) // Should _never_ happen
|
|
216 return AF_ERROR;
|
|
217 af=new;
|
|
218 break;
|
|
219 }
|
|
220 case AF_DETACH:{ // Filter is redundant and wants to be unloaded
|
|
221 af_instance_t* aft=af->prev;
|
|
222 af_remove(af);
|
|
223 if(aft)
|
|
224 af=aft;
|
|
225 else
|
|
226 af=first; // Restart configuration
|
|
227 break;
|
|
228 }
|
|
229 default:
|
|
230 mp_msg(MSGT_AFILTER,MSGL_ERR,"Reinit did not work, audio filter '%s' returned error code %i\n",af->info->name,rv);
|
|
231 return AF_ERROR;
|
|
232 }
|
|
233 af=af->next;
|
|
234 }while(af);
|
|
235 return AF_OK;
|
|
236 }
|
|
237
|
|
238 /* Find filter in the dynamic filter list using it's name This
|
|
239 function is used for finding already initialized filters */
|
|
240 af_instance_t* af_get(char* name)
|
|
241 {
|
|
242 af_instance_t* af=first;
|
|
243 while(af->next != NULL){
|
|
244 if(!strcmp(af->info->name,name))
|
|
245 return af;
|
|
246 af=af->next;
|
|
247 }
|
|
248 return NULL;
|
|
249 }
|
|
250
|
|
251 // Uninit and remove all filters
|
|
252 void af_uninit()
|
|
253 {
|
|
254 while(first)
|
|
255 af_remove(first);
|
|
256 }
|
|
257
|
|
258 /* Init read configuration and create filter list accordingly. In and
|
|
259 out contains the format of the current movie and the formate of the
|
|
260 preferred output respectively */
|
|
261 int af_init(af_data_t* in, af_data_t* out)
|
|
262 {
|
|
263 int cfg=SLOW; // configuration type
|
|
264 int i=0;
|
|
265
|
|
266 // Precaution in case caller is misbehaving
|
|
267 in->audio = out->audio = NULL;
|
|
268 in->len = out->len = 0;
|
|
269
|
|
270 // Figure out how fast the machine is
|
|
271 if(af_cfg.force)
|
|
272 cfg=af_cfg.force;
|
|
273 else{
|
|
274 # if defined(HAVE_SSE) || defined(HAVE_3DNOWEX)
|
|
275 cfg=FAST;
|
|
276 # else
|
|
277 cfg=SLOW;
|
|
278 # endif
|
|
279 }
|
|
280
|
|
281 // Input and output configuration
|
|
282 memcpy(&input,in,sizeof(af_data_t));
|
|
283 memcpy(&output,out,sizeof(af_data_t));
|
|
284
|
|
285 // Check if this is the first call
|
|
286 if(!first){
|
|
287 // Add all filters in the list (if there are any)
|
|
288 if(!af_cfg.list){
|
|
289 if(!af_append(first,"dummy")) // To make automatic format conversion work
|
|
290 return -1;
|
|
291 }
|
|
292 else{
|
|
293 while(af_cfg.list[i]){
|
|
294 if(!af_append(last,af_cfg.list[i++]))
|
|
295 return -1;
|
|
296 }
|
|
297 }
|
|
298 }
|
|
299
|
|
300 // Init filters
|
|
301 if(AF_OK != af_reinit(first))
|
|
302 return -1;
|
|
303
|
|
304 // Check output format
|
|
305 if(cfg!=FORCE){
|
|
306 af_instance_t* af = NULL; // New filter
|
|
307 // Check output frequency if not OK fix with resample
|
|
308 if(last->data->rate!=output.rate){
|
|
309 if(NULL==(af=af_get("resample"))){
|
|
310 if(cfg==SLOW){
|
|
311 if(!strcmp(first->info->name,"format"))
|
|
312 af = af_append(first,"resample");
|
|
313 else
|
|
314 af = af_prepend(first,"resample");
|
|
315 }
|
|
316 else{
|
|
317 if(!strcmp(last->info->name,"format"))
|
|
318 af = af_prepend(last,"resample");
|
|
319 else
|
|
320 af = af_append(last,"resample");
|
|
321 }
|
|
322 }
|
|
323 // Init the new filter
|
|
324 if(!af || (AF_OK != af->control(af,AF_CONTROL_RESAMPLE,&output.rate)))
|
|
325 return -1;
|
|
326 if(AF_OK != af_reinit(af))
|
|
327 return -1;
|
|
328 }
|
|
329
|
|
330 // Check number of output channels fix if not OK
|
|
331 // If needed always inserted last -> easy to screw up other filters
|
|
332 if(last->data->nch!=output.nch){
|
|
333 if(!strcmp(last->info->name,"format"))
|
|
334 af = af_prepend(last,"channels");
|
|
335 else
|
|
336 af = af_append(last,"channels");
|
|
337 // Init the new filter
|
|
338 if(!af || (AF_OK != af->control(af,AF_CONTROL_CHANNELS,&output.nch)))
|
|
339 return -1;
|
|
340 if(AF_OK != af_reinit(af))
|
|
341 return -1;
|
|
342 }
|
|
343
|
|
344 // Check output format fix if not OK
|
|
345 if((last->data->format != output.format) || (last->data->bps != output.bps)){
|
|
346 if(strcmp(last->info->name,"format"))
|
|
347 af = af_append(last,"format");
|
|
348 else
|
|
349 af = last;
|
|
350 // Init the new filter
|
|
351 if(!af ||(AF_OK != af->control(af,AF_CONTROL_FORMAT,&output)))
|
|
352 return -1;
|
|
353 if(AF_OK != af_reinit(af))
|
|
354 return -1;
|
|
355 }
|
|
356
|
|
357 // Re init again just in case
|
|
358 if(AF_OK != af_reinit(first))
|
|
359 return -1;
|
|
360
|
|
361 if((last->data->format != output.format) || (last->data->bps != output.bps) ||
|
|
362 (last->data->nch!=output.nch) || (last->data->rate!=output.rate)){
|
|
363 // Something is stuffed audio out will not work
|
|
364 mp_msg(MSGT_AFILTER,MSGL_ERR,"Unable to setup filter system can not meet sound-card demands, please report this error on MPlayer development mailing list. \n");
|
|
365 af_uninit();
|
|
366 return -1;
|
|
367 }
|
|
368 }
|
|
369 return 0;
|
|
370 }
|
|
371
|
|
372 // Filter data chunk through the filters in the list
|
|
373 af_data_t* af_play(af_data_t* data)
|
|
374 {
|
|
375 af_instance_t* af=first;
|
|
376 // Iterate through all filters
|
|
377 do{
|
|
378 data=af->play(af,data);
|
|
379 af=af->next;
|
|
380 }while(af);
|
|
381 return data;
|
|
382 }
|
|
383
|
|
384 /* Helper function used to calculate the exact buffer length needed
|
|
385 when buffers are resized */
|
|
386 inline int af_lencalc(frac_t mul, int len){
|
|
387 register int q = len*mul.n;
|
|
388 return q/mul.d + q%mul.d;
|
|
389 }
|
|
390
|
|
391 /* Calculate how long the output from the filters will be given the
|
|
392 input length "len" */
|
|
393 int af_outputlen(int len)
|
|
394 {
|
|
395 af_instance_t* af=first;
|
|
396 frac_t mul = {1,1};
|
|
397 // Iterate through all filters
|
|
398 do{
|
|
399 mul.n *= af->mul.n;
|
|
400 mul.d *= af->mul.d;
|
|
401 af=af->next;
|
|
402 }while(af);
|
|
403 return af_lencalc(mul,len);
|
|
404 }
|
|
405
|
|
406 /* Calculate how long the input to the filters should be to produce a
|
|
407 certain output length, i.e. the return value of this function is
|
|
408 the input length required to produce the output length "len". */
|
|
409 int af_inputlen(int len)
|
|
410 {
|
|
411 af_instance_t* af=first;
|
|
412 frac_t mul = {1,1};
|
|
413 // Iterate through all filters
|
|
414 do{
|
|
415 mul.d *= af->mul.n;
|
|
416 mul.n *= af->mul.d;
|
|
417 af=af->next;
|
|
418 }while(af);
|
|
419 return af_lencalc(mul,len);
|
|
420 }
|
|
421
|
|
422 /* Helper function called by the macro with the same name this
|
|
423 function should not be called directly */
|
|
424 inline int af_resize_local_buffer(af_instance_t* af, af_data_t* data)
|
|
425 {
|
|
426 // Calculate new length
|
|
427 register int len = af_lencalc(af->mul,data->len);
|
|
428 mp_msg(MSGT_AFILTER,MSGL_V,"Reallocating memory in module %s, old len = %i, new len = %i\n",af->info->name,af->data->len,len);
|
|
429 // If there is a buffer free it
|
|
430 if(af->data->audio)
|
|
431 free(af->data->audio);
|
|
432 // Create new buffer and check that it is OK
|
|
433 af->data->audio = malloc(len);
|
|
434 if(!af->data->audio){
|
|
435 mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory \n");
|
|
436 return AF_ERROR;
|
|
437 }
|
|
438 af->data->len=len;
|
|
439 return AF_OK;
|
|
440 }
|