PageRenderTime 42ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/libaf/af_channels.c

https://github.com/error454/mplayer-webos
C | 307 lines | 244 code | 24 blank | 39 comment | 33 complexity | 76d0f92bef7881c6dcb69364597431e8 MD5 | raw file
  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. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <inttypes.h>
  26. #include "mp_msg.h"
  27. #include "af.h"
  28. #define FR 0
  29. #define TO 1
  30. typedef struct af_channels_s{
  31. int route[AF_NCH][2];
  32. int nr;
  33. int router;
  34. }af_channels_t;
  35. // Local function for copying data
  36. static void copy(void* in, void* out, int ins, int inos,int outs, int outos, int len, int bps)
  37. {
  38. switch(bps){
  39. case 1:{
  40. int8_t* tin = (int8_t*)in;
  41. int8_t* tout = (int8_t*)out;
  42. tin += inos;
  43. tout += outos;
  44. len = len/ins;
  45. while(len--){
  46. *tout=*tin;
  47. tin +=ins;
  48. tout+=outs;
  49. }
  50. break;
  51. }
  52. case 2:{
  53. int16_t* tin = (int16_t*)in;
  54. int16_t* tout = (int16_t*)out;
  55. tin += inos;
  56. tout += outos;
  57. len = len/(2*ins);
  58. while(len--){
  59. *tout=*tin;
  60. tin +=ins;
  61. tout+=outs;
  62. }
  63. break;
  64. }
  65. case 3:{
  66. int8_t* tin = (int8_t*)in;
  67. int8_t* tout = (int8_t*)out;
  68. tin += 3 * inos;
  69. tout += 3 * outos;
  70. len = len / ( 3 * ins);
  71. while (len--) {
  72. tout[0] = tin[0];
  73. tout[1] = tin[1];
  74. tout[2] = tin[2];
  75. tin += 3 * ins;
  76. tout += 3 * outs;
  77. }
  78. break;
  79. }
  80. case 4:{
  81. int32_t* tin = (int32_t*)in;
  82. int32_t* tout = (int32_t*)out;
  83. tin += inos;
  84. tout += outos;
  85. len = len/(4*ins);
  86. while(len--){
  87. *tout=*tin;
  88. tin +=ins;
  89. tout+=outs;
  90. }
  91. break;
  92. }
  93. case 8:{
  94. int64_t* tin = (int64_t*)in;
  95. int64_t* tout = (int64_t*)out;
  96. tin += inos;
  97. tout += outos;
  98. len = len/(8*ins);
  99. while(len--){
  100. *tout=*tin;
  101. tin +=ins;
  102. tout+=outs;
  103. }
  104. break;
  105. }
  106. default:
  107. mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] Unsupported number of bytes/sample: %i"
  108. " please report this error on the MPlayer mailing list. \n",bps);
  109. }
  110. }
  111. // Make sure the routes are sane
  112. static int check_routes(af_channels_t* s, int nin, int nout)
  113. {
  114. int i;
  115. if((s->nr < 1) || (s->nr > AF_NCH)){
  116. mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of routing pairs must be"
  117. " between 1 and %i. Current value is %i\n",AF_NCH,s->nr);
  118. return AF_ERROR;
  119. }
  120. for(i=0;i<s->nr;i++){
  121. if((s->route[i][FR] >= nin) || (s->route[i][TO] >= nout)){
  122. mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] Invalid routing in pair nr. %i.\n", i);
  123. return AF_ERROR;
  124. }
  125. }
  126. return AF_OK;
  127. }
  128. // Initialization and runtime control
  129. static int control(struct af_instance_s* af, int cmd, void* arg)
  130. {
  131. af_channels_t* s = af->setup;
  132. switch(cmd){
  133. case AF_CONTROL_REINIT:
  134. // Set default channel assignment
  135. if(!s->router){
  136. int i;
  137. // Make sure this filter isn't redundant
  138. if(af->data->nch == ((af_data_t*)arg)->nch)
  139. return AF_DETACH;
  140. // If mono: fake stereo
  141. if(((af_data_t*)arg)->nch == 1){
  142. s->nr = min(af->data->nch,2);
  143. for(i=0;i<s->nr;i++){
  144. s->route[i][FR] = 0;
  145. s->route[i][TO] = i;
  146. }
  147. }
  148. else{
  149. s->nr = min(af->data->nch, ((af_data_t*)arg)->nch);
  150. for(i=0;i<s->nr;i++){
  151. s->route[i][FR] = i;
  152. s->route[i][TO] = i;
  153. }
  154. }
  155. }
  156. af->data->rate = ((af_data_t*)arg)->rate;
  157. af->data->format = ((af_data_t*)arg)->format;
  158. af->data->bps = ((af_data_t*)arg)->bps;
  159. af->mul = (double)af->data->nch / ((af_data_t*)arg)->nch;
  160. return check_routes(s,((af_data_t*)arg)->nch,af->data->nch);
  161. case AF_CONTROL_COMMAND_LINE:{
  162. int nch = 0;
  163. int n = 0;
  164. // Check number of channels and number of routing pairs
  165. sscanf(arg, "%i:%i%n", &nch, &s->nr, &n);
  166. // If router scan commandline for routing pairs
  167. if(s->nr){
  168. char* cp = &((char*)arg)[n];
  169. int ch = 0;
  170. // Sanity check
  171. if((s->nr < 1) || (s->nr > AF_NCH)){
  172. mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of routing pairs must be"
  173. " between 1 and %i. Current value is %i\n",AF_NCH,s->nr);
  174. }
  175. s->router = 1;
  176. // Scan for pairs on commandline
  177. while((*cp == ':') && (ch < s->nr)){
  178. sscanf(cp, ":%i:%i%n" ,&s->route[ch][FR], &s->route[ch][TO], &n);
  179. mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Routing from channel %i to"
  180. " channel %i\n",s->route[ch][FR],s->route[ch][TO]);
  181. cp = &cp[n];
  182. ch++;
  183. }
  184. }
  185. if(AF_OK != af->control(af,AF_CONTROL_CHANNELS | AF_CONTROL_SET ,&nch))
  186. return AF_ERROR;
  187. return AF_OK;
  188. }
  189. case AF_CONTROL_CHANNELS | AF_CONTROL_SET:
  190. // Reinit must be called after this function has been called
  191. // Sanity check
  192. if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH){
  193. mp_msg(MSGT_AFILTER, MSGL_ERR, "[channels] The number of output channels must be"
  194. " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]);
  195. return AF_ERROR;
  196. }
  197. af->data->nch=((int*)arg)[0];
  198. if(!s->router)
  199. mp_msg(MSGT_AFILTER, MSGL_V, "[channels] Changing number of channels"
  200. " to %i\n",af->data->nch);
  201. return AF_OK;
  202. case AF_CONTROL_CHANNELS | AF_CONTROL_GET:
  203. *(int*)arg = af->data->nch;
  204. return AF_OK;
  205. case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_SET:{
  206. int ch = ((af_control_ext_t*)arg)->ch;
  207. int* route = ((af_control_ext_t*)arg)->arg;
  208. s->route[ch][FR] = route[FR];
  209. s->route[ch][TO] = route[TO];
  210. return AF_OK;
  211. }
  212. case AF_CONTROL_CHANNELS_ROUTING | AF_CONTROL_GET:{
  213. int ch = ((af_control_ext_t*)arg)->ch;
  214. int* route = ((af_control_ext_t*)arg)->arg;
  215. route[FR] = s->route[ch][FR];
  216. route[TO] = s->route[ch][TO];
  217. return AF_OK;
  218. }
  219. case AF_CONTROL_CHANNELS_NR | AF_CONTROL_SET:
  220. s->nr = *(int*)arg;
  221. return AF_OK;
  222. case AF_CONTROL_CHANNELS_NR | AF_CONTROL_GET:
  223. *(int*)arg = s->nr;
  224. return AF_OK;
  225. case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_SET:
  226. s->router = *(int*)arg;
  227. return AF_OK;
  228. case AF_CONTROL_CHANNELS_ROUTER | AF_CONTROL_GET:
  229. *(int*)arg = s->router;
  230. return AF_OK;
  231. }
  232. return AF_UNKNOWN;
  233. }
  234. // Deallocate memory
  235. static void uninit(struct af_instance_s* af)
  236. {
  237. free(af->setup);
  238. if (af->data)
  239. free(af->data->audio);
  240. free(af->data);
  241. }
  242. // Filter data through filter
  243. static af_data_t* play(struct af_instance_s* af, af_data_t* data)
  244. {
  245. af_data_t* c = data; // Current working data
  246. af_data_t* l = af->data; // Local data
  247. af_channels_t* s = af->setup;
  248. int i;
  249. if(AF_OK != RESIZE_LOCAL_BUFFER(af,data))
  250. return NULL;
  251. // Reset unused channels
  252. memset(l->audio,0,c->len / c->nch * l->nch);
  253. if(AF_OK == check_routes(s,c->nch,l->nch))
  254. for(i=0;i<s->nr;i++)
  255. copy(c->audio,l->audio,c->nch,s->route[i][FR],
  256. l->nch,s->route[i][TO],c->len,c->bps);
  257. // Set output data
  258. c->audio = l->audio;
  259. c->len = c->len / c->nch * l->nch;
  260. c->nch = l->nch;
  261. return c;
  262. }
  263. // Allocate memory and set function pointers
  264. static int af_open(af_instance_t* af){
  265. af->control=control;
  266. af->uninit=uninit;
  267. af->play=play;
  268. af->mul=1;
  269. af->data=calloc(1,sizeof(af_data_t));
  270. af->setup=calloc(1,sizeof(af_channels_t));
  271. if((af->data == NULL) || (af->setup == NULL))
  272. return AF_ERROR;
  273. return AF_OK;
  274. }
  275. // Description of this filter
  276. af_info_t af_info_channels = {
  277. "Insert or remove channels",
  278. "channels",
  279. "Anders",
  280. "",
  281. AF_FLAGS_REENTRANT,
  282. af_open
  283. };