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 }