Mercurial > mplayer.hg
annotate libaf/af_channels.c @ 35063:600e92b2d809
sync with en/mplayer.1 rev. 35156
author | jrash |
---|---|
date | Sat, 08 Sep 2012 10:37:14 +0000 |
parents | a93891202051 |
children | 2b9bc3c2933d |
rev | line source |
---|---|
28229
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
1 /* |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
2 * Audio filter that adds and removes channels, according to the |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
3 * command line parameter channels. It is stupid and can only add |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
4 * silence or copy channels, not mix or filter. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
5 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
6 * This file is part of MPlayer. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
7 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
8 * MPlayer is free software; you can redistribute it and/or modify |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
11 * (at your option) any later version. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
12 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
13 * MPlayer is distributed in the hope that it will be useful, |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
16 * GNU General Public License for more details. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
17 * |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
18 * You should have received a copy of the GNU General Public License along |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
19 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
21 */ |
72d0b1444141
Replace informal license notices by standard license header
diego
parents:
24888
diff
changeset
|
22 |
7568 | 23 #include <stdio.h> |
24 #include <stdlib.h> | |
25 #include <string.h> | |
7975 | 26 #include <inttypes.h> |
7568 | 27 |
34174
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
29263
diff
changeset
|
28 #include "mp_msg.h" |
7568 | 29 #include "af.h" |
30 | |
8607 | 31 #define FR 0 |
32 #define TO 1 | |
33 | |
34 typedef struct af_channels_s{ | |
35 int route[AF_NCH][2]; | |
36 int nr; | |
37 int router; | |
38 }af_channels_t; | |
39 | |
7568 | 40 // Local function for copying data |
8711
906f7a2dc085
sig 11 fix in reinit and resample + spelling error fixes
anders
parents:
8607
diff
changeset
|
41 static void copy(void* in, void* out, int ins, int inos,int outs, int outos, int len, int bps) |
7568 | 42 { |
43 switch(bps){ | |
44 case 1:{ | |
45 int8_t* tin = (int8_t*)in; | |
46 int8_t* tout = (int8_t*)out; | |
47 tin += inos; | |
48 tout += outos; | |
49 len = len/ins; | |
50 while(len--){ | |
51 *tout=*tin; | |
52 tin +=ins; | |
53 tout+=outs; | |
54 } | |
55 break; | |
56 } | |
57 case 2:{ | |
58 int16_t* tin = (int16_t*)in; | |
59 int16_t* tout = (int16_t*)out; | |
60 tin += inos; | |
61 tout += outos; | |
62 len = len/(2*ins); | |
63 while(len--){ | |
64 *tout=*tin; | |
65 tin +=ins; | |
66 tout+=outs; | |
67 } | |
68 break; | |
69 } | |
12913 | 70 case 3:{ |
71 int8_t* tin = (int8_t*)in; | |
72 int8_t* tout = (int8_t*)out; | |
73 tin += 3 * inos; | |
74 tout += 3 * outos; | |
75 len = len / ( 3 * ins); | |
76 while (len--) { | |
77 tout[0] = tin[0]; | |
78 tout[1] = tin[1]; | |
79 tout[2] = tin[2]; | |
80 tin += 3 * ins; | |
81 tout += 3 * outs; | |
82 } | |
83 break; | |
84 } | |
7568 | 85 case 4:{ |
86 int32_t* tin = (int32_t*)in; | |
87 int32_t* tout = (int32_t*)out; | |
88 tin += inos; | |
89 tout += outos; | |
90 len = len/(4*ins); | |
91 while(len--){ | |
92 *tout=*tin; | |
93 tin +=ins; | |
94 tout+=outs; | |
95 } | |
96 break; | |
97 } | |
98 case 8:{ | |
99 int64_t* tin = (int64_t*)in; | |
100 int64_t* tout = (int64_t*)out; | |
101 tin += inos; | |
102 tout += outos; | |
103 len = len/(8*ins); | |
104 while(len--){ | |
105 *tout=*tin; | |
106 tin +=ins; | |
107 tout+=outs; | |
108 } | |
109 break; | |
110 } | |
111 default: | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
112 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] Unsupported number of bytes/sample: %i" |
8607 | 113 " please report this error on the MPlayer mailing list. \n",bps); |
7568 | 114 } |
115 } | |
116 | |
8607 | 117 // Make sure the routes are sane |
118 static int check_routes(af_channels_t* s, int nin, int nout) | |
119 { | |
120 int i; | |
121 if((s->nr < 1) || (s->nr > AF_NCH)){ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
122 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of routing pairs must be" |
8607 | 123 " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); |
124 return AF_ERROR; | |
125 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
126 |
8607 | 127 for(i=0;i<s->nr;i++){ |
128 if((s->route[i][FR] >= nin) || (s->route[i][TO] >= nout)){ | |
29049 | 129 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] Invalid routing in pair nr. %i.\n", i); |
8607 | 130 return AF_ERROR; |
131 } | |
132 } | |
133 return AF_OK; | |
134 } | |
135 | |
7568 | 136 // Initialization and runtime control |
137 static int control(struct af_instance_s* af, int cmd, void* arg) | |
138 { | |
8607 | 139 af_channels_t* s = af->setup; |
7568 | 140 switch(cmd){ |
141 case AF_CONTROL_REINIT: | |
8607 | 142 |
143 // Set default channel assignment | |
144 if(!s->router){ | |
145 int i; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
146 // Make sure this filter isn't redundant |
8607 | 147 if(af->data->nch == ((af_data_t*)arg)->nch) |
148 return AF_DETACH; | |
149 | |
150 // If mono: fake stereo | |
151 if(((af_data_t*)arg)->nch == 1){ | |
152 s->nr = min(af->data->nch,2); | |
153 for(i=0;i<s->nr;i++){ | |
154 s->route[i][FR] = 0; | |
155 s->route[i][TO] = i; | |
156 } | |
157 } | |
158 else{ | |
159 s->nr = min(af->data->nch, ((af_data_t*)arg)->nch); | |
160 for(i=0;i<s->nr;i++){ | |
161 s->route[i][FR] = i; | |
162 s->route[i][TO] = i; | |
163 } | |
164 } | |
165 } | |
7568 | 166 |
167 af->data->rate = ((af_data_t*)arg)->rate; | |
168 af->data->format = ((af_data_t*)arg)->format; | |
169 af->data->bps = ((af_data_t*)arg)->bps; | |
24888 | 170 af->mul = (double)af->data->nch / ((af_data_t*)arg)->nch; |
8607 | 171 return check_routes(s,((af_data_t*)arg)->nch,af->data->nch); |
7998
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
172 case AF_CONTROL_COMMAND_LINE:{ |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
173 int nch = 0; |
8607 | 174 int n = 0; |
175 // Check number of channels and number of routing pairs | |
176 sscanf(arg, "%i:%i%n", &nch, &s->nr, &n); | |
177 | |
178 // If router scan commandline for routing pairs | |
179 if(s->nr){ | |
180 char* cp = &((char*)arg)[n]; | |
181 int ch = 0; | |
182 // Sanity check | |
183 if((s->nr < 1) || (s->nr > AF_NCH)){ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
184 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of routing pairs must be" |
8607 | 185 " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
186 } |
8607 | 187 s->router = 1; |
188 // Scan for pairs on commandline | |
189 while((*cp == ':') && (ch < s->nr)){ | |
190 sscanf(cp, ":%i:%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
191 mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Routing from channel %i to" |
8607 | 192 " channel %i\n",s->route[ch][FR],s->route[ch][TO]); |
193 cp = &cp[n]; | |
194 ch++; | |
195 } | |
196 } | |
197 | |
198 if(AF_OK != af->control(af,AF_CONTROL_CHANNELS | AF_CONTROL_SET ,&nch)) | |
199 return AF_ERROR; | |
200 return AF_OK; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
201 } |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
202 case AF_CONTROL_CHANNELS | AF_CONTROL_SET: |
7568 | 203 // Reinit must be called after this function has been called |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
204 |
7568 | 205 // Sanity check |
12008 | 206 if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH){ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
207 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of output channels must be" |
8607 | 208 " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]); |
7568 | 209 return AF_ERROR; |
210 } | |
211 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
212 af->data->nch=((int*)arg)[0]; |
8607 | 213 if(!s->router) |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
214 mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Changing number of channels" |
8607 | 215 " to %i\n",af->data->nch); |
216 return AF_OK; | |
217 case AF_CONTROL_CHANNELS | AF_CONTROL_GET: | |
218 *(int*)arg = af->data->nch; | |
219 return AF_OK; | |
220 case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_SET:{ | |
221 int ch = ((af_control_ext_t*)arg)->ch; | |
222 int* route = ((af_control_ext_t*)arg)->arg; | |
223 s->route[ch][FR] = route[FR]; | |
224 s->route[ch][TO] = route[TO]; | |
225 return AF_OK; | |
226 } | |
227 case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_GET:{ | |
228 int ch = ((af_control_ext_t*)arg)->ch; | |
229 int* route = ((af_control_ext_t*)arg)->arg; | |
230 route[FR] = s->route[ch][FR]; | |
231 route[TO] = s->route[ch][TO]; | |
232 return AF_OK; | |
233 } | |
234 case AF_CONTROL_CHANNELS_NR | AF_CONTROL_SET: | |
235 s->nr = *(int*)arg; | |
236 return AF_OK; | |
237 case AF_CONTROL_CHANNELS_NR | AF_CONTROL_GET: | |
238 *(int*)arg = s->nr; | |
239 return AF_OK; | |
240 case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_SET: | |
241 s->router = *(int*)arg; | |
242 return AF_OK; | |
243 case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_GET: | |
244 *(int*)arg = s->router; | |
7568 | 245 return AF_OK; |
246 } | |
247 return AF_UNKNOWN; | |
248 } | |
249 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
250 // Deallocate memory |
7568 | 251 static void uninit(struct af_instance_s* af) |
252 { | |
22179 | 253 free(af->setup); |
254 if (af->data) | |
255 free(af->data->audio); | |
256 free(af->data); | |
7568 | 257 } |
258 | |
259 // Filter data through filter | |
260 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
261 { | |
8607 | 262 af_data_t* c = data; // Current working data |
263 af_data_t* l = af->data; // Local data | |
264 af_channels_t* s = af->setup; | |
265 int i; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
266 |
7568 | 267 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) |
268 return NULL; | |
269 | |
8607 | 270 // Reset unused channels |
24888 | 271 memset(l->audio,0,c->len / c->nch * l->nch); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
272 |
8607 | 273 if(AF_OK == check_routes(s,c->nch,l->nch)) |
274 for(i=0;i<s->nr;i++) | |
275 copy(c->audio,l->audio,c->nch,s->route[i][FR], | |
276 l->nch,s->route[i][TO],c->len,c->bps); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
277 |
7568 | 278 // Set output data |
279 c->audio = l->audio; | |
24888 | 280 c->len = c->len / c->nch * l->nch; |
7568 | 281 c->nch = l->nch; |
282 | |
283 return c; | |
284 } | |
285 | |
286 // Allocate memory and set function pointers | |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22179
diff
changeset
|
287 static int af_open(af_instance_t* af){ |
7568 | 288 af->control=control; |
289 af->uninit=uninit; | |
290 af->play=play; | |
24888 | 291 af->mul=1; |
7568 | 292 af->data=calloc(1,sizeof(af_data_t)); |
8607 | 293 af->setup=calloc(1,sizeof(af_channels_t)); |
294 if((af->data == NULL) || (af->setup == NULL)) | |
7568 | 295 return AF_ERROR; |
296 return AF_OK; | |
297 } | |
298 | |
299 // Description of this filter | |
300 af_info_t af_info_channels = { | |
301 "Insert or remove channels", | |
302 "channels", | |
303 "Anders", | |
304 "", | |
7615 | 305 AF_FLAGS_REENTRANT, |
22746
fd6f824ef894
Rename open to af_open so as not to conflict with a previous header definition.
diego
parents:
22179
diff
changeset
|
306 af_open |
7568 | 307 }; |