Mercurial > mplayer.hg
annotate libaf/af_channels.c @ 32777:9cc2689e5cd1
Fix r32587: the previous approach to return subtitles in time broke
DVB subtitles due to returning incomplete packets and even for
PGS subtitles resulted in incorrect pts values for the sub packets.
author | reimar |
---|---|
date | Sun, 06 Feb 2011 13:52:05 +0000 |
parents | 0f1b5b68af32 |
children | a93891202051 |
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 |
28 #include "af.h" | |
29 | |
8607 | 30 #define FR 0 |
31 #define TO 1 | |
32 | |
33 typedef struct af_channels_s{ | |
34 int route[AF_NCH][2]; | |
35 int nr; | |
36 int router; | |
37 }af_channels_t; | |
38 | |
7568 | 39 // Local function for copying data |
8711
906f7a2dc085
sig 11 fix in reinit and resample + spelling error fixes
anders
parents:
8607
diff
changeset
|
40 static void copy(void* in, void* out, int ins, int inos,int outs, int outos, int len, int bps) |
7568 | 41 { |
42 switch(bps){ | |
43 case 1:{ | |
44 int8_t* tin = (int8_t*)in; | |
45 int8_t* tout = (int8_t*)out; | |
46 tin += inos; | |
47 tout += outos; | |
48 len = len/ins; | |
49 while(len--){ | |
50 *tout=*tin; | |
51 tin +=ins; | |
52 tout+=outs; | |
53 } | |
54 break; | |
55 } | |
56 case 2:{ | |
57 int16_t* tin = (int16_t*)in; | |
58 int16_t* tout = (int16_t*)out; | |
59 tin += inos; | |
60 tout += outos; | |
61 len = len/(2*ins); | |
62 while(len--){ | |
63 *tout=*tin; | |
64 tin +=ins; | |
65 tout+=outs; | |
66 } | |
67 break; | |
68 } | |
12913 | 69 case 3:{ |
70 int8_t* tin = (int8_t*)in; | |
71 int8_t* tout = (int8_t*)out; | |
72 tin += 3 * inos; | |
73 tout += 3 * outos; | |
74 len = len / ( 3 * ins); | |
75 while (len--) { | |
76 tout[0] = tin[0]; | |
77 tout[1] = tin[1]; | |
78 tout[2] = tin[2]; | |
79 tin += 3 * ins; | |
80 tout += 3 * outs; | |
81 } | |
82 break; | |
83 } | |
7568 | 84 case 4:{ |
85 int32_t* tin = (int32_t*)in; | |
86 int32_t* tout = (int32_t*)out; | |
87 tin += inos; | |
88 tout += outos; | |
89 len = len/(4*ins); | |
90 while(len--){ | |
91 *tout=*tin; | |
92 tin +=ins; | |
93 tout+=outs; | |
94 } | |
95 break; | |
96 } | |
97 case 8:{ | |
98 int64_t* tin = (int64_t*)in; | |
99 int64_t* tout = (int64_t*)out; | |
100 tin += inos; | |
101 tout += outos; | |
102 len = len/(8*ins); | |
103 while(len--){ | |
104 *tout=*tin; | |
105 tin +=ins; | |
106 tout+=outs; | |
107 } | |
108 break; | |
109 } | |
110 default: | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
111 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] Unsupported number of bytes/sample: %i" |
8607 | 112 " please report this error on the MPlayer mailing list. \n",bps); |
7568 | 113 } |
114 } | |
115 | |
8607 | 116 // Make sure the routes are sane |
117 static int check_routes(af_channels_t* s, int nin, int nout) | |
118 { | |
119 int i; | |
120 if((s->nr < 1) || (s->nr > AF_NCH)){ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
121 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of routing pairs must be" |
8607 | 122 " between 1 and %i. Current value is %i\n",AF_NCH,s->nr); |
123 return AF_ERROR; | |
124 } | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
125 |
8607 | 126 for(i=0;i<s->nr;i++){ |
127 if((s->route[i][FR] >= nin) || (s->route[i][TO] >= nout)){ | |
29049 | 128 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] Invalid routing in pair nr. %i.\n", i); |
8607 | 129 return AF_ERROR; |
130 } | |
131 } | |
132 return AF_OK; | |
133 } | |
134 | |
7568 | 135 // Initialization and runtime control |
136 static int control(struct af_instance_s* af, int cmd, void* arg) | |
137 { | |
8607 | 138 af_channels_t* s = af->setup; |
7568 | 139 switch(cmd){ |
140 case AF_CONTROL_REINIT: | |
8607 | 141 |
142 // Set default channel assignment | |
143 if(!s->router){ | |
144 int i; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
145 // Make sure this filter isn't redundant |
8607 | 146 if(af->data->nch == ((af_data_t*)arg)->nch) |
147 return AF_DETACH; | |
148 | |
149 // If mono: fake stereo | |
150 if(((af_data_t*)arg)->nch == 1){ | |
151 s->nr = min(af->data->nch,2); | |
152 for(i=0;i<s->nr;i++){ | |
153 s->route[i][FR] = 0; | |
154 s->route[i][TO] = i; | |
155 } | |
156 } | |
157 else{ | |
158 s->nr = min(af->data->nch, ((af_data_t*)arg)->nch); | |
159 for(i=0;i<s->nr;i++){ | |
160 s->route[i][FR] = i; | |
161 s->route[i][TO] = i; | |
162 } | |
163 } | |
164 } | |
7568 | 165 |
166 af->data->rate = ((af_data_t*)arg)->rate; | |
167 af->data->format = ((af_data_t*)arg)->format; | |
168 af->data->bps = ((af_data_t*)arg)->bps; | |
24888 | 169 af->mul = (double)af->data->nch / ((af_data_t*)arg)->nch; |
8607 | 170 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
|
171 case AF_CONTROL_COMMAND_LINE:{ |
d48a06d07afb
Adding commandline options for filters and fixing stupid bug in cfg
anders
parents:
7975
diff
changeset
|
172 int nch = 0; |
8607 | 173 int n = 0; |
174 // Check number of channels and number of routing pairs | |
175 sscanf(arg, "%i:%i%n", &nch, &s->nr, &n); | |
176 | |
177 // If router scan commandline for routing pairs | |
178 if(s->nr){ | |
179 char* cp = &((char*)arg)[n]; | |
180 int ch = 0; | |
181 // Sanity check | |
182 if((s->nr < 1) || (s->nr > AF_NCH)){ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
183 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of routing pairs must be" |
8607 | 184 " 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
|
185 } |
8607 | 186 s->router = 1; |
187 // Scan for pairs on commandline | |
188 while((*cp == ':') && (ch < s->nr)){ | |
189 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
|
190 mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Routing from channel %i to" |
8607 | 191 " channel %i\n",s->route[ch][FR],s->route[ch][TO]); |
192 cp = &cp[n]; | |
193 ch++; | |
194 } | |
195 } | |
196 | |
197 if(AF_OK != af->control(af,AF_CONTROL_CHANNELS | AF_CONTROL_SET ,&nch)) | |
198 return AF_ERROR; | |
199 return AF_OK; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
200 } |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
201 case AF_CONTROL_CHANNELS | AF_CONTROL_SET: |
7568 | 202 // Reinit must be called after this function has been called |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
203 |
7568 | 204 // Sanity check |
12008 | 205 if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH){ |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
206 mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of output channels must be" |
8607 | 207 " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]); |
7568 | 208 return AF_ERROR; |
209 } | |
210 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
211 af->data->nch=((int*)arg)[0]; |
8607 | 212 if(!s->router) |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
213 mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Changing number of channels" |
8607 | 214 " to %i\n",af->data->nch); |
215 return AF_OK; | |
216 case AF_CONTROL_CHANNELS | AF_CONTROL_GET: | |
217 *(int*)arg = af->data->nch; | |
218 return AF_OK; | |
219 case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_SET:{ | |
220 int ch = ((af_control_ext_t*)arg)->ch; | |
221 int* route = ((af_control_ext_t*)arg)->arg; | |
222 s->route[ch][FR] = route[FR]; | |
223 s->route[ch][TO] = route[TO]; | |
224 return AF_OK; | |
225 } | |
226 case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_GET:{ | |
227 int ch = ((af_control_ext_t*)arg)->ch; | |
228 int* route = ((af_control_ext_t*)arg)->arg; | |
229 route[FR] = s->route[ch][FR]; | |
230 route[TO] = s->route[ch][TO]; | |
231 return AF_OK; | |
232 } | |
233 case AF_CONTROL_CHANNELS_NR | AF_CONTROL_SET: | |
234 s->nr = *(int*)arg; | |
235 return AF_OK; | |
236 case AF_CONTROL_CHANNELS_NR | AF_CONTROL_GET: | |
237 *(int*)arg = s->nr; | |
238 return AF_OK; | |
239 case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_SET: | |
240 s->router = *(int*)arg; | |
241 return AF_OK; | |
242 case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_GET: | |
243 *(int*)arg = s->router; | |
7568 | 244 return AF_OK; |
245 } | |
246 return AF_UNKNOWN; | |
247 } | |
248 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
249 // Deallocate memory |
7568 | 250 static void uninit(struct af_instance_s* af) |
251 { | |
22179 | 252 free(af->setup); |
253 if (af->data) | |
254 free(af->data->audio); | |
255 free(af->data); | |
7568 | 256 } |
257 | |
258 // Filter data through filter | |
259 static af_data_t* play(struct af_instance_s* af, af_data_t* data) | |
260 { | |
8607 | 261 af_data_t* c = data; // Current working data |
262 af_data_t* l = af->data; // Local data | |
263 af_channels_t* s = af->setup; | |
264 int i; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
265 |
7568 | 266 if(AF_OK != RESIZE_LOCAL_BUFFER(af,data)) |
267 return NULL; | |
268 | |
8607 | 269 // Reset unused channels |
24888 | 270 memset(l->audio,0,c->len / c->nch * l->nch); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
271 |
8607 | 272 if(AF_OK == check_routes(s,c->nch,l->nch)) |
273 for(i=0;i<s->nr;i++) | |
274 copy(c->audio,l->audio,c->nch,s->route[i][FR], | |
275 l->nch,s->route[i][TO],c->len,c->bps); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
29049
diff
changeset
|
276 |
7568 | 277 // Set output data |
278 c->audio = l->audio; | |
24888 | 279 c->len = c->len / c->nch * l->nch; |
7568 | 280 c->nch = l->nch; |
281 | |
282 return c; | |
283 } | |
284 | |
285 // 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
|
286 static int af_open(af_instance_t* af){ |
7568 | 287 af->control=control; |
288 af->uninit=uninit; | |
289 af->play=play; | |
24888 | 290 af->mul=1; |
7568 | 291 af->data=calloc(1,sizeof(af_data_t)); |
8607 | 292 af->setup=calloc(1,sizeof(af_channels_t)); |
293 if((af->data == NULL) || (af->setup == NULL)) | |
7568 | 294 return AF_ERROR; |
295 return AF_OK; | |
296 } | |
297 | |
298 // Description of this filter | |
299 af_info_t af_info_channels = { | |
300 "Insert or remove channels", | |
301 "channels", | |
302 "Anders", | |
303 "", | |
7615 | 304 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
|
305 af_open |
7568 | 306 }; |