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