Mercurial > mplayer.hg
comparison libaf/af.c @ 8167:e8832e66babd
New features:
-- Support for runtime cpu detection
-- Stand alone compile of libaf
-- Unlimited number of channels (compiletime switch)
-- Sample format defined by bit-fields
-- New formats: float, A-Law and mu-law
-- Format conversion set in human readable format
i.e. format=4:us_be to set 32 bit unsigned big endian output
-- Format reporting in human readable format
-- Volume control has only one parameter for setting the volume
i.e. volume=-10.0:1:0:1 to set atenuation = -10dB
author | anders |
---|---|
date | Tue, 12 Nov 2002 12:33:56 +0000 |
parents | c0e556f9986b |
children | d6f40a06867b |
comparison
equal
deleted
inserted
replaced
8166:1a824d76d2a9 | 8167:e8832e66babd |
---|---|
3 #include <string.h> | 3 #include <string.h> |
4 | 4 |
5 #ifdef HAVE_MALLOC_H | 5 #ifdef HAVE_MALLOC_H |
6 #include <malloc.h> | 6 #include <malloc.h> |
7 #endif | 7 #endif |
8 | |
9 #include "../config.h" | |
10 #include "../mp_msg.h" | |
11 | 8 |
12 #include "af.h" | 9 #include "af.h" |
13 | 10 |
14 // Static list of filters | 11 // Static list of filters |
15 extern af_info_t af_info_dummy; | 12 extern af_info_t af_info_dummy; |
29 &af_info_volume,\ | 26 &af_info_volume,\ |
30 &af_info_equalizer,\ | 27 &af_info_equalizer,\ |
31 NULL \ | 28 NULL \ |
32 }; | 29 }; |
33 | 30 |
31 // Message printing | |
32 af_msg_cfg_t af_msg_cfg={0,NULL,NULL}; | |
33 | |
34 // CPU speed | |
35 int* af_cpu_speed = NULL; | |
36 | |
34 /* Find a filter in the static list of filters using it's name. This | 37 /* Find a filter in the static list of filters using it's name. This |
35 function is used internally */ | 38 function is used internally */ |
36 af_info_t* af_find(char*name) | 39 af_info_t* af_find(char*name) |
37 { | 40 { |
38 int i=0; | 41 int i=0; |
39 while(filter_list[i]){ | 42 while(filter_list[i]){ |
40 if(!strcmp(filter_list[i]->name,name)) | 43 if(!strcmp(filter_list[i]->name,name)) |
41 return filter_list[i]; | 44 return filter_list[i]; |
42 i++; | 45 i++; |
43 } | 46 } |
44 mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't find audio filter '%s'\n",name); | 47 af_msg(AF_MSG_ERROR,"Couldn't find audio filter '%s'\n",name); |
45 return NULL; | 48 return NULL; |
46 } | 49 } |
47 | 50 |
48 /* Find filter in the dynamic filter list using it's name This | 51 /* Find filter in the dynamic filter list using it's name This |
49 function is used for finding already initialized filters */ | 52 function is used for finding already initialized filters */ |
67 char* delim = "="; | 70 char* delim = "="; |
68 | 71 |
69 // Allocate space for the new filter and reset all pointers | 72 // Allocate space for the new filter and reset all pointers |
70 af_instance_t* new=malloc(sizeof(af_instance_t)); | 73 af_instance_t* new=malloc(sizeof(af_instance_t)); |
71 if(!new){ | 74 if(!new){ |
72 mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory\n"); | 75 af_msg(AF_MSG_ERROR,"Could not allocate memory\n"); |
73 return NULL; | 76 return NULL; |
74 } | 77 } |
75 memset(new,0,sizeof(af_instance_t)); | 78 memset(new,0,sizeof(af_instance_t)); |
76 | 79 |
77 // Check for commandline parameters | 80 // Check for commandline parameters |
83 | 86 |
84 /* Make sure that the filter is not already in the list if it is | 87 /* Make sure that the filter is not already in the list if it is |
85 non-reentrant */ | 88 non-reentrant */ |
86 if(new->info->flags & AF_FLAGS_NOT_REENTRANT){ | 89 if(new->info->flags & AF_FLAGS_NOT_REENTRANT){ |
87 if(af_get(s,name)){ | 90 if(af_get(s,name)){ |
88 mp_msg(MSGT_AFILTER,MSGL_ERR,"There can only be one instance of the filter '%s' in each stream\n",name); | 91 af_msg(AF_MSG_ERROR,"There can only be one instance of the filter '%s' in each stream\n",name); |
89 free(new); | 92 free(new); |
90 return NULL; | 93 return NULL; |
91 } | 94 } |
92 } | 95 } |
93 | 96 |
94 mp_msg(MSGT_AFILTER,MSGL_V,"Adding filter %s \n",name); | 97 af_msg(AF_MSG_VERBOSE,"Adding filter %s \n",name); |
95 | 98 |
96 // Initialize the new filter | 99 // Initialize the new filter |
97 if(AF_OK == new->info->open(new) && | 100 if(AF_OK == new->info->open(new) && |
98 AF_ERROR < new->control(new,AF_CONTROL_POST_CREATE,&s->cfg)){ | 101 AF_ERROR < new->control(new,AF_CONTROL_POST_CREATE,&s->cfg)){ |
99 if(cmdline){ | 102 if(cmdline){ |
103 else | 106 else |
104 return new; | 107 return new; |
105 } | 108 } |
106 | 109 |
107 free(new); | 110 free(new); |
108 mp_msg(MSGT_AFILTER,MSGL_ERR,"Couldn't create or open audio filter '%s'\n",name); | 111 af_msg(AF_MSG_ERROR,"Couldn't create or open audio filter '%s'\n",name); |
109 return NULL; | 112 return NULL; |
110 } | 113 } |
111 | 114 |
112 /* Create and insert a new filter of type name before the filter in the | 115 /* Create and insert a new filter of type name before the filter in the |
113 argument. This function can be called during runtime, the return | 116 argument. This function can be called during runtime, the return |
204 rv = af->control(af,AF_CONTROL_REINIT,&in); | 207 rv = af->control(af,AF_CONTROL_REINIT,&in); |
205 switch(rv){ | 208 switch(rv){ |
206 case AF_OK: | 209 case AF_OK: |
207 break; | 210 break; |
208 case AF_FALSE:{ // Configuration filter is needed | 211 case AF_FALSE:{ // Configuration filter is needed |
209 af_instance_t* new = NULL; | 212 // Do auto insertion only if force is not specified |
210 // Insert channels filter | 213 if((AF_INIT_TYPE_MASK & s->cfg.force) != AF_INIT_FORCE){ |
211 if((af->prev?af->prev->data->nch:s->input.nch) != in.nch){ | 214 af_instance_t* new = NULL; |
212 // Create channels filter | 215 // Insert channels filter |
213 if(NULL == (new = af_prepend(s,af,"channels"))) | 216 if((af->prev?af->prev->data->nch:s->input.nch) != in.nch){ |
217 // Create channels filter | |
218 if(NULL == (new = af_prepend(s,af,"channels"))) | |
219 return AF_ERROR; | |
220 // Set number of output channels | |
221 if(AF_OK != (rv = new->control(new,AF_CONTROL_CHANNELS,&in.nch))) | |
222 return rv; | |
223 // Initialize channels filter | |
224 if(!new->prev) | |
225 memcpy(&in,&(s->input),sizeof(af_data_t)); | |
226 else | |
227 memcpy(&in,new->prev->data,sizeof(af_data_t)); | |
228 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in))) | |
229 return rv; | |
230 } | |
231 // Insert format filter | |
232 if(((af->prev?af->prev->data->format:s->input.format) != in.format) || | |
233 ((af->prev?af->prev->data->bps:s->input.bps) != in.bps)){ | |
234 // Create format filter | |
235 if(NULL == (new = af_prepend(s,af,"format"))) | |
236 return AF_ERROR; | |
237 // Set output format | |
238 if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in))) | |
239 return rv; | |
240 // Initialize format filter | |
241 if(!new->prev) | |
242 memcpy(&in,&(s->input),sizeof(af_data_t)); | |
243 else | |
244 memcpy(&in,new->prev->data,sizeof(af_data_t)); | |
245 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in))) | |
246 return rv; | |
247 } | |
248 if(!new) // Should _never_ happen | |
214 return AF_ERROR; | 249 return AF_ERROR; |
215 // Set number of output channels | 250 af=new; |
216 if(AF_OK != (rv = new->control(new,AF_CONTROL_CHANNELS,&in.nch))) | 251 } |
217 return rv; | 252 break; |
218 // Initialize channels filter | 253 } |
219 if(!new->prev) | 254 case AF_DETACH:{ // Filter is redundant and wants to be unloaded |
220 memcpy(&in,&(s->input),sizeof(af_data_t)); | 255 // Do auto remove only if force is not specified |
256 if((AF_INIT_TYPE_MASK & s->cfg.force) != AF_INIT_FORCE){ | |
257 af_instance_t* aft=af->prev; | |
258 af_remove(s,af); | |
259 if(aft) | |
260 af=aft; | |
221 else | 261 else |
222 memcpy(&in,new->prev->data,sizeof(af_data_t)); | 262 af=s->first; // Restart configuration |
223 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in))) | |
224 return rv; | |
225 } | 263 } |
226 // Insert format filter | |
227 if(((af->prev?af->prev->data->format:s->input.format) != in.format) || | |
228 ((af->prev?af->prev->data->bps:s->input.bps) != in.bps)){ | |
229 // Create format filter | |
230 if(NULL == (new = af_prepend(s,af,"format"))) | |
231 return AF_ERROR; | |
232 // Set output format | |
233 if(AF_OK != (rv = new->control(new,AF_CONTROL_FORMAT,&in))) | |
234 return rv; | |
235 // Initialize format filter | |
236 if(!new->prev) | |
237 memcpy(&in,&(s->input),sizeof(af_data_t)); | |
238 else | |
239 memcpy(&in,new->prev->data,sizeof(af_data_t)); | |
240 if(AF_OK != (rv = new->control(new,AF_CONTROL_REINIT,&in))) | |
241 return rv; | |
242 } | |
243 if(!new) // Should _never_ happen | |
244 return AF_ERROR; | |
245 af=new; | |
246 break; | 264 break; |
247 } | 265 } |
248 case AF_DETACH:{ // Filter is redundant and wants to be unloaded | |
249 af_instance_t* aft=af->prev; | |
250 af_remove(s,af); | |
251 if(aft) | |
252 af=aft; | |
253 else | |
254 af=s->first; // Restart configuration | |
255 break; | |
256 } | |
257 default: | 266 default: |
258 mp_msg(MSGT_AFILTER,MSGL_ERR,"Reinitialization did not work, audio filter '%s' returned error code %i\n",af->info->name,rv); | 267 af_msg(AF_MSG_ERROR,"Reinitialization did not work, audio filter '%s' returned error code %i\n",af->info->name,rv); |
259 return AF_ERROR; | 268 return AF_ERROR; |
260 } | 269 } |
261 af=af->next; | 270 af=af->next; |
262 }while(af); | 271 }while(af); |
263 return AF_OK; | 272 return AF_OK; |
287 // Precaution in case caller is misbehaving | 296 // Precaution in case caller is misbehaving |
288 s->input.audio = s->output.audio = NULL; | 297 s->input.audio = s->output.audio = NULL; |
289 s->input.len = s->output.len = 0; | 298 s->input.len = s->output.len = 0; |
290 | 299 |
291 // Figure out how fast the machine is | 300 // Figure out how fast the machine is |
292 if(AF_INIT_AUTO == (AF_INIT_TYPE_MASK & s->cfg.force)){ | 301 if(AF_INIT_AUTO == (AF_INIT_TYPE_MASK & s->cfg.force)) |
293 # if defined(HAVE_SSE) || defined(HAVE_3DNOWEX) | 302 s->cfg.force = (s->cfg.force & ~AF_INIT_TYPE_MASK) | AF_INIT_TYPE; |
294 s->cfg.force = (s->cfg.force & ~AF_INIT_TYPE_MASK) | AF_INIT_FAST; | |
295 # else | |
296 s->cfg.force = (s->cfg.force & ~AF_INIT_TYPE_MASK) | AF_INIT_SLOW; | |
297 # endif | |
298 } | |
299 | 303 |
300 // Check if this is the first call | 304 // Check if this is the first call |
301 if(!s->first){ | 305 if(!s->first){ |
302 // Add all filters in the list (if there are any) | 306 // Add all filters in the list (if there are any) |
303 if(!s->cfg.list){ // To make automatic format conversion work | 307 if(!s->cfg.list){ // To make automatic format conversion work |
377 if((s->last->data->format != s->output.format) || | 381 if((s->last->data->format != s->output.format) || |
378 (s->last->data->bps != s->output.bps) || | 382 (s->last->data->bps != s->output.bps) || |
379 (s->last->data->nch != s->output.nch) || | 383 (s->last->data->nch != s->output.nch) || |
380 (s->last->data->rate != s->output.rate)) { | 384 (s->last->data->rate != s->output.rate)) { |
381 // Something is stuffed audio out will not work | 385 // Something is stuffed audio out will not work |
382 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"); | 386 af_msg(AF_MSG_ERROR,"Unable to setup filter system can not meet sound-card demands, please report this error on MPlayer development mailing list. \n"); |
383 af_uninit(s); | 387 af_uninit(s); |
384 return -1; | 388 return -1; |
385 } | 389 } |
386 } | 390 } |
387 return 0; | 391 return 0; |
525 function should not be called directly */ | 529 function should not be called directly */ |
526 inline int af_resize_local_buffer(af_instance_t* af, af_data_t* data) | 530 inline int af_resize_local_buffer(af_instance_t* af, af_data_t* data) |
527 { | 531 { |
528 // Calculate new length | 532 // Calculate new length |
529 register int len = af_lencalc(af->mul,data); | 533 register int len = af_lencalc(af->mul,data); |
530 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); | 534 af_msg(AF_MSG_VERBOSE,"Reallocating memory in module %s, old len = %i, new len = %i\n",af->info->name,af->data->len,len); |
531 // If there is a buffer free it | 535 // If there is a buffer free it |
532 if(af->data->audio) | 536 if(af->data->audio) |
533 free(af->data->audio); | 537 free(af->data->audio); |
534 // Create new buffer and check that it is OK | 538 // Create new buffer and check that it is OK |
535 af->data->audio = malloc(len); | 539 af->data->audio = malloc(len); |
536 if(!af->data->audio){ | 540 if(!af->data->audio){ |
537 mp_msg(MSGT_AFILTER,MSGL_ERR,"Could not allocate memory \n"); | 541 af_msg(AF_MSG_FATAL,"Could not allocate memory \n"); |
538 return AF_ERROR; | 542 return AF_ERROR; |
539 } | 543 } |
540 af->data->len=len; | 544 af->data->len=len; |
541 return AF_OK; | 545 return AF_OK; |
542 } | 546 } |