Mercurial > mplayer.hg
annotate libaf/af_channels.c @ 36089:d4056035c260
Set file prior to adding to the URL list.
An already existing URL list item won't be added, but the allocated url
string will be freed (which thus can't be uiSetFile() nor be added to
the playlist).
author | ib |
---|---|
date | Mon, 29 Apr 2013 12:10:03 +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 }; |