Mercurial > mplayer.hg
annotate libaf/af_format.c @ 8027:b9da278e4c92
verbose can be negative
author | arpi |
---|---|
date | Fri, 01 Nov 2002 17:46:45 +0000 |
parents | d48a06d07afb |
children | e8832e66babd |
rev | line source |
---|---|
7568 | 1 /* This audio output filter changes the format of a data block. Valid |
2 formats are: AFMT_U8, AFMT_S8, AFMT_S16_LE, AFMT_S16_BE | |
3 AFMT_U16_LE, AFMT_U16_BE, AFMT_S32_LE and AFMT_S32_BE. | |
4 */ | |
5 | |
6 #include <stdio.h> | |
7 #include <stdlib.h> | |
8 #include <string.h> | |
9 #include <unistd.h> | |
10 #include <inttypes.h> | |
11 #include <limits.h> | |
12 | |
13 #include "../config.h" | |
14 #include "../mp_msg.h" | |
15 | |
16 #include "../libao2/afmt.h" | |
17 | |
18 #include "af.h" | |
19 | |
20 // Number of bits | |
21 #define B08 (0<<0) | |
22 #define B16 (1<<0) | |
23 #define B32 (2<<0) | |
24 #define NBITS_MASK (3<<0) | |
25 | |
26 // Endianess | |
27 #define BE (0<<2) // Big Endian | |
28 #define LE (1<<2) // Little Endian | |
29 #define END_MASK (1<<2) | |
30 | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
31 #if WORDS_BIGENDIAN // native endian of cpu |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
32 #define NE BE |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
33 #else |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
34 #define NE LE |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
35 #endif |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
36 |
7568 | 37 // Signed |
38 #define US (0<<3) // Un Signed | |
39 #define SI (1<<3) // SIgned | |
40 #define SIGN_MASK (1<<3) | |
41 | |
42 int decode(int format) | |
43 { | |
44 // Check input format | |
45 switch(format){ | |
46 case(AFMT_U8): | |
47 return LE|B08|US; | |
48 case(AFMT_S8): | |
49 return LE|B08|SI; break; | |
50 case(AFMT_S16_LE): | |
51 return LE|B16|SI; break; | |
52 case(AFMT_S16_BE): | |
53 return BE|B16|SI; break; | |
54 case(AFMT_U16_LE): | |
55 return LE|B16|US; break; | |
56 case(AFMT_U16_BE): | |
57 return BE|B16|US; break; | |
58 case(AFMT_S32_LE): | |
59 return LE|B32|SI; break; | |
60 case(AFMT_S32_BE): | |
61 return BE|B32|SI; break; | |
62 case(AFMT_IMA_ADPCM): | |
63 case(AFMT_MU_LAW): | |
64 case(AFMT_A_LAW): | |
65 case(AFMT_MPEG): | |
66 case(AFMT_AC3): | |
67 mp_msg(MSGT_AFILTER,MSGL_ERR,"[af_format] Input audio format not yet supported \n"); | |
68 return 0; | |
69 default: | |
70 //This can not happen .... | |
71 mp_msg(MSGT_AFILTER,MSGL_ERR,"Unrecognized input audio format\n"); | |
72 return 0; | |
73 } | |
74 | |
75 } | |
76 | |
77 // Initialization and runtime control | |
78 static int control(struct af_instance_s* af, int cmd, void* arg) | |
79 { | |
80 switch(cmd){ | |
81 case AF_CONTROL_REINIT: | |
82 // Make sure this filter isn't redundant | |
83 if(af->data->format == ((af_data_t*)arg)->format && af->data->bps == ((af_data_t*)arg)->bps) | |
84 return AF_DETACH; | |
85 | |
86 af->data->rate = ((af_data_t*)arg)->rate; | |
87 af->data->nch = ((af_data_t*)arg)->nch; | |
88 af->mul.n = af->data->bps; | |
89 af->mul.d = ((af_data_t*)arg)->bps; | |
90 return AF_OK; | |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
91 case AF_CONTROL_COMMAND_LINE:{ |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
92 af_data_t d; |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
93 sscanf((char*)arg,"%i:%i",&(d.format),&(d.bps)); |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
94 return af->control(af,AF_CONTROL_FORMAT,&d); |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7719
diff
changeset
|
95 } |
7568 | 96 case AF_CONTROL_FORMAT: |
97 // Reinit must be called after this function has been called | |
98 | |
99 // Sanity check for sample format | |
100 if(0 == ((int)af->setup=decode(((af_data_t*)arg)->format))) | |
101 return AF_ERROR; | |
102 af->data->format = ((af_data_t*)arg)->format; | |
103 | |
104 // Sanity check for bytes per sample | |
105 if(((af_data_t*)arg)->bps != 4 && ((af_data_t*)arg)->bps != 2 && ((af_data_t*)arg)->bps != 1){ | |
106 mp_msg(MSGT_AFILTER,MSGL_ERR,"[format] The number of output bytes per sample must be 1, 2 or 4. Current value is%i \n",((af_data_t*)arg)->bps); | |
107 return AF_ERROR; | |
108 } | |
109 af->data->bps=((af_data_t*)arg)->bps; | |
110 | |
7571
8819fdf88b5d
Adding support for multiple audio streams and removing annoying message from resample and format
anders
parents:
7568
diff
changeset
|
111 mp_msg(MSGT_AFILTER,MSGL_V,"[format] Changing number sample format to 0x%08X and/or bytes per sample to %i \n",af->data->format,af->data->bps); |
7568 | 112 return AF_OK; |
113 } | |
114 return AF_UNKNOWN; | |
115 } | |
116 | |
117 // Deallocate memory | |
118 static void uninit(struct af_instance_s* af) | |
119 { | |
120 if(af->data) | |
121 free(af->data); | |
122 (int)af->setup = 0; | |
123 } | |
124 | |
125 // Filter data through filter | |
126 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
127 { | |
128 af_data_t* l = af->data; // Local data | |
129 void* la = NULL; // Local audio | |
130 int lf = (int)af->setup; // Local format | |
131 af_data_t* c = data; // Current working data | |
132 void* ca = c->audio; // Current audio | |
133 int cf = decode(c->format); // Current format | |
134 register int i = 0; // Counter | |
135 int len = c->len>>(cf&NBITS_MASK); // Loop end | |
136 | |
137 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) | |
138 return NULL; | |
139 | |
140 la = l->audio; | |
141 | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
142 // Change to cpu native endian |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
143 if((cf&END_MASK)!=NE){ |
7568 | 144 switch(cf&NBITS_MASK){ |
145 case(B16):{ | |
146 register uint16_t s; | |
7711 | 147 for(i=0;i<len;i++){ |
7568 | 148 s=((uint16_t*)ca)[i]; |
149 ((uint16_t*)ca)[i]=(uint16_t)(((s&0x00FF)<<8) | (s&0xFF00)>>8); | |
150 } | |
151 } | |
152 break; | |
153 case(B32):{ | |
154 register uint32_t s; | |
7711 | 155 for(i=0;i<len;i++){ |
7568 | 156 s=((uint32_t*)ca)[i]; |
157 ((uint32_t*)ca)[i]=(uint32_t)(((s&0x000000FF)<<24) | ((s&0x0000FF00)<<8) | | |
158 ((s&0x00FF0000)>>8) | ((s&0xFF000000)>>24)); | |
159 } | |
160 } | |
161 break; | |
162 } | |
163 } | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
164 |
7568 | 165 // Change signed/unsigned |
166 if((cf&SIGN_MASK) != (lf&SIGN_MASK)){ | |
167 switch((cf&NBITS_MASK)){ | |
168 case(B08): | |
169 switch(cf&SIGN_MASK){ | |
170 case(US): | |
171 for(i=0;i<len;i++) | |
172 ((int8_t*)ca)[i]=(int8_t)(SCHAR_MIN+((int)((uint8_t*)ca)[i])); | |
173 break; | |
174 case(SI): | |
175 for(i=0;i<len;i++) | |
176 ((uint8_t*)ca)[i]=(uint8_t)(SCHAR_MAX+((int)((int8_t*)ca)[i])); | |
177 break; | |
178 } | |
179 break; | |
180 case(B16): | |
181 switch(cf&SIGN_MASK){ | |
182 case(US): | |
183 for(i=0;i<len;i++) | |
184 ((int16_t*)ca)[i]=(int16_t)(SHRT_MIN+((int)((uint16_t*)ca)[i])); | |
185 break; | |
186 case(SI): | |
187 for(i=0;i<len;i++) | |
188 ((uint16_t*)ca)[i]=(uint16_t)(SHRT_MAX+((int)((int16_t*)ca)[i])); | |
189 break; | |
190 } | |
191 break; | |
192 case(B32): | |
193 switch(cf&SIGN_MASK){ | |
194 case(US): | |
195 for(i=0;i<len;i++) | |
196 ((int32_t*)ca)[i]=(int32_t)(INT_MIN+((uint32_t*)ca)[i]); | |
197 break; | |
198 case(SI): | |
199 for(i=0;i<len;i++) | |
200 ((uint32_t*)ca)[i]=(uint32_t)(INT_MAX+((int32_t*)ca)[i]); | |
201 break; | |
202 } | |
203 break; | |
204 } | |
205 } | |
206 // Change the number of bits | |
207 if((cf&NBITS_MASK) == (lf&NBITS_MASK)){ | |
208 memcpy(la,ca,c->len); | |
209 } else { | |
210 switch(cf&NBITS_MASK){ | |
211 case(B08): | |
212 switch(lf&NBITS_MASK){ | |
213 case(B16): | |
7711 | 214 for(i=0;i<len;i++) |
7568 | 215 ((uint16_t*)la)[i]=((uint16_t)((uint8_t*)ca)[i])<<8; |
216 break; | |
217 case(B32): | |
7711 | 218 for(i=0;i<len;i++) |
7568 | 219 ((uint32_t*)la)[i]=((uint32_t)((uint8_t*)ca)[i])<<24; |
220 break; | |
221 } | |
222 break; | |
223 case(B16): | |
224 switch(lf&NBITS_MASK){ | |
225 case(B08): | |
226 for(i=0;i<len;i++) | |
227 ((uint8_t*)la)[i]=(uint8_t)((((uint16_t*)ca)[i])>>8); | |
228 break; | |
229 case(B32): | |
7711 | 230 for(i=0;i<len;i++) |
7568 | 231 ((uint32_t*)la)[i]=((uint32_t)((uint16_t*)ca)[i])<<16; |
232 break; | |
233 } | |
234 break; | |
235 case(B32): | |
236 switch(lf&NBITS_MASK){ | |
237 case(B08): | |
238 for(i=0;i<len;i++) | |
239 ((uint8_t*)la)[i]=(uint8_t)((((uint32_t*)ca)[i])>>24); | |
240 break; | |
241 case(B16): | |
7711 | 242 for(i=0;i<len;i++) |
7568 | 243 ((uint16_t*)la)[i]=(uint16_t)((((uint32_t*)ca)[i])>>16); |
244 break; | |
245 } | |
246 break; | |
247 } | |
248 } | |
7719
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
249 |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
250 // Switch from cpu native endian to the correct endianess |
41e8d0916c60
Fix for audio filters on big endian cpus. It's working now on Solaris SPARC &
jkeil
parents:
7711
diff
changeset
|
251 if((lf&END_MASK)!=NE){ |
7711 | 252 switch(lf&NBITS_MASK){ |
7568 | 253 case(B16):{ |
254 register uint16_t s; | |
7711 | 255 for(i=0;i<len;i++){ |
7568 | 256 s=((uint16_t*)la)[i]; |
257 ((uint16_t*)la)[i]=(uint16_t)(((s&0x00FF)<<8) | (s&0xFF00)>>8); | |
258 } | |
259 } | |
260 break; | |
261 case(B32):{ | |
262 register uint32_t s; | |
7711 | 263 for(i=0;i<len;i++){ |
7568 | 264 s=((uint32_t*)la)[i]; |
265 ((uint32_t*)la)[i]=(uint32_t)(((s&0x000000FF)<<24) | ((s&0x0000FF00)<<8) | | |
266 ((s&0x00FF0000)>>8) | ((s&0xFF000000)>>24)); | |
267 } | |
268 } | |
269 break; | |
270 } | |
271 } | |
272 | |
273 // Set output data | |
274 | |
275 // Make sure no samples are lost | |
276 c->len = (c->len*l->bps)/c->bps; | |
277 c->audio = l->audio; | |
278 c->bps = l->bps; | |
279 c->format = l->format; | |
280 return c; | |
281 } | |
282 | |
283 // Allocate memory and set function pointers | |
284 static int open(af_instance_t* af){ | |
285 af->control=control; | |
286 af->uninit=uninit; | |
287 af->play=play; | |
288 af->mul.n=1; | |
289 af->mul.d=1; | |
290 af->data=calloc(1,sizeof(af_data_t)); | |
291 if(af->data == NULL) | |
292 return AF_ERROR; | |
293 (int)af->setup = 0; | |
294 return AF_OK; | |
295 } | |
296 | |
297 // Description of this filter | |
298 af_info_t af_info_format = { | |
299 "Sample format conversion", | |
300 "format", | |
301 "Anders", | |
302 "", | |
7615 | 303 AF_FLAGS_REENTRANT, |
7568 | 304 open |
305 }; |